openSUSE Commits
Threads by month
- ----- 2025 -----
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
June 2019
- 1 participants
- 2296 discussions
Hello community,
here is the log from the commit of package yubikey-manager for openSUSE:Factory checked in at 2019-06-30 10:22:09
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/yubikey-manager (Old)
and /work/SRC/openSUSE:Factory/.yubikey-manager.new.4615 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "yubikey-manager"
Sun Jun 30 10:22:09 2019 rev:11 rq:712543 version:3.0.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/yubikey-manager/yubikey-manager.changes 2019-06-18 14:56:18.253404922 +0200
+++ /work/SRC/openSUSE:Factory/.yubikey-manager.new.4615/yubikey-manager.changes 2019-06-30 10:22:26.987708605 +0200
@@ -1,0 +2,10 @@
+Sat Jun 29 20:32:49 UTC 2019 - Karol Babioch <kbabioch(a)suse.com>
+
+- Version 3.0.0 (released 2019-06-24)
+ * Add support for new YubiKey Preview and lightning form factor
+ * FIDO: Support for credential management
+ * OpenPGP: Support for OpenPGP attestation, cardholder certificates and
+ cached touch policies
+ * OTP: Add flag for using numeric keypad when sending digits
+
+-------------------------------------------------------------------
Old:
----
yubikey-manager-2.1.1.tar.gz
yubikey-manager-2.1.1.tar.gz.sig
New:
----
yubikey-manager-3.0.0.tar.gz
yubikey-manager-3.0.0.tar.gz.sig
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ yubikey-manager.spec ++++++
--- /var/tmp/diff_new_pack.t9CyQJ/_old 2019-06-30 10:22:27.447709320 +0200
+++ /var/tmp/diff_new_pack.t9CyQJ/_new 2019-06-30 10:22:27.451709326 +0200
@@ -17,7 +17,7 @@
Name: yubikey-manager
-Version: 2.1.1
+Version: 3.0.0
Release: 0
Summary: Python 3 library and command line tool for configuring a YubiKey
License: BSD-2-Clause
++++++ yubikey-manager-2.1.1.tar.gz -> yubikey-manager-3.0.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey-manager-2.1.1/NEWS new/yubikey-manager-3.0.0/NEWS
--- old/yubikey-manager-2.1.1/NEWS 2019-05-28 09:04:43.000000000 +0200
+++ new/yubikey-manager-3.0.0/NEWS 2019-06-24 09:07:27.000000000 +0200
@@ -1,3 +1,9 @@
+* Version 3.0.0 (released 2019-06-24)
+ ** Add support for new YubiKey Preview and lightning form factor
+ ** FIDO: Support for credential management
+ ** OpenPGP: Support for OpenPGP attestation, cardholder certificates and cached touch policies
+ ** OTP: Add flag for using numeric keypad when sending digits
+
* Version 2.1.1 (released 2019-05-28)
** OTP: Add initial support for uploading Yubico OTP credentials to YubiCloud
** Don't automatically select the U2F applet on YubiKey NEO, it might be blocked by the OS
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey-manager-2.1.1/PKG-INFO new/yubikey-manager-3.0.0/PKG-INFO
--- old/yubikey-manager-2.1.1/PKG-INFO 2019-05-28 10:05:25.000000000 +0200
+++ new/yubikey-manager-3.0.0/PKG-INFO 2019-06-24 09:12:28.000000000 +0200
@@ -1,13 +1,12 @@
-Metadata-Version: 1.2
+Metadata-Version: 1.1
Name: yubikey-manager
-Version: 2.1.1
+Version: 3.0.0
Summary: Tool for managing your YubiKey configuration.
Home-page: https://github.com/Yubico/yubikey-manager
-Author: Dain Nilsson
-Author-email: dain(a)yubico.com
-Maintainer: Yubico Open Source Maintainers
-Maintainer-email: ossmaint(a)yubico.com
+Author: Yubico Open Source Maintainers
+Author-email: ossmaint(a)yubico.com
License: BSD 2 clause
+Description-Content-Type: UNKNOWN
Description: UNKNOWN
Platform: UNKNOWN
Classifier: License :: OSI Approved :: BSD License
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey-manager-2.1.1/man/ykman.1 new/yubikey-manager-3.0.0/man/ykman.1
--- old/yubikey-manager-2.1.1/man/ykman.1 2019-05-28 08:53:55.000000000 +0200
+++ new/yubikey-manager-3.0.0/man/ykman.1 2019-06-24 09:07:27.000000000 +0200
@@ -1,4 +1,4 @@
-.TH YKMAN "1" "May 2019" "ykman 2.1.1" "User Commands"
+.TH YKMAN "1" "June 2019" "ykman 3.0.0" "User Commands"
.SH NAME
ykman \- YubiKey Manager (ykman)
.SH SYNOPSIS
Binary files old/yubikey-manager-2.1.1/test/__pycache__/__init__.cpython-36.pyc and new/yubikey-manager-3.0.0/test/__pycache__/__init__.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.1/test/__pycache__/test_device.cpython-36.pyc and new/yubikey-manager-3.0.0/test/__pycache__/test_device.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.1/test/__pycache__/test_external_libs.cpython-36.pyc and new/yubikey-manager-3.0.0/test/__pycache__/test_external_libs.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.1/test/__pycache__/test_oath.cpython-36.pyc and new/yubikey-manager-3.0.0/test/__pycache__/test_oath.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.1/test/__pycache__/test_piv.cpython-36.pyc and new/yubikey-manager-3.0.0/test/__pycache__/test_piv.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.1/test/__pycache__/test_scancodes.cpython-36.pyc and new/yubikey-manager-3.0.0/test/__pycache__/test_scancodes.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.1/test/__pycache__/test_util.cpython-36.pyc and new/yubikey-manager-3.0.0/test/__pycache__/test_util.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.1/test/__pycache__/util.cpython-36.pyc and new/yubikey-manager-3.0.0/test/__pycache__/util.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.1/test/on_yubikey/__pycache__/__init__.cpython-36.pyc and new/yubikey-manager-3.0.0/test/on_yubikey/__pycache__/__init__.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.1/test/on_yubikey/__pycache__/test_cli_config.cpython-36.pyc and new/yubikey-manager-3.0.0/test/on_yubikey/__pycache__/test_cli_config.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.1/test/on_yubikey/__pycache__/test_cli_misc.cpython-36.pyc and new/yubikey-manager-3.0.0/test/on_yubikey/__pycache__/test_cli_misc.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.1/test/on_yubikey/__pycache__/test_cli_oath.cpython-36.pyc and new/yubikey-manager-3.0.0/test/on_yubikey/__pycache__/test_cli_oath.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.1/test/on_yubikey/__pycache__/test_cli_openpgp.cpython-36.pyc and new/yubikey-manager-3.0.0/test/on_yubikey/__pycache__/test_cli_openpgp.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.1/test/on_yubikey/__pycache__/test_cli_otp.cpython-36.pyc and new/yubikey-manager-3.0.0/test/on_yubikey/__pycache__/test_cli_otp.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.1/test/on_yubikey/__pycache__/test_fips_u2f_commands.cpython-36.pyc and new/yubikey-manager-3.0.0/test/on_yubikey/__pycache__/test_fips_u2f_commands.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.1/test/on_yubikey/__pycache__/test_interfaces.cpython-36.pyc and new/yubikey-manager-3.0.0/test/on_yubikey/__pycache__/test_interfaces.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.1/test/on_yubikey/__pycache__/test_piv.cpython-36.pyc and new/yubikey-manager-3.0.0/test/on_yubikey/__pycache__/test_piv.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.1/test/on_yubikey/__pycache__/util.cpython-36.pyc and new/yubikey-manager-3.0.0/test/on_yubikey/__pycache__/util.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.1/test/on_yubikey/cli_piv/__pycache__/__init__.cpython-36.pyc and new/yubikey-manager-3.0.0/test/on_yubikey/cli_piv/__pycache__/__init__.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.1/test/on_yubikey/cli_piv/__pycache__/test_fips.cpython-36.pyc and new/yubikey-manager-3.0.0/test/on_yubikey/cli_piv/__pycache__/test_fips.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.1/test/on_yubikey/cli_piv/__pycache__/test_generate_cert_and_csr.cpython-36.pyc and new/yubikey-manager-3.0.0/test/on_yubikey/cli_piv/__pycache__/test_generate_cert_and_csr.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.1/test/on_yubikey/cli_piv/__pycache__/test_key_management.cpython-36.pyc and new/yubikey-manager-3.0.0/test/on_yubikey/cli_piv/__pycache__/test_key_management.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.1/test/on_yubikey/cli_piv/__pycache__/test_management_key.cpython-36.pyc and new/yubikey-manager-3.0.0/test/on_yubikey/cli_piv/__pycache__/test_management_key.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.1/test/on_yubikey/cli_piv/__pycache__/test_misc.cpython-36.pyc and new/yubikey-manager-3.0.0/test/on_yubikey/cli_piv/__pycache__/test_misc.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.1/test/on_yubikey/cli_piv/__pycache__/test_pin_puk.cpython-36.pyc and new/yubikey-manager-3.0.0/test/on_yubikey/cli_piv/__pycache__/test_pin_puk.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.1/test/on_yubikey/cli_piv/__pycache__/util.cpython-36.pyc and new/yubikey-manager-3.0.0/test/on_yubikey/cli_piv/__pycache__/util.cpython-36.pyc differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey-manager-2.1.1/test/on_yubikey/cli_piv/test_key_management.py new/yubikey-manager-3.0.0/test/on_yubikey/cli_piv/test_key_management.py
--- old/yubikey-manager-2.1.1/test/on_yubikey/cli_piv/test_key_management.py 2019-04-09 09:39:55.000000000 +0200
+++ new/yubikey-manager-3.0.0/test/on_yubikey/cli_piv/test_key_management.py 2019-06-24 09:07:27.000000000 +0200
@@ -107,7 +107,7 @@
csr = x509.load_pem_x509_csr(output.encode(), default_backend())
self.assertTrue(csr.is_signature_valid)
- def test_import_correct_cert_succeeds_with_pin(self):
+ def test_import_verify_correct_cert_succeeds_with_pin(self):
# Set up a key in the slot and create a certificate for it
public_key_pem = ykman_cli(
'piv', 'generate-key', '9a', '-a', 'ECCP256', '-m',
@@ -122,17 +122,20 @@
with self.assertRaises(SystemExit):
ykman_cli(
- 'piv', 'import-certificate', '9a', '/tmp/test-pub-key.pem',
+ 'piv', 'import-certificate', '--verify',
+ '9a', '/tmp/test-pub-key.pem',
'-m', DEFAULT_MANAGEMENT_KEY)
ykman_cli(
- 'piv', 'import-certificate', '9a', '/tmp/test-pub-key.pem',
+ 'piv', 'import-certificate', '--verify',
+ '9a', '/tmp/test-pub-key.pem',
'-m', DEFAULT_MANAGEMENT_KEY, '-P', DEFAULT_PIN)
ykman_cli(
- 'piv', 'import-certificate', '9a', '/tmp/test-pub-key.pem',
+ 'piv', 'import-certificate', '--verify',
+ '9a', '/tmp/test-pub-key.pem',
'-m', DEFAULT_MANAGEMENT_KEY, input=DEFAULT_PIN)
- def test_import_wrong_cert_fails(self):
+ def test_import_verify_wrong_cert_fails(self):
# Set up a key in the slot and create a certificate for it
public_key_pem = ykman_cli(
'piv', 'generate-key', '9a', '-a', 'ECCP256', '-m',
@@ -153,10 +156,10 @@
with self.assertRaises(SystemExit):
ykman_cli(
- 'piv', 'import-certificate', '9a', '-',
+ 'piv', 'import-certificate', '--verify', '9a', '-',
'-m', DEFAULT_MANAGEMENT_KEY, '-P', DEFAULT_PIN, input=cert_pem)
- def test_import_wrong_cert_can_be_forced(self):
+ def test_import_no_verify_wrong_cert_succeeds(self):
# Set up a key in the slot and create a certificate for it
public_key_pem = ykman_cli(
'piv', 'generate-key', '9a', '-a', 'ECCP256', '-m',
@@ -177,7 +180,7 @@
with self.assertRaises(SystemExit):
ykman_cli(
- 'piv', 'import-certificate', '9a', '-',
+ 'piv', 'import-certificate', '--verify', '9a', '-',
'-m', DEFAULT_MANAGEMENT_KEY, '-P', DEFAULT_PIN, input=cert_pem)
ykman_cli(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey-manager-2.1.1/test/on_yubikey/cli_piv/test_misc.py new/yubikey-manager-3.0.0/test/on_yubikey/cli_piv/test_misc.py
--- old/yubikey-manager-2.1.1/test/on_yubikey/cli_piv/test_misc.py 2019-04-09 09:39:55.000000000 +0200
+++ new/yubikey-manager-3.0.0/test/on_yubikey/cli_piv/test_misc.py 2019-06-24 09:07:27.000000000 +0200
@@ -1,6 +1,7 @@
from ..util import ykman_cli
from .util import PivTestCase, DEFAULT_MANAGEMENT_KEY
+
class Misc(PivTestCase):
def test_info(self):
@@ -14,7 +15,7 @@
def test_write_read_object(self):
ykman_cli(
'piv', 'write-object',
- '-m', DEFAULT_MANAGEMENT_KEY,'0x5f0001',
+ '-m', DEFAULT_MANAGEMENT_KEY, '0x5f0001',
'-', input='test data')
output = ykman_cli('piv', 'read-object', '0x5f0001')
self.assertEquals('test data\n', output)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey-manager-2.1.1/test/on_yubikey/test_cli_misc.py new/yubikey-manager-3.0.0/test/on_yubikey/test_cli_misc.py
--- old/yubikey-manager-2.1.1/test/on_yubikey/test_cli_misc.py 2019-04-09 09:39:55.000000000 +0200
+++ new/yubikey-manager-3.0.0/test/on_yubikey/test_cli_misc.py 2019-06-24 09:07:27.000000000 +0200
@@ -13,7 +13,7 @@
@unittest.skipIf(is_fips(), 'Not applicable to YubiKey FIPS.')
def test_ykman_info_does_not_report_fips_for_non_fips_device(self):
- info = ykman_cli('info --check-fips')
+ info = ykman_cli('info', '--check-fips')
self.assertNotIn('FIPS', info)
@unittest.skipIf(not is_fips(), 'YubiKey FIPS required.')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey-manager-2.1.1/test/test_util.py new/yubikey-manager-3.0.0/test/test_util.py
--- old/yubikey-manager-2.1.1/test/test_util.py 2019-04-09 09:39:55.000000000 +0200
+++ new/yubikey-manager-3.0.0/test/test_util.py 2019-06-24 09:07:27.000000000 +0200
@@ -33,7 +33,7 @@
for l in range(0, 38):
self.assertRegex(
generate_static_pw(l),
- '^[cbdefghijklnrtuvCBDEFGHIJKLNRTUV]{' + '{:d}'.format(l) + '}$')
+ '^[cbdefghijklnrtuvCBDEFGHIJKLNRTUV]{%d}$' % l)
def test_hmac_shorten_key(self):
self.assertEqual(b'short', hmac_shorten_key(b'short', 'sha1'))
@@ -146,15 +146,14 @@
with open_file('rsa_2048_key_cert.pfx') as rsa_2048_key_cert_pfx:
self.assertFalse(is_pem(rsa_2048_key_cert_pfx.read()))
- with open_file('rsa_2048_cert_metadata.pem') as rsa_2048_cert_metadata_pem:
- self.assertTrue(is_pem(rsa_2048_cert_metadata_pem.read()))
+ with open_file('rsa_2048_cert_metadata.pem') as f:
+ self.assertTrue(is_pem(f.read()))
with open_file(
'rsa_2048_key_cert_encrypted.pfx') as \
rsa_2048_key_cert_encrypted_pfx:
self.assertFalse(is_pem(rsa_2048_key_cert_encrypted_pfx.read()))
-
def test_form_factor_from_code(self):
self.assertEqual(FORM_FACTOR.UNKNOWN, FORM_FACTOR.from_code(None))
with self.assertRaises(ValueError):
@@ -166,4 +165,6 @@
self.assertEqual(
FORM_FACTOR.USB_C_KEYCHAIN, FORM_FACTOR.from_code(0x03))
self.assertEqual(FORM_FACTOR.USB_C_NANO, FORM_FACTOR.from_code(0x04))
- self.assertEqual(FORM_FACTOR.UNKNOWN, FORM_FACTOR.from_code(0x05))
+ self.assertEqual(FORM_FACTOR.USB_C_LIGHTNING,
+ FORM_FACTOR.from_code(0x05))
+ self.assertEqual(FORM_FACTOR.UNKNOWN, FORM_FACTOR.from_code(0x06))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey-manager-2.1.1/ykman/VERSION new/yubikey-manager-3.0.0/ykman/VERSION
--- old/yubikey-manager-2.1.1/ykman/VERSION 2019-05-27 12:35:48.000000000 +0200
+++ new/yubikey-manager-3.0.0/ykman/VERSION 2019-06-24 09:07:27.000000000 +0200
@@ -1 +1 @@
-2.1.1
+3.0.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey-manager-2.1.1/ykman/cli/fido.py new/yubikey-manager-3.0.0/ykman/cli/fido.py
--- old/yubikey-manager-2.1.1/ykman/cli/fido.py 2019-05-08 09:19:37.000000000 +0200
+++ new/yubikey-manager-3.0.0/ykman/cli/fido.py 2019-06-24 09:07:27.000000000 +0200
@@ -102,6 +102,74 @@
click.echo('PIN is not set.')
+(a)fido.command('list')
+(a)click.pass_context
+(a)click.option('-P', '--pin', help='PIN code.')
+def list_creds(ctx, pin):
+ """
+ List resident credentials.
+ """
+ controller = ctx.obj['controller']
+
+ if not controller.has_pin:
+ ctx.fail('No PIN set.')
+
+ if controller.has_pin and pin is None:
+ pin = _prompt_current_pin(prompt='Enter your PIN')
+
+ try:
+ for cred in controller.get_resident_credentials(pin):
+ click.echo('{} ({})'.format(cred.user_name, cred.rp_id))
+ except CtapError as e:
+ if e.code == CtapError.ERR.PIN_INVALID:
+ ctx.fail('Wrong PIN.')
+ except Exception as e:
+ logger.debug('Failed to list resident credentials', exc_info=e)
+ ctx.fail('Failed to list resident credentials.')
+
+
+(a)fido.command()
+(a)click.pass_context
+(a)click.argument('query')
+(a)click.option('-P', '--pin', help='PIN code.')
+(a)click.option('-f', '--force', is_flag=True,
+ help='Confirm deletion without prompting')
+def delete(ctx, query, pin, force):
+ """
+ Delete a resident credential.
+ """
+ controller = ctx.obj['controller']
+
+ if not controller.has_pin:
+ ctx.fail('No PIN set.')
+
+ if controller.has_pin and pin is None:
+ pin = _prompt_current_pin(prompt='Enter your PIN')
+
+ try:
+ hits = [
+ cred for cred in controller.get_resident_credentials(pin)
+ if query.lower() in cred.user_name or query.lower() in cred.rp_id
+ ]
+ if len(hits) == 0:
+ ctx.fail('No matches, nothing to be done.')
+ elif len(hits) == 1:
+ cred = hits[0]
+ if force or click.confirm(
+ 'Delete credential {} ({})?'.format(
+ cred.user_name, cred.rp_id)):
+ controller.delete_resident_credential(
+ cred.credential_id, pin)
+ else:
+ ctx.fail('Multiple matches, make the query more specific.')
+ except CtapError as e:
+ if e.code == CtapError.ERR.PIN_INVALID:
+ ctx.fail('Wrong PIN.')
+ except Exception as e:
+ logger.debug('Failed to delete resident credential', exc_info=e)
+ ctx.fail('Failed to delete resident credential.')
+
+
@fido.command('set-pin')
@click.pass_context
@click.option('-P', '--pin', help='Current PIN code.')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey-manager-2.1.1/ykman/cli/opgp.py new/yubikey-manager-3.0.0/ykman/cli/opgp.py
--- old/yubikey-manager-2.1.1/ykman/cli/opgp.py 2019-04-09 09:39:55.000000000 +0200
+++ new/yubikey-manager-3.0.0/ykman/cli/opgp.py 2019-06-24 09:07:27.000000000 +0200
@@ -29,28 +29,17 @@
import logging
import click
-from ..util import TRANSPORT
+from ..util import TRANSPORT, parse_certificates, parse_private_key
from ..opgp import OpgpController, KEY_SLOT, TOUCH_MODE
from ..driver_ccid import APDUError, SW
-from .util import click_force_option, click_postpone_execution
+from .util import (
+ click_force_option, click_format_option, click_postpone_execution,
+ UpperCaseChoice)
logger = logging.getLogger(__name__)
-KEY_NAMES = dict(
- sig=KEY_SLOT.SIGNATURE,
- enc=KEY_SLOT.ENCRYPTION,
- aut=KEY_SLOT.AUTHENTICATION
-)
-
-MODE_NAMES = dict(
- off=TOUCH_MODE.OFF,
- on=TOUCH_MODE.ON,
- fixed=TOUCH_MODE.FIXED
-)
-
-
def one_of(data):
def inner(ctx, param, key):
if key is not None:
@@ -92,7 +81,7 @@
\b
Require touch to use the authentication key:
- $ ykman openpgp touch aut on
+ $ ykman openpgp set-touch aut on
"""
try:
ctx.obj['controller'] = OpgpController(ctx.obj['dev'].driver)
@@ -116,17 +105,23 @@
click.echo('PIN tries remaining: {}'.format(retries.pin))
click.echo('Reset code tries remaining: {}'.format(retries.reset))
click.echo('Admin PIN tries remaining: {}'.format(retries.admin))
- click.echo()
- click.echo('Touch policies')
- click.echo(
- 'Signature key {.name}'.format(
- controller.get_touch(KEY_SLOT.SIGNATURE)))
- click.echo(
- 'Encryption key {.name}'.format(
- controller.get_touch(KEY_SLOT.ENCRYPTION)))
- click.echo(
- 'Authentication key {.name}'.format(
- controller.get_touch(KEY_SLOT.AUTHENTICATION)))
+ # Touch only available on YK4 and later
+ if controller.version >= (4, 2, 6):
+ click.echo()
+ click.echo('Touch policies')
+ click.echo(
+ 'Signature key {!s}'.format(
+ controller.get_touch(KEY_SLOT.SIGNATURE)))
+ click.echo(
+ 'Encryption key {!s}'.format(
+ controller.get_touch(KEY_SLOT.ENCRYPTION)))
+ click.echo(
+ 'Authentication key {!s}'.format(
+ controller.get_touch(KEY_SLOT.AUTHENTICATION)))
+ if controller.supports_attestation:
+ click.echo(
+ 'Attestation key {!s}'.format(
+ controller.get_touch(KEY_SLOT.ATTESTATION)))
@openpgp.command()
@@ -153,63 +148,242 @@
click.echo('Admin PIN: 12345678')
-(a)openpgp.command()
-(a)click.argument('key', metavar='KEY', type=click.Choice(sorted(KEY_NAMES)),
- callback=lambda c, p, k: KEY_NAMES.get(k))
-(a)click.argument('policy', metavar='POLICY', type=click.Choice(sorted(MODE_NAMES)),
- callback=lambda c, p, k: MODE_NAMES.get(k))
-(a)click.option('--admin-pin', required=False, metavar='PIN',
- help='Admin PIN for OpenPGP.')
+(a)openpgp.command('set-touch')
+(a)click.argument(
+ 'key', metavar='KEY', type=UpperCaseChoice(['AUT', 'ENC', 'SIG', 'ATT']),
+ callback=lambda c, p, v: KEY_SLOT(v))
+(a)click.argument(
+ 'policy', metavar='POLICY',
+ type=UpperCaseChoice(['ON', 'OFF', 'FIXED', 'CACHED', 'CACHED-FIXED']),
+ callback=lambda c, p, v: TOUCH_MODE[v.replace('-', '_')])
+(a)click.option('-a', '--admin-pin', help='Admin PIN for OpenPGP.')
@click_force_option
@click.pass_context
-def touch(ctx, key, policy, admin_pin, force):
+def set_touch(ctx, key, policy, admin_pin, force):
"""
- Manage touch policy for OpenPGP keys.
+ Set touch policy for OpenPGP keys.
\b
- KEY Key slot to set (sig, enc or aut).
- POLICY Touch policy to set (on, off or fixed).
+ KEY Key slot to set (sig, enc, aut or att).
+ POLICY Touch policy to set (on, off, fixed, cached or cached-fixed).
"""
controller = ctx.obj['controller']
- old_policy = controller.get_touch(key)
- if old_policy == TOUCH_MODE.FIXED:
- ctx.fail('A FIXED policy cannot be changed!')
-
- force or click.confirm('Set touch policy of {.name} key to {.name}?'.format(
- key, policy), abort=True, err=True)
if admin_pin is None:
admin_pin = click.prompt('Enter admin PIN', hide_input=True, err=True)
- controller.set_touch(key, policy, admin_pin.encode('utf8'))
+
+ policy_name = policy.name.lower().replace('_', '-')
+
+ if policy not in controller.supported_touch_policies:
+ ctx.fail('Touch policy {} not supported.'.format(policy_name))
+
+ if force or click.confirm(
+ 'Set touch policy of {} key to {}?'.format(
+ key.name.lower(),
+ policy_name),
+ abort=True, err=True):
+ try:
+ controller.set_touch(key, policy, admin_pin)
+ except APDUError as e:
+ if e.sw == SW.SECURITY_CONDITION_NOT_SATISFIED:
+ ctx.fail('Touch policy not allowed.')
+ logger.debug('Failed to set touch policy', exc_info=e)
+ ctx.fail('Failed to set touch policy.')
@openpgp.command('set-pin-retries')
-(a)click.argument('pw-attempts', nargs=3, type=click.IntRange(1, 99))
-(a)click.password_option('--admin-pin', metavar='PIN', prompt='Enter admin PIN',
- confirmation_prompt=False)
+(a)click.argument(
+ 'pin-retries', type=click.IntRange(1, 99), metavar='PIN-RETRIES')
+(a)click.argument(
+ 'reset-code-retries',
+ type=click.IntRange(1, 99), metavar='RESET-CODE-RETRIES')
+(a)click.argument(
+ 'admin-pin-retries',
+ type=click.IntRange(1, 99), metavar='ADMIN-PIN-RETRIES')
+(a)click.option('-a', '--admin-pin', help='Admin PIN for OpenPGP.')
@click_force_option
@click.pass_context
-def set_pin_retries(ctx, pw_attempts, admin_pin, force):
+def set_pin_retries(
+ ctx, admin_pin, pin_retries,
+ reset_code_retries, admin_pin_retries, force):
"""
- Manage pin-retries.
-
- Sets the number of attempts available before locking for each PIN.
-
- PW_ATTEMPTS should be three integer values corresponding to the number of
- attempts for the PIN, Reset Code, and Admin PIN, respectively.
+ Set PIN, Reset Code and Admin PIN retries.
"""
controller = ctx.obj['controller']
+
+ if admin_pin is None:
+ admin_pin = click.prompt('Enter admin PIN', hide_input=True, err=True)
+
resets_pins = controller.version < (4, 0, 0)
if resets_pins:
click.echo('WARNING: Setting PIN retries will reset the values for all '
'3 PINs!')
- force or click.confirm('Set PIN retry counters to: {} {} {}?'.format(
- *pw_attempts), abort=True, err=True)
- controller.set_pin_retries(*(pw_attempts + (admin_pin.encode('utf8'),)))
- click.echo('PIN retries successfully set.')
- if resets_pins:
- click.echo('Default PINs are set.')
- echo_default_pins()
+ if force or click.confirm(
+ 'Set PIN retry counters to: {} {} {}?'.format(
+ pin_retries, reset_code_retries,
+ admin_pin_retries), abort=True, err=True):
+
+ controller.set_pin_retries(
+ pin_retries, reset_code_retries, admin_pin_retries, admin_pin)
+
+ if resets_pins:
+ click.echo('Default PINs are set.')
+ echo_default_pins()
+
+
+(a)openpgp.command()
+(a)click.pass_context
+(a)click.option('-P', '--pin', help='PIN code.')
+@click_format_option
+(a)click.argument(
+ 'key', metavar='KEY', type=UpperCaseChoice(['AUT', 'ENC', 'SIG']),
+ callback=lambda c, p, v: KEY_SLOT(v))
+(a)click.argument('certificate', type=click.File('wb'), metavar='CERTIFICATE')
+def attest(ctx, key, certificate, pin, format):
+ """
+ Generate a attestation certificate for a key.
+
+ Attestation is used to show that an asymmetric key was generated on the
+ YubiKey and therefore doesn't exist outside the device.
+
+ \b
+ KEY Key slot to attest (sig, enc, aut).
+ CERTIFICATE File to write attestation certificate to. Use '-' to use stdout.
+ """
+
+ controller = ctx.obj['controller']
+
+ if not pin:
+ pin = click.prompt(
+ 'Enter PIN', default='', hide_input=True,
+ show_default=False, err=True)
+
+ try:
+ cert = controller.read_certificate(key)
+ except ValueError:
+ cert = None
+
+ if not cert or click.confirm(
+ 'There is already data stored in the certificate slot for {}, '
+ 'do you want to overwrite it?'.format(key.name)):
+ touch_policy = controller.get_touch(KEY_SLOT.ATTESTATION)
+ if touch_policy in [TOUCH_MODE.ON, TOUCH_MODE.FIXED]:
+ click.echo('Touch your YubiKey...')
+ try:
+ cert = controller.attest(key, pin)
+ certificate.write(cert.public_bytes(encoding=format))
+ except Exception as e:
+ logger.debug('Failed to attest', exc_info=e)
+ ctx.fail('Attestation failed')
+
+
+(a)openpgp.command('export-certificate')
+(a)click.pass_context
+(a)click.argument(
+ 'key', metavar='KEY', type=UpperCaseChoice(['AUT', 'ENC', 'SIG', 'ATT']),
+ callback=lambda c, p, v: KEY_SLOT(v))
+@click_format_option
+(a)click.argument('certificate', type=click.File('wb'), metavar='CERTIFICATE')
+def export_certificate(ctx, key, format, certificate):
+ """
+ Export an OpenPGP Cardholder certificate.
+
+ \b
+ KEY Key slot to read from (sig, enc, aut, or att).
+ CERTIFICATE File to write certificate to. Use '-' to use stdout.
+ """
+ controller = ctx.obj['controller']
+ try:
+ cert = controller.read_certificate(key)
+ except ValueError:
+ ctx.fail('Failed to read certificate from {}'.format(key.name))
+ certificate.write(cert.public_bytes(encoding=format))
+
+
+(a)openpgp.command('delete-certificate')
+(a)click.option('-a', '--admin-pin', help='Admin PIN for OpenPGP.')
+(a)click.pass_context
+(a)click.argument(
+ 'key', metavar='KEY', type=UpperCaseChoice(['AUT', 'ENC', 'SIG', 'ATT']),
+ callback=lambda c, p, v: KEY_SLOT(v))
+def delete_certificate(ctx, key, admin_pin):
+ """
+ Delete an OpenPGP Cardholder certificate.
+
+ \b
+ KEY Key slot to delete certificate from (sig, enc, aut, or att).
+ """
+ controller = ctx.obj['controller']
+ if admin_pin is None:
+ admin_pin = click.prompt('Enter admin PIN', hide_input=True, err=True)
+ try:
+ controller.delete_certificate(key, admin_pin)
+ except Exception as e:
+ logger.debug('Failed to delete ', exc_info=e)
+ ctx.fail('Failed to delete certificate.')
+
+
+(a)openpgp.command('import-certificate')
+(a)click.option('-a', '--admin-pin', help='Admin PIN for OpenPGP.')
+(a)click.pass_context
+(a)click.argument(
+ 'key', metavar='KEY', type=UpperCaseChoice(['AUT', 'ENC', 'SIG', 'ATT']),
+ callback=lambda c, p, v: KEY_SLOT(v))
+(a)click.argument('cert', type=click.File('rb'), metavar='CERTIFICATE')
+def import_certificate(ctx, key, cert, admin_pin):
+ """
+ Import an OpenPGP Cardholder certificate.
+
+ \b
+ KEY Key slot to import certificate to (sig, enc, aut, or att).
+ CERTIFICATE File containing the certificate. Use '-' to use stdin.
+ """
+ controller = ctx.obj['controller']
+
+ if admin_pin is None:
+ admin_pin = click.prompt('Enter admin PIN', hide_input=True, err=True)
+
+ try:
+ certs = parse_certificates(cert.read(), password=None)
+ except Exception as e:
+ logger.debug('Failed to parse', exc_info=e)
+ ctx.fail('Failed to parse certificate.')
+ if len(certs) != 1:
+ ctx.fail('Can only import one certificate.')
+ try:
+ controller.import_certificate(key, certs[0], admin_pin)
+ except Exception as e:
+ logger.debug('Failed to import', exc_info=e)
+ ctx.fail('Failed to import certificate')
+
+
+(a)openpgp.command('import-attestation-key')
+(a)click.option('-a', '--admin-pin', help='Admin PIN for OpenPGP.')
+(a)click.pass_context
+(a)click.argument('private-key', type=click.File('rb'), metavar='PRIVATE-KEY')
+def import_attestation_key(ctx, private_key, admin_pin):
+ """
+ Import a private attestation key.
+
+ Import a private key for OpenPGP attestation.
+
+ \b
+ PRIVATE-KEY File containing the private key. Use '-' to use stdin.
+ """
+ controller = ctx.obj['controller']
+
+ if admin_pin is None:
+ admin_pin = click.prompt('Enter admin PIN', hide_input=True, err=True)
+ try:
+ private_key = parse_private_key(private_key.read(), password=None)
+ except Exception as e:
+ logger.debug('Failed to parse', exc_info=e)
+ ctx.fail('Failed to parse private key.')
+ try:
+ controller.import_attestation_key(private_key, admin_pin)
+ except Exception as e:
+ logger.debug('Failed to import', exc_info=e)
+ ctx.fail('Failed to import attestation key.')
openpgp.transports = TRANSPORT.CCID
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey-manager-2.1.1/ykman/cli/otp.py new/yubikey-manager-3.0.0/ykman/cli/otp.py
--- old/yubikey-manager-2.1.1/ykman/cli/otp.py 2019-05-27 12:04:25.000000000 +0200
+++ new/yubikey-manager-3.0.0/ykman/cli/otp.py 2019-06-24 09:07:27.000000000 +0200
@@ -36,7 +36,7 @@
from binascii import a2b_hex, b2a_hex
from .. import __version__
from ..driver_otp import YkpersError
-from ..otp import OtpController, PrepareUploadFailed
+from ..otp import OtpController, PrepareUploadFailed, SlotConfig
from ..scancodes import KEYBOARD_LAYOUT
import logging
import os
@@ -339,7 +339,9 @@
abort=True, err=True)
try:
- controller.program_otp(slot, key, public_id, private_id, not no_enter)
+ controller.program_otp(slot, key, public_id, private_id, SlotConfig(
+ append_cr=not no_enter
+ ))
except YkpersError as e:
_failed_to_write_msg(ctx, e)
@@ -394,8 +396,9 @@
if not force:
_confirm_slot_overwrite(controller, slot)
try:
- controller.program_static(
- slot, password, not no_enter, keyboard_layout=keyboard_layout)
+ controller.program_static(slot, password, keyboard_layout, SlotConfig(
+ append_cr=not no_enter
+ ))
except YkpersError as e:
_failed_to_write_msg(ctx, e)
@@ -546,7 +549,9 @@
err=True)
try:
controller.program_hotp(
- slot, key, counter, int(digits) == 8, not no_enter)
+ slot, key, counter, int(digits) == 8, SlotConfig(
+ append_cr=not no_enter
+ ))
except YkpersError as e:
_failed_to_write_msg(ctx, e)
@@ -569,8 +574,11 @@
'-p', '--pacing', type=click.Choice(['0', '20', '40', '60']),
default='0', show_default=True, help='Throttle output speed by '
'adding a delay (in ms) between characters emitted.')
+(a)click.option('--use-numeric-keypad', is_flag=True, show_default=True,
+ help='Use scancodes for numeric keypad when sending digits.'
+ ' Helps with some keyboard layouts. ')
def settings(ctx, slot, new_access_code, delete_access_code, enter, pacing,
- force):
+ use_numeric_keypad, force):
"""
Update the settings for a slot.
@@ -605,7 +613,11 @@
pacing = int(pacing)
try:
- controller.update_settings(slot, enter=enter, pacing=pacing)
+ controller.update_settings(slot, SlotConfig(
+ append_cr=enter,
+ pacing=pacing,
+ numeric_keypad=use_numeric_keypad
+ ))
except YkpersError as e:
_failed_to_write_msg(ctx, e)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey-manager-2.1.1/ykman/cli/piv.py new/yubikey-manager-3.0.0/ykman/cli/piv.py
--- old/yubikey-manager-2.1.1/ykman/cli/piv.py 2019-04-30 12:51:29.000000000 +0200
+++ new/yubikey-manager-3.0.0/ykman/cli/piv.py 2019-06-24 09:07:27.000000000 +0200
@@ -165,9 +165,11 @@
except AttributeError:
print_dn = False
logger.debug('Failed to read DN, falling back to only CNs')
- subject_cn = cert.subject.get_attributes_for_oid(x509.NameOID.COMMON_NAME)
+ subject_cn = cert.subject.get_attributes_for_oid(
+ x509.NameOID.COMMON_NAME)
subject_cn = subject_cn[0].value if subject_cn else 'None'
- issuer_cn = cert.issuer.get_attributes_for_oid(x509.NameOID.COMMON_NAME)
+ issuer_cn = cert.issuer.get_attributes_for_oid(
+ x509.NameOID.COMMON_NAME)
issuer_cn = issuer_cn[0].value if issuer_cn else 'None'
except ValueError as e:
# Malformed certificates may throw ValueError
@@ -823,6 +825,7 @@
show_default=False, hide_input=True, err=True)
controller.unblock_pin(puk, new_pin)
+
@piv.command('read-object')
@click_pin_option
@click.pass_context
@@ -875,8 +878,8 @@
the range 5f0000 - 5fffff.
\b
- OBJECT-ID Id of PIV object in HEX.
- DATA File containing the data to be written. Use '-' to use stdin.
+ OBJECT-ID Id of PIV object in HEX.
+ DATA File containing the data to be written. Use '-' to use stdin.
"""
controller = ctx.obj['controller']
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey-manager-2.1.1/ykman/device.py new/yubikey-manager-3.0.0/ykman/device.py
--- old/yubikey-manager-2.1.1/ykman/device.py 2019-05-27 12:04:25.000000000 +0200
+++ new/yubikey-manager-3.0.0/ykman/device.py 2019-06-24 09:07:27.000000000 +0200
@@ -270,6 +270,7 @@
FORM_FACTOR.USB_A_NANO,
FORM_FACTOR.USB_C_KEYCHAIN,
FORM_FACTOR.USB_C_NANO,
+ FORM_FACTOR.USB_C_LIGHTNING
):
config._set(TAG.NFC_SUPPORTED, 0)
config._set(TAG.NFC_ENABLED, 0)
@@ -284,7 +285,8 @@
if config.nfc_supported:
self.device_name = 'Security Key NFC'
elif self._key_type == YUBIKEY.YK4:
- if (5, 1, 0) > self.version >= (5, 0, 0):
+ if (5, 0, 0) <= self.version < (5, 1, 0) or \
+ self.version in [(5, 2, 0), (5, 2, 1), (5, 2, 2)]:
self.device_name = 'YubiKey Preview'
elif self.version >= (5, 1, 0):
logger.debug('Identified YubiKey 5')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey-manager-2.1.1/ykman/fido.py new/yubikey-manager-3.0.0/ykman/fido.py
--- old/yubikey-manager-2.1.1/ykman/fido.py 2019-04-29 14:32:48.000000000 +0200
+++ new/yubikey-manager-3.0.0/ykman/fido.py 2019-06-24 09:07:27.000000000 +0200
@@ -29,13 +29,35 @@
import six
import time
+import logging
from fido2.ctap1 import CTAP1, ApduError
-from fido2.ctap2 import CTAP2, PinProtocolV1
+from fido2.ctap2 import CTAP2, PinProtocolV1, CredentialManagement
from threading import Timer
from .driver_ccid import SW
from .driver_fido import FIPS_U2F_CMD
+logger = logging.getLogger(__name__)
+
+
+class ResidentCredential(object):
+ def __init__(self, raw_credential, raw_rp):
+ self._raw_credential = raw_credential
+ self._raw_rp = raw_rp
+
+ @property
+ def credential_id(self):
+ return self._raw_credential[CredentialManagement.RESULT.CREDENTIAL_ID]
+
+ @property
+ def rp_id(self):
+ return self._raw_rp[CredentialManagement.RESULT.RP]['id']
+
+ @property
+ def user_name(self):
+ return self._raw_credential[CredentialManagement.RESULT.USER]['name']
+
+
class Fido2Controller(object):
def __init__(self, driver):
@@ -48,6 +70,27 @@
def has_pin(self):
return self._pin
+ def get_resident_credentials(self, pin):
+ _credman = CredentialManagement(
+ self.ctap,
+ self.pin.VERSION,
+ self.pin.get_pin_token(pin))
+
+ for rp in _credman.enumerate_rps():
+ for cred in _credman.enumerate_creds(
+ rp[CredentialManagement.RESULT.RP_ID_HASH]):
+ yield ResidentCredential(cred, rp)
+
+ def delete_resident_credential(self, credential_id, pin):
+ _credman = CredentialManagement(
+ self.ctap,
+ self.pin.VERSION,
+ self.pin.get_pin_token(pin))
+
+ for cred in self.get_resident_credentials(pin):
+ if credential_id == cred.credential_id:
+ _credman.delete_cred(credential_id)
+
def get_pin_retries(self):
return self.pin.get_pin_retries()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey-manager-2.1.1/ykman/opgp.py new/yubikey-manager-3.0.0/ykman/opgp.py
--- old/yubikey-manager-2.1.1/ykman/opgp.py 2019-04-09 09:39:55.000000000 +0200
+++ new/yubikey-manager-3.0.0/ykman/opgp.py 2019-06-24 09:07:27.000000000 +0200
@@ -28,18 +28,62 @@
from __future__ import absolute_import
import six
+import struct
+import logging
from .util import AID
from .driver_ccid import (APDUError, SW, GP_INS_SELECT)
-from enum import IntEnum, unique
-from binascii import b2a_hex
+from enum import Enum, IntEnum, unique
+from binascii import b2a_hex, a2b_hex
from collections import namedtuple
+from cryptography import x509
+from cryptography.utils import int_to_bytes
+from cryptography.hazmat.backends import default_backend
+from cryptography.hazmat.primitives.serialization import Encoding
+from cryptography.hazmat.primitives.asymmetric import rsa, ec
+
+
+logger = logging.getLogger(__name__)
@unique
-class KEY_SLOT(IntEnum): # noqa: N801
- SIGNATURE = 0xd6
- ENCRYPTION = 0xd7
- AUTHENTICATION = 0xd8
+class KEY_SLOT(Enum): # noqa: N801
+ SIGNATURE = 'SIG'
+ ENCRYPTION = 'ENC'
+ AUTHENTICATION = 'AUT'
+ ATTESTATION = 'ATT'
+
+ @property
+ def key_position(self):
+ if self == KEY_SLOT.SIGNATURE:
+ return 0x01
+ if self == KEY_SLOT.ENCRYPTION:
+ return 0x02
+ if self == KEY_SLOT.AUTHENTICATION:
+ return 0x03
+ if self == KEY_SLOT.ATTESTATION:
+ return 0x04
+
+ @property
+ def touch_position(self):
+ if self == KEY_SLOT.SIGNATURE:
+ return 0xd6
+ if self == KEY_SLOT.ENCRYPTION:
+ return 0xd7
+ if self == KEY_SLOT.AUTHENTICATION:
+ return 0xd8
+ if self == KEY_SLOT.ATTESTATION:
+ return 0xd9
+
+ @property
+ def cert_position(self):
+ if self == KEY_SLOT.SIGNATURE:
+ return 0x02
+ if self == KEY_SLOT.ENCRYPTION:
+ return 0x01
+ if self == KEY_SLOT.AUTHENTICATION:
+ return 0x00
+ if self == KEY_SLOT.ATTESTATION:
+ return 0x03
@unique
@@ -47,6 +91,25 @@
OFF = 0x00
ON = 0x01
FIXED = 0x02
+ CACHED = 0x03
+ CACHED_FIXED = 0x04
+
+ def __str__(self):
+ if self == TOUCH_MODE.OFF:
+ return 'Off'
+ elif self == TOUCH_MODE.ON:
+ return 'On'
+ elif self == TOUCH_MODE.FIXED:
+ return 'On (fixed)'
+ elif self == TOUCH_MODE.CACHED:
+ return 'Cached'
+ elif self == TOUCH_MODE.CACHED_FIXED:
+ return 'Cached (fixed)'
+
+
+@unique
+class TAG(IntEnum): # noqa: N801
+ CARDHOLDER_CERTIFICATE = 0x7f
@unique
@@ -58,6 +121,9 @@
TERMINATE = 0xe6
ACTIVATE = 0x44
PUT_DATA = 0xda
+ GET_ATTESTATION = 0xfb
+ SEND_REMAINING = 0xc0
+ SELECT_DATA = 0xa5
PinRetries = namedtuple('PinRetries', ['pin', 'reset', 'admin'])
@@ -92,6 +158,23 @@
return self._driver.send_apdu(cl, ins, p1, p2, data, check)
raise
+ def send_cmd(self, cl, ins, p1=0, p2=0, data=b'', check=SW.OK):
+ while len(data) > 0xff:
+ self._driver.send_apdu(0x10, ins, p1, p2, data[:0xff])
+ data = data[0xff:]
+ resp, sw = self._driver.send_apdu(0, ins, p1, p2, data, check=None)
+
+ while (sw >> 8) == SW.MORE_DATA:
+ more, sw = self._driver.send_apdu(
+ 0, INS.SEND_REMAINING, 0, 0, b'', check=None)
+ resp += more
+
+ if check is None:
+ return resp, sw
+ elif sw != check:
+ raise APDUError(resp, sw)
+ return resp
+
def _read_version(self):
bcd_hex = b2a_hex(self.send_apdu(0, INS.GET_VERSION, 0, 0))
return tuple(int(bcd_hex[i:i+2]) for i in range(0, 6, 2))
@@ -118,32 +201,163 @@
def _verify(self, pw, pin):
try:
+ pin = pin.encode('utf-8')
self.send_apdu(0, INS.VERIFY, 0, pw, pin)
except APDUError:
pw_remaining = self.get_remaining_pin_tries()[pw-PW1]
raise ValueError('Invalid PIN, {} tries remaining.'.format(
pw_remaining))
- def get_touch(self, key_slot):
+ @property
+ def supported_touch_policies(self):
if self.version < (4, 2, 0):
+ return []
+ if self.version < (5, 2, 1):
+ return [TOUCH_MODE.ON, TOUCH_MODE.OFF, TOUCH_MODE.FIXED]
+ if self.version >= (5, 2, 1):
+ return [
+ TOUCH_MODE.ON, TOUCH_MODE.OFF, TOUCH_MODE.FIXED,
+ TOUCH_MODE.CACHED, TOUCH_MODE.CACHED_FIXED]
+
+ @property
+ def supports_attestation(self):
+ return self.version >= (5, 2, 1)
+
+ def get_touch(self, key_slot):
+ if not self.supported_touch_policies:
raise ValueError('Touch policy is available on YubiKey 4 or later.')
- data = self.send_apdu(0, INS.GET_DATA, 0, key_slot)
+ if key_slot == KEY_SLOT.ATTESTATION and not self.supports_attestation:
+ raise ValueError('Attestation key not available on this device.')
+ data = self.send_apdu(0, INS.GET_DATA, 0, key_slot.touch_position)
return TOUCH_MODE(six.indexbytes(data, 0))
- def set_touch(self, key_slot, mode, pin):
- if self.version < (4, 2, 0):
+ def set_touch(self, key_slot, mode, admin_pin):
+ if not self.supported_touch_policies:
raise ValueError('Touch policy is available on YubiKey 4 or later.')
- self._verify(PW3, pin)
- self.send_apdu(0, INS.PUT_DATA, 0, key_slot,
+ if mode not in self.supported_touch_policies:
+ raise ValueError('Touch policy not available on this device.')
+ self._verify(PW3, admin_pin)
+ self.send_apdu(0, INS.PUT_DATA, 0, key_slot.touch_position,
bytes(bytearray([mode, TOUCH_METHOD_BUTTON])))
- def set_pin_retries(self, pw1_tries, pw2_tries, pw3_tries, pin):
+ def set_pin_retries(self, pw1_tries, pw2_tries, pw3_tries, admin_pin):
if self.version < (1, 0, 7): # For YubiKey NEO
raise ValueError('Setting PIN retry counters requires version '
'1.0.7 or later.')
if (4, 0, 0) <= self.version < (4, 3, 1): # For YubiKey 4
raise ValueError('Setting PIN retry counters requires version '
'4.3.1 or later.')
- self._verify(PW3, pin)
+ self._verify(PW3, admin_pin)
self.send_apdu(0, INS.SET_PIN_RETRIES, 0, 0,
bytes(bytearray([pw1_tries, pw2_tries, pw3_tries])))
+
+ def read_certificate(self, key_slot):
+ self.send_cmd(
+ 0, INS.SELECT_DATA, key_slot.cert_position,
+ 0x04, data=a2b_hex('0660045C027F21'))
+ data = self.send_cmd(
+ 0, INS.GET_DATA, TAG.CARDHOLDER_CERTIFICATE, 0x21)
+ if not data:
+ raise ValueError('No certificate found!')
+ return x509.load_der_x509_certificate(data, default_backend())
+
+ def import_certificate(self, key_slot, certificate, admin_pin):
+ self._verify(PW3, admin_pin)
+ cert_data = certificate.public_bytes(Encoding.DER)
+ self.send_cmd(
+ 0, INS.SELECT_DATA, key_slot.cert_position,
+ 0x04, data=a2b_hex('0660045C027F21'))
+ self.send_cmd(
+ 0, INS.PUT_DATA, TAG.CARDHOLDER_CERTIFICATE, 0x21, data=cert_data)
+
+ def _get_key_attributes(self, key):
+ if isinstance(key, rsa.RSAPrivateKey):
+ return struct.pack('>BHHB', 0x01, key.key_size, 32, 0)
+ if isinstance(key, ec.EllipticCurvePrivateKey):
+ return int_to_bytes(
+ self._get_opgp_algo_id_from_ec(
+ key)) + a2b_hex(self._get_oid_from_ec(key))
+ raise ValueError('Not a valid private key!')
+
+ def _get_oid_from_ec(self, key):
+ curve = key.curve.name
+ if curve == 'secp384r1':
+ return '2B81040022'
+ if curve == 'secp256r1':
+ return '2A8648CE3D030107'
+ if curve == 'secp521r1':
+ return '2B81040023'
+ if curve == 'x25519':
+ return '2B060104019755010501'
+ raise ValueError('No OID for curve: ' + curve)
+
+ def _get_opgp_algo_id_from_ec(self, key):
+ curve = key.curve.name
+ if curve in ['secp384r1', 'secp256r1', 'secp521r1']:
+ return 0x13
+ if curve == 'x25519':
+ return 0x16
+ raise ValueError('No Algo ID for curve: ' + curve)
+
+ def _get_key_data(self, key):
+
+ def _der_len(data):
+ ln = len(data)
+ if ln <= 128:
+ res = [ln]
+ elif ln <= 255:
+ res = [0x81, ln]
+ else:
+ res = [0x82, (ln >> 8) & 0xff, ln & 0xff]
+ return bytearray(res)
+
+ private_numbers = key.private_numbers()
+ data = a2b_hex('B603840181')
+
+ if isinstance(key, rsa.RSAPrivateKey):
+ ln = key.key_size // 8 // 2
+ data += b'\x7f\x48\x08\x91\x03\x92\x81\x80\x93\x81\x80\x5f\x48\x82\x01\x03\x01\x00\x01' # noqa: E501
+ data += int_to_bytes(private_numbers.p, ln)
+ data += int_to_bytes(private_numbers.q, ln)
+ return b'\x4d' + _der_len(data) + data
+ elif isinstance(key, ec.EllipticCurvePrivateKey):
+ ln = key.key_size // 8
+ privkey = int_to_bytes(private_numbers.private_value, ln)
+ data += b'\x7f\x48\x02\x92' + _der_len(privkey)
+ data += b'\x5f\x48' + _der_len(privkey) + privkey
+ return b'\x4d' + _der_len(data) + data
+
+ def import_attestation_key(self, key, admin_pin):
+ self._verify(PW3, admin_pin)
+ data = self._get_key_attributes(key)
+ self.send_cmd(0, INS.PUT_DATA, 0, 0xda, data=data)
+ data = self._get_key_data(key)
+ self.send_cmd(0, 0xdb, 0x3f, 0xff, data=data)
+
+ def delete_attestation_key(self, admin_pin):
+ self._verify(PW3, admin_pin)
+ # Delete attestation key by changing the key attributes twice.
+ self.send_cmd(
+ 0, INS.PUT_DATA, 0, 0xda,
+ data=struct.pack('>BHHB', 0x01, 2048, 32, 0))
+ self.send_cmd(
+ 0, INS.PUT_DATA, 0, 0xda,
+ data=struct.pack('>BHHB', 0x01, 4096, 32, 0))
+
+ def delete_certificate(self, key_slot, admin_pin):
+ self._verify(PW3, admin_pin)
+ self.send_cmd(
+ 0, INS.SELECT_DATA, key_slot.cert_position(),
+ 0x04, data=a2b_hex('0660045C027F21'))
+ self.send_apdu(
+ 0, INS.PUT_DATA, TAG.CARDHOLDER_CERTIFICATE, 0x21, data=b'')
+
+ def attest(self, key_slot, pin):
+ self._verify(PW1, pin)
+ self.send_apdu(0x80, INS.GET_ATTESTATION, key_slot.key_position, 0)
+ self.send_cmd(
+ 0, INS.SELECT_DATA, key_slot.cert_position(),
+ 0x04, data=a2b_hex('0660045C027F21'))
+ data = self.send_cmd(
+ 0, INS.GET_DATA, TAG.CARDHOLDER_CERTIFICATE, 0x21)
+ return x509.load_der_x509_certificate(data, default_backend())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey-manager-2.1.1/ykman/otp.py new/yubikey-manager-3.0.0/ykman/otp.py
--- old/yubikey-manager-2.1.1/ykman/otp.py 2019-05-16 09:16:05.000000000 +0200
+++ new/yubikey-manager-3.0.0/ykman/otp.py 2019-06-24 09:07:27.000000000 +0200
@@ -111,6 +111,68 @@
return [e.message() for e in self.errors]
+class SlotConfig(object):
+ def __init__(
+ self,
+ serial_api_visible=True,
+ allow_update=True,
+ append_cr=True,
+ pacing=None,
+ numeric_keypad=False,
+ ):
+ self.serial_api_visible = serial_api_visible
+ self.allow_update = allow_update
+ self.append_cr = append_cr
+ self.pacing = pacing
+ self.numeric_keypad = numeric_keypad
+
+
+class _SlotConfigContext(object):
+
+ def __init__(self, dev, cmd, conf):
+ st = ykpers.ykds_alloc()
+ self.cfg = ykpers.ykp_alloc()
+ try:
+ check(ykpers.yk_get_status(dev, st))
+ ykpers.ykp_configure_version(self.cfg, st)
+ ykpers.ykp_configure_command(self.cfg, cmd)
+ except YkpersError:
+ ykpers.ykp_free_config(self.cfg)
+ raise
+ finally:
+ ykpers.ykds_free(st)
+
+ if conf is None:
+ conf = SlotConfig()
+ self._apply(conf)
+
+ def _apply(self, config):
+ if config.serial_api_visible:
+ check(ykpers.ykp_set_extflag(self.cfg, 'SERIAL_API_VISIBLE'))
+ if config.allow_update:
+ check(ykpers.ykp_set_extflag(self.cfg, 'ALLOW_UPDATE'))
+ if config.append_cr:
+ check(ykpers.ykp_set_tktflag(self.cfg, 'APPEND_CR'))
+
+ # Output speed throttling
+ if config.pacing == 20:
+ check(ykpers.ykp_set_cfgflag(self.cfg, 'PACING_10MS'))
+ elif config.pacing == 40:
+ check(ykpers.ykp_set_cfgflag(self.cfg, 'PACING_20MS'))
+ elif config.pacing == 60:
+ check(ykpers.ykp_set_cfgflag(self.cfg, 'PACING_10MS'))
+ check(ykpers.ykp_set_cfgflag(self.cfg, 'PACING_20MS'))
+
+ if config.numeric_keypad:
+ check(ykpers.ykp_set_extflag(self.cfg, 'USE_NUMERIC_KEYPAD'))
+
+ def __enter__(self):
+ return self.cfg
+
+ def __exit__(self, type, value, traceback):
+ ykpers.ykp_free_config(self.cfg)
+
+
class OtpController(object):
def __init__(self, driver):
@@ -126,30 +188,19 @@
def access_code(self, value):
self._access_code = value
- def _create_cfg(self, cmd):
- st = ykpers.ykds_alloc()
- cfg = ykpers.ykp_alloc()
- try:
- check(ykpers.yk_get_status(self._dev, st))
- ykpers.ykp_configure_version(cfg, st)
- ykpers.ykp_configure_command(cfg, cmd)
- check(ykpers.ykp_set_extflag(cfg, 'SERIAL_API_VISIBLE'))
- check(ykpers.ykp_set_extflag(cfg, 'ALLOW_UPDATE'))
- if self.access_code is not None:
- check(ykpers.ykp_set_access_code(
- cfg, self.access_code, _ACCESS_CODE_LENGTH))
- return cfg
- except YkpersError:
- ykpers.ykp_free_config(cfg)
- raise
- finally:
- ykpers.ykds_free(st)
+ def _create_cfg(self, cmd, conf=None):
+ context = _SlotConfigContext(self._dev, cmd, conf)
+ if self.access_code is not None:
+ check(ykpers.ykp_set_access_code(
+ context.cfg, self.access_code, _ACCESS_CODE_LENGTH))
+
+ return context
@property
def slot_status(self):
return self._driver.slot_status
- def program_otp(self, slot, key, fixed, uid, append_cr=True):
+ def program_otp(self, slot, key, fixed, uid, config=None):
if len(key) != 16:
raise ValueError('key must be 16 bytes')
if len(uid) != 6:
@@ -158,19 +209,16 @@
raise ValueError('public ID must be <= 16 bytes')
cmd = slot_to_cmd(slot)
- cfg = self._create_cfg(cmd)
- try:
+ with self._create_cfg(cmd, config) as cfg:
check(ykpers.ykp_set_fixed(cfg, fixed, len(fixed)))
check(ykpers.ykp_set_uid(cfg, uid, 6))
ykpers.ykp_AES_key_from_raw(cfg, key)
- if append_cr:
- check(ykpers.ykp_set_tktflag(cfg, 'APPEND_CR'))
- check(ykpers.yk_write_command(self._dev,
- ykpers.ykp_core_config(cfg),
- cmd, self.access_code))
- finally:
- ykpers.ykp_free_config(cfg)
+ check(ykpers.yk_write_command(
+ self._dev,
+ ykpers.ykp_core_config(cfg),
+ cmd, self.access_code
+ ))
def prepare_upload_key(self, key, public_id, private_id, serial=None,
user_agent='python-yubikey-manager/' + __version__):
@@ -218,8 +266,13 @@
errors = []
raise PrepareUploadFailed(resp.status, resp_body, errors)
- def program_static(self, slot, password, append_cr=True,
- keyboard_layout=KEYBOARD_LAYOUT.MODHEX):
+ def program_static(
+ self,
+ slot,
+ password,
+ keyboard_layout=KEYBOARD_LAYOUT.MODHEX,
+ config=None
+ ):
pw_len = len(password)
if self._driver.version < (2, 0, 0):
raise ValueError('static password requires YubiKey 2.0.0 or later')
@@ -231,14 +284,9 @@
'maximum of %d characters' % 38)
cmd = slot_to_cmd(slot)
- cfg = self._create_cfg(cmd)
- try:
+ with self._create_cfg(cmd, config) as cfg:
check(ykpers.ykp_set_cfgflag(cfg, 'SHORT_TICKET'))
-
- if append_cr:
- check(ykpers.ykp_set_tktflag(cfg, 'APPEND_CR'))
-
pw_bytes = encode(password, keyboard_layout=keyboard_layout)
if pw_len <= 16: # All in fixed
check(ykpers.ykp_set_fixed(cfg, pw_bytes, pw_len))
@@ -252,10 +300,8 @@
check(ykpers.yk_write_command(
self._dev, ykpers.ykp_core_config(cfg), cmd, self.access_code))
- finally:
- ykpers.ykp_free_config(cfg)
- def program_chalresp(self, slot, key, touch=False):
+ def program_chalresp(self, slot, key, touch=False, config=None):
if self._driver.version < (2, 2, 0):
raise ValueError('challenge-response requires YubiKey 2.2.0 or '
'later')
@@ -263,9 +309,9 @@
if len(key) > 20:
raise ValueError('key lengths >20 bytes not supported')
cmd = slot_to_cmd(slot)
- cfg = self._create_cfg(cmd)
key = key.ljust(20, b'\0') # Pad key to 20 bytes
- try:
+
+ with self._create_cfg(cmd, config) as cfg:
check(ykpers.ykp_set_tktflag(cfg, 'CHAL_RESP'))
check(ykpers.ykp_set_cfgflag(cfg, 'CHAL_HMAC'))
check(ykpers.ykp_set_cfgflag(cfg, 'HMAC_LT64'))
@@ -274,8 +320,6 @@
ykpers.ykp_HMAC_key_from_raw(cfg, key)
check(ykpers.yk_write_command(
self._dev, ykpers.ykp_core_config(cfg), cmd, self.access_code))
- finally:
- ykpers.ykp_free_config(cfg)
def calculate(
self, slot, challenge=None, totp=False,
@@ -323,7 +367,7 @@
else:
return b2a_hex(resp.raw[:20])
- def program_hotp(self, slot, key, imf=0, hotp8=False, append_cr=True):
+ def program_hotp(self, slot, key, imf=0, hotp8=False, config=None):
if self._driver.version < (2, 1, 0):
raise ValueError('HOTP requires YubiKey 2.1.0 or later')
key = hmac_shorten_key(key, 'SHA1')
@@ -333,20 +377,15 @@
if imf % 16 != 0:
raise ValueError('imf must be a multiple of 16')
cmd = slot_to_cmd(slot)
- cfg = self._create_cfg(cmd)
- try:
+ with self._create_cfg(cmd, config) as cfg:
check(ykpers.ykp_set_tktflag(cfg, 'OATH_HOTP'))
check(ykpers.ykp_set_oath_imf(cfg, imf))
if hotp8:
check(ykpers.ykp_set_cfgflag(cfg, 'OATH_HOTP8'))
- if append_cr:
- check(ykpers.ykp_set_tktflag(cfg, 'APPEND_CR'))
ykpers.ykp_HMAC_key_from_raw(cfg, key)
check(ykpers.yk_write_command(
self._dev, ykpers.ykp_core_config(cfg), cmd, self.access_code))
- finally:
- ykpers.ykp_free_config(cfg)
def zap_slot(self, slot):
check(ykpers.yk_write_command(self._dev, None, slot_to_cmd(slot),
@@ -355,12 +394,10 @@
def swap_slots(self):
if self._driver.version < (2, 3, 0):
raise ValueError('swapping slots requires YubiKey 2.3.0 or later')
- cfg = self._create_cfg(SLOT.SWAP)
- try:
+
+ with self._create_cfg(SLOT.SWAP) as cfg:
ycfg = ykpers.ykp_core_config(cfg)
check(ykpers.yk_write_command(self._dev, ycfg, SLOT.SWAP, None))
- finally:
- ykpers.ykp_free_config(cfg)
def configure_ndef_slot(self, slot, prefix='https://my.yubico.com/yk/#'):
ndef = ykpers.ykp_alloc_ndef()
@@ -389,8 +426,7 @@
'code when initially programming the slot instead.')
cmd = slot_to_cmd(slot, update)
- cfg = self._create_cfg(cmd)
- try:
+ with self._create_cfg(cmd) as cfg:
check(ykpers.ykp_set_access_code(
cfg, new_code or _RESET_ACCESS_CODE, _ACCESS_CODE_LENGTH))
ycfg = ykpers.ykp_core_config(cfg)
@@ -399,9 +435,6 @@
self.access_code = new_code
- finally:
- ykpers.ykp_free_config(cfg)
-
def delete_access_code(self, slot):
if self._has_update_access_code_bug:
raise ValueError(
@@ -411,26 +444,11 @@
self.set_access_code(slot, None)
- def update_settings(self, slot, enter=True, pacing=None):
+ def update_settings(self, slot, config=None):
cmd = slot_to_cmd(slot, update=True)
- cfg = self._create_cfg(cmd)
- if enter:
- check(ykpers.ykp_set_tktflag(cfg, 'APPEND_CR'))
-
- # Output speed throttling
- if pacing == 20:
- check(ykpers.ykp_set_cfgflag(cfg, 'PACING_10MS'))
- elif pacing == 40:
- check(ykpers.ykp_set_cfgflag(cfg, 'PACING_20MS'))
- elif pacing == 60:
- check(ykpers.ykp_set_cfgflag(cfg, 'PACING_10MS'))
- check(ykpers.ykp_set_cfgflag(cfg, 'PACING_20MS'))
-
- try:
+ with self._create_cfg(cmd, config) as cfg:
check(ykpers.yk_write_command(
self._dev, ykpers.ykp_core_config(cfg), cmd, self.access_code))
- finally:
- ykpers.ykp_free_config(cfg)
@property
def is_in_fips_mode(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey-manager-2.1.1/ykman/piv.py new/yubikey-manager-3.0.0/ykman/piv.py
--- old/yubikey-manager-2.1.1/ykman/piv.py 2019-04-09 09:39:55.000000000 +0200
+++ new/yubikey-manager-3.0.0/ykman/piv.py 2019-06-24 09:07:27.000000000 +0200
@@ -846,10 +846,18 @@
).public_key(default_backend())
elif algorithm in [ALGO.ECCP256, ALGO.ECCP384]:
curve = ec.SECP256R1 if algorithm == ALGO.ECCP256 else ec.SECP384R1
- return ec.EllipticCurvePublicNumbers.from_encoded_point(
- curve(),
- resp[5:]
- ).public_key(default_backend())
+
+ try:
+ # Added in cryptography 2.5
+ return ec.EllipticCurvePublicKey.from_encoded_point(
+ curve(),
+ resp[5:]
+ )
+ except AttributeError:
+ return ec.EllipticCurvePublicNumbers.from_encoded_point(
+ curve(),
+ resp[5:]
+ ).public_key(default_backend())
raise UnsupportedAlgorithm(
'Invalid algorithm: {}'.format(algorithm),
@@ -949,7 +957,7 @@
raise KeypairMismatch(slot, certificate)
raise
- except InvalidSignature as e:
+ except InvalidSignature:
raise KeypairMismatch(slot, certificate)
self.put_data(OBJ.from_slot(slot), Tlv(TAG.CERTIFICATE, cert_data) +
@@ -1010,10 +1018,10 @@
def update_chuid(self):
# Non-Federal Issuer FASC-N
# [9999-9999-999999-0-1-0000000000300001]
- FASC_N=b'\xd4\xe7\x39\xda\x73\x9c\xed\x39\xce\x73\x9d\x83\x68' + \
- b'\x58\x21\x08\x42\x10\x84\x21\xc8\x42\x10\xc3\xeb'
+ FASC_N = b'\xd4\xe7\x39\xda\x73\x9c\xed\x39\xce\x73\x9d\x83\x68' + \
+ b'\x58\x21\x08\x42\x10\x84\x21\xc8\x42\x10\xc3\xeb'
# Expires on: 2030-01-01
- EXPIRY=b'\x32\x30\x33\x30\x30\x31\x30\x31'
+ EXPIRY = b'\x32\x30\x33\x30\x30\x31\x30\x31'
self.put_data(
OBJ.CHUID,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey-manager-2.1.1/ykman/util.py new/yubikey-manager-3.0.0/ykman/util.py
--- old/yubikey-manager-2.1.1/ykman/util.py 2019-05-27 10:21:11.000000000 +0200
+++ new/yubikey-manager-3.0.0/ykman/util.py 2019-06-24 09:07:27.000000000 +0200
@@ -111,6 +111,7 @@
USB_A_NANO = 0x02
USB_C_KEYCHAIN = 0x03
USB_C_NANO = 0x04
+ USB_C_LIGHTNING = 0x05
def __str__(self):
if self == FORM_FACTOR.USB_A_KEYCHAIN:
@@ -121,6 +122,8 @@
return 'Keychain (USB-C)'
elif self == FORM_FACTOR.USB_C_NANO:
return 'Nano (USB-C)'
+ elif self == FORM_FACTOR.USB_C_LIGHTNING:
+ return 'Keychain (USB-C, Lightning)'
elif self == FORM_FACTOR.UNKNOWN:
return 'Unknown.'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey-manager-2.1.1/yubikey_manager.egg-info/PKG-INFO new/yubikey-manager-3.0.0/yubikey_manager.egg-info/PKG-INFO
--- old/yubikey-manager-2.1.1/yubikey_manager.egg-info/PKG-INFO 2019-05-28 10:05:25.000000000 +0200
+++ new/yubikey-manager-3.0.0/yubikey_manager.egg-info/PKG-INFO 2019-06-24 09:12:28.000000000 +0200
@@ -1,13 +1,12 @@
-Metadata-Version: 1.2
+Metadata-Version: 1.1
Name: yubikey-manager
-Version: 2.1.1
+Version: 3.0.0
Summary: Tool for managing your YubiKey configuration.
Home-page: https://github.com/Yubico/yubikey-manager
-Author: Dain Nilsson
-Author-email: dain(a)yubico.com
-Maintainer: Yubico Open Source Maintainers
-Maintainer-email: ossmaint(a)yubico.com
+Author: Yubico Open Source Maintainers
+Author-email: ossmaint(a)yubico.com
License: BSD 2 clause
+Description-Content-Type: UNKNOWN
Description: UNKNOWN
Platform: UNKNOWN
Classifier: License :: OSI Approved :: BSD License
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey-manager-2.1.1/yubikey_manager.egg-info/SOURCES.txt new/yubikey-manager-3.0.0/yubikey_manager.egg-info/SOURCES.txt
--- old/yubikey-manager-2.1.1/yubikey_manager.egg-info/SOURCES.txt 2019-05-28 10:05:25.000000000 +0200
+++ new/yubikey-manager-3.0.0/yubikey_manager.egg-info/SOURCES.txt 2019-06-24 09:12:28.000000000 +0200
@@ -14,6 +14,14 @@
test/test_scancodes.py
test/test_util.py
test/util.py
+test/__pycache__/__init__.cpython-36.pyc
+test/__pycache__/test_device.cpython-36.pyc
+test/__pycache__/test_external_libs.cpython-36.pyc
+test/__pycache__/test_oath.cpython-36.pyc
+test/__pycache__/test_piv.cpython-36.pyc
+test/__pycache__/test_scancodes.cpython-36.pyc
+test/__pycache__/test_util.cpython-36.pyc
+test/__pycache__/util.cpython-36.pyc
test/files/rsa_1024_key.pem
test/files/rsa_2048_cert.der
test/files/rsa_2048_cert.pem
@@ -32,6 +40,16 @@
test/on_yubikey/test_interfaces.py
test/on_yubikey/test_piv.py
test/on_yubikey/util.py
+test/on_yubikey/__pycache__/__init__.cpython-36.pyc
+test/on_yubikey/__pycache__/test_cli_config.cpython-36.pyc
+test/on_yubikey/__pycache__/test_cli_misc.cpython-36.pyc
+test/on_yubikey/__pycache__/test_cli_oath.cpython-36.pyc
+test/on_yubikey/__pycache__/test_cli_openpgp.cpython-36.pyc
+test/on_yubikey/__pycache__/test_cli_otp.cpython-36.pyc
+test/on_yubikey/__pycache__/test_fips_u2f_commands.cpython-36.pyc
+test/on_yubikey/__pycache__/test_interfaces.cpython-36.pyc
+test/on_yubikey/__pycache__/test_piv.cpython-36.pyc
+test/on_yubikey/__pycache__/util.cpython-36.pyc
test/on_yubikey/cli_piv/__init__.py
test/on_yubikey/cli_piv/test_fips.py
test/on_yubikey/cli_piv/test_generate_cert_and_csr.py
@@ -40,6 +58,14 @@
test/on_yubikey/cli_piv/test_misc.py
test/on_yubikey/cli_piv/test_pin_puk.py
test/on_yubikey/cli_piv/util.py
+test/on_yubikey/cli_piv/__pycache__/__init__.cpython-36.pyc
+test/on_yubikey/cli_piv/__pycache__/test_fips.cpython-36.pyc
+test/on_yubikey/cli_piv/__pycache__/test_generate_cert_and_csr.cpython-36.pyc
+test/on_yubikey/cli_piv/__pycache__/test_key_management.cpython-36.pyc
+test/on_yubikey/cli_piv/__pycache__/test_management_key.cpython-36.pyc
+test/on_yubikey/cli_piv/__pycache__/test_misc.cpython-36.pyc
+test/on_yubikey/cli_piv/__pycache__/test_pin_puk.cpython-36.pyc
+test/on_yubikey/cli_piv/__pycache__/util.cpython-36.pyc
ykman/VERSION
ykman/__init__.py
ykman/descriptor.py
1
0
Hello community,
here is the log from the commit of package perl-Mojolicious for openSUSE:Factory checked in at 2019-06-30 10:22:05
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/perl-Mojolicious (Old)
and /work/SRC/openSUSE:Factory/.perl-Mojolicious.new.4615 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "perl-Mojolicious"
Sun Jun 30 10:22:05 2019 rev:111 rq:712541 version:8.18
Changes:
--------
--- /work/SRC/openSUSE:Factory/perl-Mojolicious/perl-Mojolicious.changes 2019-05-25 13:20:49.180323516 +0200
+++ /work/SRC/openSUSE:Factory/.perl-Mojolicious.new.4615/perl-Mojolicious.changes 2019-06-30 10:22:23.883703782 +0200
@@ -1,0 +2,29 @@
+Sat Jun 29 05:17:39 UTC 2019 - Stephan Kulow <coolo(a)suse.com>
+
+- updated to 8.18
+ see /usr/share/doc/packages/perl-Mojolicious/Changes
+
+ 8.18 2019-06-28
+ - Welcome to the Mojolicious core team CandyAngel, Christopher Rasch-Olsen
+ Raa and Dan Book.
+ - Deprecated the use of the config stash value and $config variable in
+ templates by Mojolicious::Plugin::Config. You can use the config helper
+ instead. Unfortunately there is no good way to warn users, so this
+ deprecation will be in effect until the next major release.
+ - Deprecated Mojo::Collection::slice since nobody remembers anymore what its
+ intended purpose was.
+ - Added EXPERIMENTAL proxy->get_p, proxy->post_p and proxy->start_p helpers to
+ Mojolicious::Plugin::DefaultHelpers.
+ - Added EXPERIMENTAL dehop method to Mojo::Headers.
+ - Added EXPERIMENTAL bytes_waiting and can_write methods to
+ Mojo::IOLoop::Stream.
+ - Added EXPERIMENTAL high_water_mark attribute to Mojo::IOLoop::Stream.
+ - Updated bundled TLS certificate.
+ - Improved Mojo::Base flags not to require a certain order.
+ - Improved clone performance in Mojo::Headers by 100%.
+ - Improved streaming response performance slightly.
+ - Fixed a typo in the 425 status message in Mojo::Message::Response.
+ (CandyAngel)
+ - Fixed a missing deprecation warning in Mojo::Promise. (marcus)
+
+-------------------------------------------------------------------
Old:
----
Mojolicious-8.17.tar.gz
New:
----
Mojolicious-8.18.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ perl-Mojolicious.spec ++++++
--- /var/tmp/diff_new_pack.xa02wa/_old 2019-06-30 10:22:24.407704597 +0200
+++ /var/tmp/diff_new_pack.xa02wa/_new 2019-06-30 10:22:24.411704603 +0200
@@ -17,7 +17,7 @@
Name: perl-Mojolicious
-Version: 8.17
+Version: 8.18
Release: 0
%define cpan_name Mojolicious
Summary: Real-time web framework
++++++ Mojolicious-8.17.tar.gz -> Mojolicious-8.18.tar.gz ++++++
++++ 2177 lines of diff (skipped)
1
0
Hello community,
here is the log from the commit of package irssi for openSUSE:Factory checked in at 2019-06-30 10:22:03
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/irssi (Old)
and /work/SRC/openSUSE:Factory/.irssi.new.4615 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "irssi"
Sun Jun 30 10:22:03 2019 rev:55 rq:712533 version:1.2.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/irssi/irssi.changes 2019-02-27 17:27:40.999352315 +0100
+++ /work/SRC/openSUSE:Factory/.irssi.new.4615/irssi.changes 2019-06-30 10:22:09.839681965 +0200
@@ -1,0 +2,20 @@
+Fri Jun 28 21:27:15 UTC 2019 - Ailin Nemui <ailin.nemui(a)gmail.com>
+
+- update to 1.2.1
+ ! Contains all changes from 1.1.3
+ ! Contains all changes from 1.0.8
+ - Fix a test on big endian machines (#1014)
+ - Fix the compile time conditionality of wcwidth
+ implementation (#1019, gentoo#677804, #720)
+ - Fix /save no longer working on old Solaris (pre
+ POSIX.1-2008) (#1042, #1043)
+ - Fix regression of #764 where display of 8-bit (legacy
+ encoding) in the input prompt was broken (#1018,
+ #1057). Initial patch by Артём Курашов
+ - Fix regression of #779 where autolog_ignore_targets would
+ not matching itemless windows anymore (#1012, #1013)
+ - Fix a use after free issue when sending the SASL login on
+ (automatic and manual) reconnects (#1055, #1058). Reported
+ by ilbelkyr. CVE-2019-13045
+
+-------------------------------------------------------------------
Old:
----
irssi-1.2.0.tar.xz
irssi-1.2.0.tar.xz.asc
New:
----
irssi-1.2.1.tar.xz
irssi-1.2.1.tar.xz.asc
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ irssi.spec ++++++
--- /var/tmp/diff_new_pack.ZoGuCm/_old 2019-06-30 10:22:11.539684606 +0200
+++ /var/tmp/diff_new_pack.ZoGuCm/_new 2019-06-30 10:22:11.567684649 +0200
@@ -18,7 +18,7 @@
%bcond_with socks
Name: irssi
-Version: 1.2.0
+Version: 1.2.1
Release: 0
Summary: Modular IRC Client
License: GPL-2.0-or-later
++++++ irssi-1.2.0.tar.xz -> irssi-1.2.1.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/irssi-1.2.0/ChangeLog new/irssi-1.2.1/ChangeLog
--- old/irssi-1.2.0/ChangeLog 2019-02-11 18:35:23.000000000 +0100
+++ new/irssi-1.2.1/ChangeLog 2019-06-28 13:54:31.000000000 +0200
@@ -1,3 +1,69 @@
+commit 248a1591a26e0bf3fda3545fe54ebd0c27f4419d
+Author: Ailin Nemui <ailin(a)z30a.localdomain>
+Date: Fri Jun 28 13:52:47 2019 +0200
+
+ tag as 1.2.1
+
+commit 27c02a2d961e83e5c509bbcaca3e01825bfbc9df
+Author: ailin-nemui <ailin-nemui(a)users.noreply.github.com>
+Date: Fri Jun 28 11:28:30 2019 +0200
+
+ Merge pull request #1058 from ailin-nemui/sasl-reconnect
+
+ copy sasl username and password values
+
+ (cherry picked from commit d23b0d22cc611e43c88d99192a59f413f951a955)
+
+commit bb7e81438dd0a0822bb7d140881e858365d392cd
+Author: ailin-nemui <ailin-nemui(a)users.noreply.github.com>
+Date: Mon Feb 18 09:36:34 2019 +0100
+
+ Merge pull request #1013 from ailin-nemui/fix-1012
+
+ do not stop autolog_ignore_targets from matching itemless targets
+
+ (cherry picked from commit df532d4461fa0e1aba8672fa6d56e3056ce52272)
+
+commit fddcbe56c9c0f97ecea73ab9e39787f02ba72a68
+Author: ailin-nemui <ailin-nemui(a)users.noreply.github.com>
+Date: Fri Jun 28 11:29:19 2019 +0200
+
+ Merge pull request #1057 from ailin-nemui/entry-8bit
+
+ restore 8bit support in input entry
+
+ (cherry picked from commit 8551dd99cc6ad29b1b356acc4f4c92209ed98eed)
+
+commit 309ea8825281b1eb30f78c009df4f11611223513
+Author: ailin-nemui <ailin-nemui(a)users.noreply.github.com>
+Date: Mon May 13 15:26:21 2019 +0200
+
+ Merge pull request #1043 from ailin-nemui/solaris10
+
+ fix realpath on old solaris
+
+ (cherry picked from commit 7654f30d04f2b4fae7b49f8b1579bdf77dfca900)
+
+commit 24547829e7c7c9b6cf41d38c672a64cf1b9fd1a2
+Author: ailin-nemui <ailin-nemui(a)users.noreply.github.com>
+Date: Wed Feb 27 13:00:22 2019 +0100
+
+ Merge pull request #1019 from ailin-nemui/configure-utf8proc
+
+ make utf8proc configurable
+
+ (cherry picked from commit 6242d25055520a0abcdd95cbf969479c99d36700)
+
+commit bb600a65753aa34e7c41b59c3d5dcfdcd48bda4f
+Author: ailin-nemui <ailin-nemui(a)users.noreply.github.com>
+Date: Tue Feb 19 07:22:06 2019 +0100
+
+ Merge pull request #1014 from ailin-nemui/fix-be64
+
+ fix test on Big Endian 64bit, due to pointer size mismatch
+
+ (cherry picked from commit 01ce66c684b66860b9c0dae04912d7cf3ebb9aeb)
+
commit bd2ff8c99c41f35430a945e888db828a9925dce7
Author: ailin-nemui <ailin-nemui(a)users.noreply.github.com>
Date: Mon Feb 11 18:05:57 2019 +0100
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/irssi-1.2.0/NEWS new/irssi-1.2.1/NEWS
--- old/irssi-1.2.0/NEWS 2019-02-11 18:35:17.000000000 +0100
+++ new/irssi-1.2.1/NEWS 2019-06-28 13:52:07.000000000 +0200
@@ -1,3 +1,24 @@
+v1.2.1 2019-06-29 The Irssi team <staff(a)irssi.org>
+ ! Contains all changes from 1.1.3
+ - Fix a test on big endian machines (#1014)
+ - Fix the compile time conditionality of wcwidth
+ implementation (#1019, gentoo#677804, #720)
+ - Fix /save no longer working on old Solaris (pre
+ POSIX.1-2008) (#1042, #1043)
+ - Fix regression of #764 where display of 8-bit (legacy
+ encoding) in the input prompt was broken (#1018,
+ #1057). Initial patch by Артём Курашов
+
+v1.1.3 2019-06-29 The Irssi team <staff(a)irssi.org>
+ ! Contains all changes from 1.0.8
+ - Fix regression of #779 where autolog_ignore_targets would
+ not matching itemless windows anymore (#1012, #1013)
+
+v1.0.8 2019-06-29 The Irssi team <staff(a)irssi.org>
+ - Fix a use after free issue when sending the SASL login on
+ (automatic and manual) reconnects (#1055, #1058). Reported
+ by ilbelkyr
+
v1.2.0 2019-02-11 The Irssi team <staff(a)irssi.org>
! Contains all changes from 1.1.2
* Improved the /STATUSBAR commands (#858)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/irssi-1.2.0/configure new/irssi-1.2.1/configure
--- old/irssi-1.2.0/configure 2019-02-11 18:35:30.000000000 +0100
+++ new/irssi-1.2.1/configure 2019-06-28 13:54:40.000000000 +0200
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for irssi 1.2.0.
+# Generated by GNU Autoconf 2.69 for irssi 1.2.1.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -587,8 +587,8 @@
# Identity of this package.
PACKAGE_NAME='irssi'
PACKAGE_TARNAME='irssi'
-PACKAGE_VERSION='1.2.0'
-PACKAGE_STRING='irssi 1.2.0'
+PACKAGE_VERSION='1.2.1'
+PACKAGE_STRING='irssi 1.2.1'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -843,6 +843,7 @@
with_otr
enable_true_color
enable_gregex
+enable_utf8proc
with_capsicum
enable_glibtest
enable_installed_tests
@@ -1406,7 +1407,7 @@
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures irssi 1.2.0 to adapt to many kinds of systems.
+\`configure' configures irssi 1.2.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1476,7 +1477,7 @@
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of irssi 1.2.0:";;
+ short | recursive ) echo "Configuration of irssi 1.2.1:";;
esac
cat <<\_ACEOF
@@ -1501,6 +1502,7 @@
--disable-largefile omit support for large files
--enable-true-color Build with true color support in terminal
--disable-gregex Build without GRegex (fall back to regex.h)
+ --disable-utf8proc Build without Julia's utf8proc
--disable-glibtest do not try to compile and run a test GLIB program
--enable-installed-tests
Enable installation of some test cases
@@ -1628,7 +1630,7 @@
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-irssi configure 1.2.0
+irssi configure 1.2.1
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2230,7 +2232,7 @@
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by irssi $as_me 1.2.0, which was
+It was created by irssi $as_me 1.2.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -3099,7 +3101,7 @@
# Define the identity of the package.
PACKAGE='irssi'
- VERSION='1.2.0'
+ VERSION='1.2.1'
# Some tools Automake needs.
@@ -12866,6 +12868,18 @@
fi
+# Check whether --enable-utf8proc was given.
+if test "${enable_utf8proc+set}" = set; then :
+ enableval=$enable_utf8proc; if test x$enableval = xno ; then
+ want_utf8proc=no
+ else
+ want_utf8proc=yes
+ fi
+else
+ want_utf8proc=yes
+fi
+
+
# Check whether --with-capsicum was given.
if test "${with_capsicum+set}" = set; then :
@@ -13859,7 +13873,11 @@
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for utf8proc_version in -lutf8proc" >&5
+if test "x$want_utf8proc" != "xno"; then
+ ac_fn_c_check_header_mongrel "$LINENO" "utf8proc.h" "ac_cv_header_utf8proc_h" "$ac_includes_default"
+if test "x$ac_cv_header_utf8proc_h" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for utf8proc_version in -lutf8proc" >&5
$as_echo_n "checking for utf8proc_version in -lutf8proc... " >&6; }
if ${ac_cv_lib_utf8proc_utf8proc_version+:} false; then :
$as_echo_n "(cached) " >&6
@@ -13896,15 +13914,26 @@
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_utf8proc_utf8proc_version" >&5
$as_echo "$ac_cv_lib_utf8proc_utf8proc_version" >&6; }
if test "x$ac_cv_lib_utf8proc_utf8proc_version" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBUTF8PROC 1
-_ACEOF
- LIBS="-lutf8proc $LIBS"
+ want_utf8proc=yes
+ LIBS="$LIBS -lutf8proc"
+
+else
+
+ want_utf8proc="no, library not found"
+
+fi
+
+
+else
+
+ want_utf8proc="no, library header not found"
fi
+fi
+
if test "x$want_textui" != "xno"; then
@@ -15364,7 +15393,7 @@
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by irssi $as_me 1.2.0, which was
+This file was extended by irssi $as_me 1.2.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -15430,7 +15459,7 @@
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-irssi config.status 1.2.0
+irssi config.status 1.2.1
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
@@ -17232,7 +17261,7 @@
echo "Building with true color support.. : $want_truecolor"
echo "Building with GRegex ............. : $want_gregex"
echo "Building with Capsicum ........... : $want_capsicum"
-echo "Building with utf8proc ........... : $ac_cv_lib_utf8proc_utf8proc_version"
+echo "Building with utf8proc ........... : $want_utf8proc"
if test "x$want_otr" = "xstatic"; then
echo "Building with OTR support ........ : static (in irssi binary)"
elif test "x$want_otr" = "xmodule"; then
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/irssi-1.2.0/configure.ac new/irssi-1.2.1/configure.ac
--- old/irssi-1.2.0/configure.ac 2019-02-11 18:35:17.000000000 +0100
+++ new/irssi-1.2.1/configure.ac 2019-06-28 13:50:42.000000000 +0200
@@ -1,4 +1,4 @@
-AC_INIT(irssi, 1.2.0)
+AC_INIT(irssi, 1.2.1)
AC_CONFIG_SRCDIR([src])
AC_CONFIG_AUX_DIR(build-aux)
AC_PREREQ(2.50)
@@ -181,6 +181,15 @@
fi,
want_gregex=yes)
+AC_ARG_ENABLE(utf8proc,
+[ --disable-utf8proc Build without Julia's utf8proc],
+ if test x$enableval = xno ; then
+ want_utf8proc=no
+ else
+ want_utf8proc=yes
+ fi,
+ want_utf8proc=yes)
+
AC_ARG_WITH(capsicum,
[ --with-capsicum Build with Capsicum support],
if test x$withval = xno; then
@@ -329,7 +338,18 @@
dnl **
dnl ** utf8proc
dnl **
-AC_CHECK_LIB([utf8proc], [utf8proc_version])
+if test "x$want_utf8proc" != "xno"; then
+ AC_CHECK_HEADER([utf8proc.h], [
+ AC_CHECK_LIB([utf8proc], [utf8proc_version], [
+ want_utf8proc=yes
+ LIBS="$LIBS -lutf8proc"
+ ], [
+ want_utf8proc="no, library not found"
+ ])
+ ], [
+ want_utf8proc="no, library header not found"
+ ])
+fi
dnl **
dnl ** curses checks
@@ -821,7 +841,7 @@
echo "Building with true color support.. : $want_truecolor"
echo "Building with GRegex ............. : $want_gregex"
echo "Building with Capsicum ........... : $want_capsicum"
-echo "Building with utf8proc ........... : $ac_cv_lib_utf8proc_utf8proc_version"
+echo "Building with utf8proc ........... : $want_utf8proc"
if test "x$want_otr" = "xstatic"; then
echo "Building with OTR support ........ : static (in irssi binary)"
elif test "x$want_otr" = "xmodule"; then
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/irssi-1.2.0/irssi-config.h new/irssi-1.2.1/irssi-config.h
--- old/irssi-1.2.0/irssi-config.h 2019-02-11 18:35:39.000000000 +0100
+++ new/irssi-1.2.1/irssi-config.h 2019-06-28 13:54:51.000000000 +0200
@@ -17,10 +17,7 @@
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the `otr' library (-lotr). */
-#define HAVE_LIBOTR 1
-
-/* Define to 1 if you have the `utf8proc' library (-lutf8proc). */
-#define HAVE_LIBUTF8PROC 1
+/* #undef HAVE_LIBOTR */
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
@@ -35,7 +32,7 @@
/* #undef HAVE_STATIC_OTR */
/* */
-/* #undef HAVE_STATIC_PERL */
+#define HAVE_STATIC_PERL 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
@@ -83,7 +80,7 @@
#define PACKAGE_NAME "irssi"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "irssi 1.2.0"
+#define PACKAGE_STRING "irssi 1.2.1"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "irssi"
@@ -92,7 +89,7 @@
#define PACKAGE_URL ""
/* Define to the version of this package. */
-#define PACKAGE_VERSION "1.2.0"
+#define PACKAGE_VERSION "1.2.1"
/* printf()-format for uoff_t, eg. "u" or "lu" or "llu" */
#define PRIuUOFF_T "lu"
@@ -113,7 +110,7 @@
#define STDC_HEADERS 1
/* true color support in terminal */
-#define TERM_TRUECOLOR /**/
+/* #undef TERM_TRUECOLOR */
/* What type should be used for uoff_t */
/* #undef UOFF_T_INT */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/irssi-1.2.0/irssi-config.h.in new/irssi-1.2.1/irssi-config.h.in
--- old/irssi-1.2.0/irssi-config.h.in 2019-02-11 18:35:30.000000000 +0100
+++ new/irssi-1.2.1/irssi-config.h.in 2019-06-28 13:54:40.000000000 +0200
@@ -18,9 +18,6 @@
/* Define to 1 if you have the `otr' library (-lotr). */
#undef HAVE_LIBOTR
-/* Define to 1 if you have the `utf8proc' library (-lutf8proc). */
-#undef HAVE_LIBUTF8PROC
-
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/irssi-1.2.0/irssi-version.h new/irssi-1.2.1/irssi-version.h
--- old/irssi-1.2.0/irssi-version.h 2019-02-11 18:35:42.000000000 +0100
+++ new/irssi-1.2.1/irssi-version.h 2019-06-28 13:54:57.000000000 +0200
@@ -1,2 +1,2 @@
-#define IRSSI_VERSION_DATE 20190211
-#define IRSSI_VERSION_TIME 1805
+#define IRSSI_VERSION_DATE 20190628
+#define IRSSI_VERSION_TIME 1352
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/irssi-1.2.0/src/fe-common/core/fe-common-core.c new/irssi-1.2.1/src/fe-common/core/fe-common-core.c
--- old/irssi-1.2.0/src/fe-common/core/fe-common-core.c 2019-02-11 18:27:58.000000000 +0100
+++ new/irssi-1.2.1/src/fe-common/core/fe-common-core.c 2019-06-28 13:42:49.000000000 +0200
@@ -486,9 +486,6 @@
strarray_find(array, dest->window->name) != -1 ? TRUE : FALSE;
item = window_item_find_window(dest->window, dest->server, dest->target);
- if (item == NULL) {
- return FALSE;
- }
server_tag_len = dest->server_tag != NULL ? strlen(dest->server_tag) : 0;
for (tmp = array; *tmp != NULL; tmp++) {
@@ -507,11 +504,11 @@
return TRUE;
} else if (g_ascii_strcasecmp(str, dest->target) == 0) {
return TRUE;
- } else if (item->type == query_type &&
+ } else if (item != NULL && item->type == query_type &&
g_strcmp0(str, dest->target[0] == '=' ? "::dccqueries" :
"::queries") == 0) {
return TRUE;
- } else if (item->type == channel_type &&
+ } else if (item != NULL && item->type == channel_type &&
g_strcmp0(str, "::channels") == 0) {
return TRUE;
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/irssi-1.2.0/src/fe-text/gui-entry.c new/irssi-1.2.1/src/fe-text/gui-entry.c
--- old/irssi-1.2.0/src/fe-text/gui-entry.c 2019-02-11 18:27:58.000000000 +0100
+++ new/irssi-1.2.1/src/fe-text/gui-entry.c 2019-06-28 11:53:32.000000000 +0200
@@ -379,11 +379,19 @@
if (new_xpos > end_xpos)
break;
- if (entry->hidden)
+ if (entry->hidden) {
g_string_append_c(str, ' ');
- else if (unichar_isprint(c))
- g_string_append_unichar(str, c);
- else {
+ } else if (unichar_isprint(c)) {
+ if (entry->utf8) {
+ g_string_append_unichar(str, c);
+ } else if (term_type == TERM_TYPE_BIG5) {
+ if(c > 0xff)
+ g_string_append_c(str, (c >> 8) & 0xff);
+ g_string_append_c(str, c & 0xff);
+ } else {
+ g_string_append_c(str, c);
+ }
+ } else {
g_string_append_c(str, 4);
g_string_append_c(str, FORMAT_STYLE_REVERSE);
g_string_append_c(str, (c & 127)+'A'-1);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/irssi-1.2.0/src/irc/core/irc-core.c new/irssi-1.2.1/src/irc/core/irc-core.c
--- old/irssi-1.2.0/src/irc/core/irc-core.c 2019-02-11 18:27:58.000000000 +0100
+++ new/irssi-1.2.1/src/irc/core/irc-core.c 2019-06-28 13:48:28.000000000 +0200
@@ -75,6 +75,8 @@
g_free_not_null(ircconn->usermode);
g_free_not_null(ircconn->alternate_nick);
+ g_free_not_null(ircconn->sasl_username);
+ g_free_not_null(ircconn->sasl_password);
}
void irc_core_init(void)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/irssi-1.2.0/src/irc/core/irc-servers-reconnect.c new/irssi-1.2.1/src/irc/core/irc-servers-reconnect.c
--- old/irssi-1.2.0/src/irc/core/irc-servers-reconnect.c 2019-02-11 18:27:58.000000000 +0100
+++ new/irssi-1.2.1/src/irc/core/irc-servers-reconnect.c 2019-06-28 13:48:28.000000000 +0200
@@ -49,8 +49,8 @@
rec->usermode = g_strdup(src->usermode);
rec->alternate_nick = g_strdup(src->alternate_nick);
rec->sasl_mechanism = src->sasl_mechanism;
- rec->sasl_username = src->sasl_username;
- rec->sasl_password = src->sasl_password;
+ rec->sasl_username = g_strdup(src->sasl_username);
+ rec->sasl_password = g_strdup(src->sasl_password);
*dest = (SERVER_CONNECT_REC *) rec;
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/irssi-1.2.0/src/irc/core/irc-servers-setup.c new/irssi-1.2.1/src/irc/core/irc-servers-setup.c
--- old/irssi-1.2.0/src/irc/core/irc-servers-setup.c 2019-02-11 18:27:58.000000000 +0100
+++ new/irssi-1.2.1/src/irc/core/irc-servers-setup.c 2019-06-28 13:48:28.000000000 +0200
@@ -101,8 +101,8 @@
conn->sasl_mechanism = SASL_MECHANISM_PLAIN;
if (ircnet->sasl_username != NULL && *ircnet->sasl_username &&
ircnet->sasl_password != NULL && *ircnet->sasl_password) {
- conn->sasl_username = ircnet->sasl_username;
- conn->sasl_password = ircnet->sasl_password;
+ conn->sasl_username = g_strdup(ircnet->sasl_username);
+ conn->sasl_password = g_strdup(ircnet->sasl_password);
} else
g_warning("The fields sasl_username and sasl_password are either missing or empty");
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/irssi-1.2.0/src/lib-config/write.c new/irssi-1.2.1/src/lib-config/write.c
--- old/irssi-1.2.0/src/lib-config/write.c 2019-02-11 18:27:58.000000000 +0100
+++ new/irssi-1.2.1/src/lib-config/write.c 2019-06-28 11:51:54.000000000 +0200
@@ -315,6 +315,15 @@
/* expand all symlinks; else we may replace a symlink with a regular file */
dest_name = realpath(base_name, NULL);
+ if (errno == EINVAL) {
+ /* variable path length not supported by glibc < 2.3, Solaris < 11 */
+ char resolved_path[PATH_MAX] = { 0 };
+ errno = 0;
+ if ((dest_name = realpath(base_name, resolved_path)) != NULL) {
+ dest_name = g_strdup(dest_name);
+ }
+ }
+
if (dest_name == NULL) {
if (errno == ENOENT) {
dest_name = g_strdup(base_name);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/irssi-1.2.0/tests/fe-text/test-paste-join-multiline.c new/irssi-1.2.1/tests/fe-text/test-paste-join-multiline.c
--- old/irssi-1.2.0/tests/fe-text/test-paste-join-multiline.c 2019-02-11 18:27:58.000000000 +0100
+++ new/irssi-1.2.1/tests/fe-text/test-paste-join-multiline.c 2019-06-28 11:46:13.000000000 +0200
@@ -54,7 +54,12 @@
g_test_message("INPUT: \"%s\"", (t1 = g_strescape(test->input, NULL)));
g_free(t1);
- buffer->data = (char *) g_utf8_to_ucs4_fast(test->input, -1, (glong *) &buffer->len);
+ {
+ glong buf_len;
+ buffer->data = (char *) g_utf8_to_ucs4_fast(test->input, -1, &buf_len);
+ buffer->len = buf_len;
+ }
+
paste_buffer_join_lines(buffer);
resultstr = g_ucs4_to_utf8((unichar *) buffer->data, buffer->len, NULL, NULL, NULL);
1
0
Hello community,
here is the log from the commit of package beets for openSUSE:Factory checked in at 2019-06-30 10:22:00
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/beets (Old)
and /work/SRC/openSUSE:Factory/.beets.new.4615 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "beets"
Sun Jun 30 10:22:00 2019 rev:6 rq:712527 version:1.4.9
Changes:
--------
--- /work/SRC/openSUSE:Factory/beets/beets.changes 2019-05-20 13:18:34.487904312 +0200
+++ /work/SRC/openSUSE:Factory/.beets.new.4615/beets.changes 2019-06-30 10:22:05.179674725 +0200
@@ -1,0 +2,22 @@
+Sat Jun 29 09:28:04 UTC 2019 - Jaime Marquínez Ferrándiz <jaime.marquinez.ferrandiz(a)fastmail.net>
+
+- Update to 1.4.9:
+ * This small update is part of our attempt to release new versions more often!
+ There are a few important fixes, and we're clearing the deck for a change
+ to beets' dependencies in the next version.
+ * The new feature is:
+ * You can use the NO_COLOR environment variable to disable terminal colors.
+ * There are some fixes in this release:
+ * Fix a regression in the last release that made the image resizer fail to
+ detect older versions of ImageMagick.
+ * gmusic: The oauth_file config option now supports more flexible path
+ values, including ~ for the home directory.
+ * gmusic: Fix a crash when using version 12.0.0 or later of the gmusicapi
+ module.
+ * Fix an incompatibility with Python 3.8's AST changes.
+ * Here's a note for packagers:
+ * pathlib is now an optional test dependency on Python 3.4+, removing the
+ need for a Debian patch.
+- Remove fix-pathlib-requirement.diff: Incorporated upstream
+
+-------------------------------------------------------------------
Old:
----
beets-1.4.8.tar.gz
fix-pathlib-requirement.diff
New:
----
beets-1.4.9.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ beets.spec ++++++
--- /var/tmp/diff_new_pack.TQxoA8/_old 2019-06-30 10:22:07.003677559 +0200
+++ /var/tmp/diff_new_pack.TQxoA8/_new 2019-06-30 10:22:07.071677665 +0200
@@ -17,7 +17,7 @@
Name: beets
-Version: 1.4.8
+Version: 1.4.9
Release: 0
Summary: Music tagger and library organizer
License: MIT
@@ -27,8 +27,6 @@
Patch0: 0001-Fixed-failing-test-where.patch
# PATCH-FIX-UPSTREAM fix_test_command_line_option_relative_to_working_dir.diff alarrosa(a)suse.de - Fixes one of the tests to run successfully
Patch1: fix_test_command_line_option_relative_to_working_dir.diff
-# PATCH-FIX-UPSTREAM fix-pathlib-requirement.diff alarrosa(a)suse.de - Don't require pathlib for tests in python >= 3.4.0
-Patch2: fix-pathlib-requirement.diff
BuildRequires: python3-PyYAML
BuildRequires: python3-Unidecode
BuildRequires: python3-devel
@@ -110,7 +108,6 @@
%setup -q -n beets-%{version}
%patch0 -p1
%patch1 -p1
-%patch2 -p1
%build
python3 setup.py build
++++++ beets-1.4.8.tar.gz -> beets-1.4.9.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/beets-1.4.8/PKG-INFO new/beets-1.4.9/PKG-INFO
--- old/beets-1.4.8/PKG-INFO 2019-05-17 02:44:23.000000000 +0200
+++ new/beets-1.4.9/PKG-INFO 2019-05-31 02:06:34.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: beets
-Version: 1.4.8
+Version: 1.4.9
Summary: music tagger and library organizer
Home-page: http://beets.io/
Author: Adrian Sampson
@@ -134,24 +134,24 @@
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: Implementation :: CPython
-Provides-Extra: absubmit
-Provides-Extra: beatport
-Provides-Extra: replaygain
-Provides-Extra: plexupdate
Provides-Extra: embedart
Provides-Extra: embyupdate
-Provides-Extra: fetchart
+Provides-Extra: gmusic
Provides-Extra: import
-Provides-Extra: metasync
Provides-Extra: thumbnails
-Provides-Extra: chroma
-Provides-Extra: discogs
Provides-Extra: lyrics
-Provides-Extra: kodiupdate
-Provides-Extra: lastgenre
Provides-Extra: bpd
-Provides-Extra: mpdstats
-Provides-Extra: web
+Provides-Extra: discogs
+Provides-Extra: plexupdate
Provides-Extra: lastimport
+Provides-Extra: replaygain
+Provides-Extra: chroma
+Provides-Extra: lastgenre
+Provides-Extra: web
+Provides-Extra: beatport
+Provides-Extra: kodiupdate
Provides-Extra: sonosupdate
-Provides-Extra: gmusic
+Provides-Extra: fetchart
+Provides-Extra: mpdstats
+Provides-Extra: metasync
+Provides-Extra: absubmit
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/beets-1.4.8/beets/__init__.py new/beets-1.4.9/beets/__init__.py
--- old/beets-1.4.8/beets/__init__.py 2019-05-17 02:42:57.000000000 +0200
+++ new/beets-1.4.9/beets/__init__.py 2019-05-17 02:44:25.000000000 +0200
@@ -19,7 +19,7 @@
from beets.util import confit
-__version__ = u'1.4.8'
+__version__ = u'1.4.9'
__author__ = u'Adrian Sampson <adrian(a)radbox.org>'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/beets-1.4.8/beets/ui/__init__.py new/beets-1.4.9/beets/ui/__init__.py
--- old/beets-1.4.8/beets/ui/__init__.py 2019-05-17 02:42:57.000000000 +0200
+++ new/beets-1.4.9/beets/ui/__init__.py 2019-05-30 15:08:39.000000000 +0200
@@ -529,22 +529,22 @@
"""Colorize text if colored output is enabled. (Like _colorize but
conditional.)
"""
- if config['ui']['color']:
- global COLORS
- if not COLORS:
- COLORS = dict((name,
- config['ui']['colors'][name].as_str())
- for name in COLOR_NAMES)
- # In case a 3rd party plugin is still passing the actual color ('red')
- # instead of the abstract color name ('text_error')
- color = COLORS.get(color_name)
- if not color:
- log.debug(u'Invalid color_name: {0}', color_name)
- color = color_name
- return _colorize(color, text)
- else:
+ if not config['ui']['color'] or 'NO_COLOR' in os.environ.keys():
return text
+ global COLORS
+ if not COLORS:
+ COLORS = dict((name,
+ config['ui']['colors'][name].as_str())
+ for name in COLOR_NAMES)
+ # In case a 3rd party plugin is still passing the actual color ('red')
+ # instead of the abstract color name ('text_error')
+ color = COLORS.get(color_name)
+ if not color:
+ log.debug(u'Invalid color_name: {0}', color_name)
+ color = color_name
+ return _colorize(color, text)
+
def _colordiff(a, b, highlight='text_highlight',
minor_highlight='text_highlight_minor'):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/beets-1.4.8/beets/util/artresizer.py new/beets-1.4.9/beets/util/artresizer.py
--- old/beets-1.4.8/beets/util/artresizer.py 2019-05-17 02:42:57.000000000 +0200
+++ new/beets-1.4.9/beets/util/artresizer.py 2019-05-18 01:35:59.000000000 +0200
@@ -278,7 +278,7 @@
int(match.group(3)))
return version, legacy
- return None
+ return None
def get_pil_version():
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/beets-1.4.8/beets/util/functemplate.py new/beets-1.4.9/beets/util/functemplate.py
--- old/beets-1.4.8/beets/util/functemplate.py 2019-05-17 02:42:57.000000000 +0200
+++ new/beets-1.4.9/beets/util/functemplate.py 2019-05-31 01:31:09.000000000 +0200
@@ -118,29 +118,30 @@
bytecode of the compiled function.
"""
if six.PY2:
- func_def = ast.FunctionDef(
- name=name.encode('utf-8'),
- args=ast.arguments(
- args=[ast.Name(n, ast.Param()) for n in arg_names],
- vararg=None,
- kwarg=None,
- defaults=[ex_literal(None) for _ in arg_names],
- ),
- body=statements,
- decorator_list=[],
+ name = name.encode('utf-8')
+ args = ast.arguments(
+ args=[ast.Name(n, ast.Param()) for n in arg_names],
+ vararg=None,
+ kwarg=None,
+ defaults=[ex_literal(None) for _ in arg_names],
)
else:
- func_def = ast.FunctionDef(
- name=name,
- args=ast.arguments(
- args=[ast.arg(arg=n, annotation=None) for n in arg_names],
- kwonlyargs=[],
- kw_defaults=[],
- defaults=[ex_literal(None) for _ in arg_names],
- ),
- body=statements,
- decorator_list=[],
- )
+ args_fields = {
+ 'args': [ast.arg(arg=n, annotation=None) for n in arg_names],
+ 'kwonlyargs': [],
+ 'kw_defaults': [],
+ 'defaults': [ex_literal(None) for _ in arg_names],
+ }
+ if 'posonlyargs' in ast.arguments._fields: # Added in Python 3.8.
+ args_fields['posonlyargs'] = []
+ args = ast.arguments(**args_fields)
+
+ func_def = ast.FunctionDef(
+ name=name,
+ args=args,
+ body=statements,
+ decorator_list=[],
+ )
# The ast.Module signature changed in 3.8 to accept a list of types to
# ignore.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/beets-1.4.8/beets.egg-info/PKG-INFO new/beets-1.4.9/beets.egg-info/PKG-INFO
--- old/beets-1.4.8/beets.egg-info/PKG-INFO 2019-05-17 02:44:22.000000000 +0200
+++ new/beets-1.4.9/beets.egg-info/PKG-INFO 2019-05-31 02:06:34.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: beets
-Version: 1.4.8
+Version: 1.4.9
Summary: music tagger and library organizer
Home-page: http://beets.io/
Author: Adrian Sampson
@@ -134,24 +134,24 @@
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: Implementation :: CPython
-Provides-Extra: absubmit
-Provides-Extra: beatport
-Provides-Extra: replaygain
-Provides-Extra: plexupdate
Provides-Extra: embedart
Provides-Extra: embyupdate
-Provides-Extra: fetchart
+Provides-Extra: gmusic
Provides-Extra: import
-Provides-Extra: metasync
Provides-Extra: thumbnails
-Provides-Extra: chroma
-Provides-Extra: discogs
Provides-Extra: lyrics
-Provides-Extra: kodiupdate
-Provides-Extra: lastgenre
Provides-Extra: bpd
-Provides-Extra: mpdstats
-Provides-Extra: web
+Provides-Extra: discogs
+Provides-Extra: plexupdate
Provides-Extra: lastimport
+Provides-Extra: replaygain
+Provides-Extra: chroma
+Provides-Extra: lastgenre
+Provides-Extra: web
+Provides-Extra: beatport
+Provides-Extra: kodiupdate
Provides-Extra: sonosupdate
-Provides-Extra: gmusic
+Provides-Extra: fetchart
+Provides-Extra: mpdstats
+Provides-Extra: metasync
+Provides-Extra: absubmit
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/beets-1.4.8/beetsplug/gmusic.py new/beets-1.4.9/beetsplug/gmusic.py
--- old/beets-1.4.8/beetsplug/gmusic.py 2019-05-17 02:42:57.000000000 +0200
+++ new/beets-1.4.9/beetsplug/gmusic.py 2019-05-18 22:32:01.000000000 +0200
@@ -31,12 +31,19 @@
def __init__(self):
super(Gmusic, self).__init__()
self.m = Musicmanager()
+
+ # OAUTH_FILEPATH was moved in gmusicapi 12.0.0.
+ if hasattr(Musicmanager, 'OAUTH_FILEPATH'):
+ oauth_file = Musicmanager.OAUTH_FILEPATH
+ else:
+ oauth_file = gmusicapi.clients.OAUTH_FILEPATH
+
self.config.add({
u'auto': False,
u'uploader_id': '',
u'uploader_name': '',
u'device_id': '',
- u'oauth_file': gmusicapi.clients.OAUTH_FILEPATH,
+ u'oauth_file': oauth_file,
})
if self.config['auto']:
self.import_stages = [self.autoupload]
@@ -62,7 +69,7 @@
return
# Checks for OAuth2 credentials,
# if they don't exist - performs authorization
- oauth_file = self.config['oauth_file'].as_str()
+ oauth_file = self.config['oauth_file'].as_filename()
if os.path.isfile(oauth_file):
uploader_id = self.config['uploader_id']
uploader_name = self.config['uploader_name']
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/beets-1.4.8/docs/changelog.rst new/beets-1.4.9/docs/changelog.rst
--- old/beets-1.4.8/docs/changelog.rst 2019-05-17 02:42:59.000000000 +0200
+++ new/beets-1.4.9/docs/changelog.rst 2019-05-31 01:32:38.000000000 +0200
@@ -1,6 +1,41 @@
Changelog
=========
+1.4.9 (May 30, 2019)
+--------------------
+
+This small update is part of our attempt to release new versions more often!
+There are a few important fixes, and we're clearing the deck for a change to
+beets' dependencies in the next version.
+
+The new feature is:
+
+* You can use the `NO_COLOR`_ environment variable to disable terminal colors.
+ :bug:`3273`
+
+There are some fixes in this release:
+
+* Fix a regression in the last release that made the image resizer fail to
+ detect older versions of ImageMagick.
+ :bug:`3269`
+* :doc:`/plugins/gmusic`: The ``oauth_file`` config option now supports more
+ flexible path values, including ``~`` for the home directory.
+ :bug:`3270`
+* :doc:`/plugins/gmusic`: Fix a crash when using version 12.0.0 or later of
+ the ``gmusicapi`` module.
+ :bug:`3270`
+* Fix an incompatibility with Python 3.8's AST changes.
+ :bug:`3278`
+
+Here's a note for packagers:
+
+* ``pathlib`` is now an optional test dependency on Python 3.4+, removing the
+ need for `a Debian patch <https://sources.debian.org/src/beets/1.4.7-2/debian/patches/pathlib-is-stdl…>`_.
+ :bug:`3275`
+
+.. _NO_COLOR: https://no-color.org
+
+
1.4.8 (May 16, 2019)
--------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/beets-1.4.8/docs/conf.py new/beets-1.4.9/docs/conf.py
--- old/beets-1.4.8/docs/conf.py 2019-05-17 02:42:57.000000000 +0200
+++ new/beets-1.4.9/docs/conf.py 2019-05-17 02:44:25.000000000 +0200
@@ -16,7 +16,7 @@
copyright = u'2016, Adrian Sampson'
version = '1.4'
-release = '1.4.8'
+release = '1.4.9'
pygments_style = 'sphinx'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/beets-1.4.8/docs/guides/main.rst new/beets-1.4.9/docs/guides/main.rst
--- old/beets-1.4.8/docs/guides/main.rst 2019-05-17 02:42:57.000000000 +0200
+++ new/beets-1.4.9/docs/guides/main.rst 2019-05-30 15:08:39.000000000 +0200
@@ -26,37 +26,37 @@
as described below by running:
``apt-get install python-dev python-pip``
-* On **Arch Linux**, `beets is in [community]`_, so just run ``pacman -S
- beets``. (There's also a bleeding-edge `dev package`_ in the AUR, which will
+* On **Arch Linux**, `beets is in [community] <Arch community_>`_, so just run ``pacman -S
+ beets``. (There's also a bleeding-edge `dev package <AUR_>`_ in the AUR, which will
probably set your computer on fire.)
* For **Gentoo Linux**, beets is in Portage as ``media-sound/beets``. Just run
``emerge beets`` to install. There are several USE flags available for
optional plugin dependencies.
-* On **FreeBSD**, there's a `beets port`_ at ``audio/beets``.
+* On **FreeBSD**, there's a `beets port <FreeBSD_>`_ at ``audio/beets``.
-* On **OpenBSD**, beets can be installed with ``pkg_add beets``.
+* On **OpenBSD**, there's a `beets port <OpenBSD_>`_ can be installed with ``pkg_add beets``.
* For **Slackware**, there's a `SlackBuild`_ available.
-* On **Fedora** 22 or later, there is a `DNF package`_ (or three)::
+* On **Fedora** 22 or later, there is a `DNF package`_::
$ sudo dnf install beets beets-plugins beets-doc
* On **Solus**, run ``eopkg install beets``.
-* On **NixOS**, run ``nix-env -i beets``.
+* On **NixOS**, there's a `package <NixOS_>`_ you can install with ``nix-env -i beets``.
-.. _copr: https://copr.fedoraproject.org/coprs/afreof/beets/
-.. _dnf package: https://apps.fedoraproject.org/packages/beets
-.. _SlackBuild: http://slackbuilds.org/repository/14.1/multimedia/beets/
-.. _beets port: http://portsmon.freebsd.org/portoverview.py?category=audio&portname=beets
-.. _beets from AUR: https://aur.archlinux.org/packages/beets-git/
-.. _dev package: https://aur.archlinux.org/packages/beets-git/
-.. _Debian details: http://packages.qa.debian.org/b/beets.html
+.. _DNF package: https://apps.fedoraproject.org/packages/beets
+.. _SlackBuild: http://slackbuilds.org/repository/14.2/multimedia/beets/
+.. _FreeBSD: http://portsmon.freebsd.org/portoverview.py?category=audio&portname=beets
+.. _AUR: https://aur.archlinux.org/packages/beets-git/
+.. _Debian details: https://tracker.debian.org/pkg/beets
.. _Ubuntu details: https://launchpad.net/ubuntu/+source/beets
-.. _beets is in [community]: https://www.archlinux.org/packages/community/any/beets/
+.. _OpenBSD: http://openports.se/audio/beets
+.. _Arch community: https://www.archlinux.org/packages/community/any/beets/
+.. _NixOS: https://github.com/NixOS/nixpkgs/tree/master/pkgs/tools/audio/beets
If you have `pip`_, just say ``pip install beets`` (or ``pip install --user
beets`` if you run into permissions problems).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/beets-1.4.8/man/beet.1 new/beets-1.4.9/man/beet.1
--- old/beets-1.4.8/man/beet.1 2019-05-17 02:44:22.000000000 +0200
+++ new/beets-1.4.9/man/beet.1 2019-05-31 02:06:33.000000000 +0200
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "BEET" "1" "May 16, 2019" "1.4" "beets"
+.TH "BEET" "1" "May 30, 2019" "1.4" "beets"
.SH NAME
beet \- music tagger and library organizer
.
@@ -32,7 +32,7 @@
..
.SH SYNOPSIS
.nf
-\fBbeet\fP [\fIargs\fP\&...] \fIcommand\fP [\fIargs\fP\&...]
+\fBbeet\fP [\fIargs\fP…] \fIcommand\fP [\fIargs\fP…]
\fBbeet help\fP \fIcommand\fP
.fi
.sp
@@ -63,7 +63,7 @@
Directories passed to the import command can contain either a single
album or many, in which case the leaf directories will be considered
albums (the latter case is true of typical Artist/Album organizations
-and many people\(aqs "downloads" folders). The path can also be a single
+and many people’s “downloads” folders). The path can also be a single
song or an archive. Beets supports \fIzip\fP and \fItar\fP archives out of the
box. To extract \fIrar\fP files, install the \fI\%rarfile\fP package and the
\fIunrar\fP command.
@@ -73,46 +73,46 @@
.IP \(bu 2
By default, the command copies files your the library directory and
updates the ID3 tags on your music. In order to move the files, instead of
-copying, use the \fB\-m\fP (move) option. If you\(aqd like to leave your music
-files untouched, try the \fB\-C\fP (don\(aqt copy) and \fB\-W\fP (don\(aqt write tags)
+copying, use the \fB\-m\fP (move) option. If you’d like to leave your music
+files untouched, try the \fB\-C\fP (don’t copy) and \fB\-W\fP (don’t write tags)
options. You can also disable this behavior by default in the
configuration file (below).
.IP \(bu 2
Also, you can disable the autotagging behavior entirely using \fB\-A\fP
-(don\(aqt autotag)\-\-\-then your music will be imported with its existing
+(don’t autotag)—then your music will be imported with its existing
metadata.
.IP \(bu 2
During a long tagging import, it can be useful to keep track of albums
-that weren\(aqt tagged successfully\-\-\-either because they\(aqre not in the
-MusicBrainz database or because something\(aqs wrong with the files. Use the
+that weren’t tagged successfully—either because they’re not in the
+MusicBrainz database or because something’s wrong with the files. Use the
\fB\-l\fP option to specify a filename to log every time you skip an album
-or import it "as\-is" or an album gets skipped as a duplicate.
+or import it “as\-is” or an album gets skipped as a duplicate.
.IP \(bu 2
Relatedly, the \fB\-q\fP (quiet) option can help with large imports by
autotagging without ever bothering to ask for user input. Whenever the
normal autotagger mode would ask for confirmation, the quiet mode
-pessimistically skips the album. The quiet mode also disables the tagger\(aqs
+pessimistically skips the album. The quiet mode also disables the tagger’s
ability to resume interrupted imports.
.IP \(bu 2
Speaking of resuming interrupted imports, the tagger will prompt you if it
seems like the last import of the directory was interrupted (by you or by
-a crash). If you want to skip this prompt, you can say "yes" automatically
-by providing \fB\-p\fP or "no" using \fB\-P\fP\&. The resuming feature can be
+a crash). If you want to skip this prompt, you can say “yes” automatically
+by providing \fB\-p\fP or “no” using \fB\-P\fP\&. The resuming feature can be
disabled by default using a configuration option (see below).
.IP \(bu 2
If you want to import only the \fInew\fP stuff from a directory, use the
\fB\-i\fP
option to run an \fIincremental\fP import. With this flag, beets will keep
track of every directory it ever imports and avoid importing them again.
-This is useful if you have an "incoming" directory that you periodically
+This is useful if you have an “incoming” directory that you periodically
add things to.
-To get this to work correctly, you\(aqll need to use an incremental import \fIevery
-time\fP you run an import on the directory in question\-\-\-including the first
+To get this to work correctly, you’ll need to use an incremental import \fIevery
+time\fP you run an import on the directory in question—including the first
time, when no subdirectories will be skipped. So consider enabling the
\fBincremental\fP configuration option.
.IP \(bu 2
When beets applies metadata to your music, it will retain the value of any
-existing tags that weren\(aqt overwritten, and import them into the database. You
+existing tags that weren’t overwritten, and import them into the database. You
may prefer to only use existing metadata for finding matches, and to erase it
completely when new metadata is applied. You can enforce this behavior with
the \fB\-\-from\-scratch\fP option, or the \fBfrom_scratch\fP configuration option.
@@ -125,7 +125,7 @@
instead want to import individual, non\-album tracks, use the \fIsingleton\fP
mode by supplying the \fB\-s\fP option.
.IP \(bu 2
-If you have an album that\(aqs split across several directories under a common
+If you have an album that’s split across several directories under a common
top directory, use the \fB\-\-flat\fP option. This takes all the music files
under the directory (recursively) and treats them as a single large album
instead of as one album per directory. This can help with your more stubborn
@@ -173,9 +173,9 @@
.sp
Queries the database for music.
.sp
-Want to search for "Gronlandic Edit" by of Montreal? Try \fBbeet list
+Want to search for “Gronlandic Edit” by of Montreal? Try \fBbeet list
gronlandic\fP\&. Maybe you want to see everything released in 2009 with
-"vegetables" in the title? Try \fBbeet list year:2009 title:vegetables\fP\&. You
+“vegetables” in the title? Try \fBbeet list year:2009 title:vegetables\fP\&. You
can also specify the sort order. (Read more in query\&.)
.sp
You can use the \fB\-a\fP switch to search for albums instead of individual items.
@@ -187,7 +187,7 @@
The \fB\-p\fP option makes beets print out filenames of matched items, which might
be useful for piping into other Unix commands (such as \fI\%xargs\fP). Similarly, the
\fB\-f\fP option lets you specify a specific format with which to print every album
-or track. This uses the same template syntax as beets\(aq path formats\&. For example, the command \fBbeet ls \-af \(aq$album: $tracktotal\(aq
+or track. This uses the same template syntax as beets’ path formats\&. For example, the command \fBbeet ls \-af \(aq$album: $tracktotal\(aq
beatles\fP prints out the number of tracks on each Beatles album. In Unix shells,
remember to enclose the template argument in single quotes to avoid environment
variable expansion.
@@ -206,8 +206,8 @@
Remove music from your library.
.sp
This command uses the same query syntax as the \fBlist\fP command.
-You\(aqll be shown a list of the files that will be removed and asked to confirm.
-By default, this just removes entries from the library database; it doesn\(aqt
+You’ll be shown a list of the files that will be removed and asked to confirm.
+By default, this just removes entries from the library database; it doesn’t
touch the files on disk. To actually delete the files, use \fBbeet remove \-d\fP\&.
If you do not want to be prompted to remove the files, use \fBbeet remove \-f\fP\&.
.SS modify
@@ -226,21 +226,21 @@
.sp
Supply a query matching the things you want to change and a
series of \fBfield=value\fP pairs. For example, \fBbeet modify genius of love
-artist="Tom Tom Club"\fP will change the artist for the track "Genius of Love."
+artist="Tom Tom Club"\fP will change the artist for the track “Genius of Love.”
To remove fields (which is only possible for flexible attributes), follow a
field name with an exclamation point: \fBfield!\fP\&.
.sp
The \fB\-a\fP switch operates on albums instead of individual tracks. Without
this flag, the command will only change \fItrack\-level\fP data, even if all the
tracks belong to the same album. If you want to change an \fIalbum\-level\fP field,
-such as \fByear\fP or \fBalbumartist\fP, you\(aqll want to use the \fB\-a\fP flag to
+such as \fByear\fP or \fBalbumartist\fP, you’ll want to use the \fB\-a\fP flag to
avoid a confusing situation where the data for individual tracks conflicts
with the data for the whole album.
.sp
-Items will automatically be moved around when necessary if they\(aqre in your
+Items will automatically be moved around when necessary if they’re in your
library directory, but you can disable that with \fB\-M\fP\&. Tags will be written
to the files according to the settings you have for imports, but these can be
-overridden with \fB\-w\fP (write tags, the default) and \fB\-W\fP (don\(aqt write
+overridden with \fB\-w\fP (write tags, the default) and \fB\-W\fP (don’t write
tags).
.sp
When you run the \fBmodify\fP command, it prints a list of all
@@ -271,10 +271,10 @@
destination directory with \fB\-d\fP manually, you can move items matching a query
anywhere in your filesystem. The \fB\-c\fP option copies files instead of moving
them. As with other commands, the \fB\-a\fP option matches albums instead of items.
-The \fB\-e\fP flag (for "export") copies files without changing the database.
+The \fB\-e\fP flag (for “export”) copies files without changing the database.
.sp
-To perform a "dry run", just use the \fB\-p\fP (for "pretend") flag. This will
-show you a list of files that would be moved but won\(aqt actually change anything
+To perform a “dry run”, just use the \fB\-p\fP (for “pretend”) flag. This will
+show you a list of files that would be moved but won’t actually change anything
on disk. The \fB\-t\fP option sets the timid mode which will ask again
before really moving or copying the files.
.SS update
@@ -299,8 +299,8 @@
also update these for \fBbeet update\fP to recognise that the files have been
edited.
.sp
-To perform a "dry run" of an update, just use the \fB\-p\fP (for "pretend") flag.
-This will show you all the proposed changes but won\(aqt actually change anything
+To perform a “dry run” of an update, just use the \fB\-p\fP (for “pretend”) flag.
+This will show you all the proposed changes but won’t actually change anything
on disk.
.sp
By default, all the changed metadata will be populated back to the database.
@@ -311,7 +311,7 @@
When an updated track is part of an album, the album\-level fields of \fIall\fP
tracks from the album are also updated. (Specifically, the command copies
album\-level data from the first track on the album and applies it to the
-rest of the tracks.) This means that, if album\-level fields aren\(aqt identical
+rest of the tracks.) This means that, if album\-level fields aren’t identical
within an album, some changes shown by the \fBupdate\fP command may be
overridden by data from other tracks on the same album. This means that
running the \fBupdate\fP command multiple times may show the same changes being
@@ -328,9 +328,9 @@
.UNINDENT
.UNINDENT
.sp
-Write metadata from the database into files\(aq tags.
+Write metadata from the database into files’ tags.
.sp
-When you make changes to the metadata stored in beets\(aq library database
+When you make changes to the metadata stored in beets’ library database
(during import or with the \fI\%modify\fP command, for example), you often
have the option of storing changes only in the database, leaving your files
untouched. The \fBwrite\fP command lets you later change your mind and write the
@@ -353,7 +353,7 @@
.UNINDENT
.UNINDENT
.sp
-Show some statistics on your entire library (if you don\(aqt provide a
+Show some statistics on your entire library (if you don’t provide a
query) or the matched items (if you do).
.sp
By default, the command calculates file sizes using their bitrate and
@@ -373,7 +373,7 @@
.sp
Show the item and album metadata fields available for use in query and
pathformat\&. The listing includes any template fields provided by
-plugins and any flexible attributes you\(aqve manually assigned to your items and
+plugins and any flexible attributes you’ve manually assigned to your items and
albums.
.SS config
.INDENT 0.0
@@ -392,7 +392,7 @@
.INDENT 0.0
.IP \(bu 2
With no options, print a YAML representation of the current user
-configuration. With the \fB\-\-default\fP option, beets\(aq default options are
+configuration. With the \fB\-\-default\fP option, beets’ default options are
also included in the dump.
.IP \(bu 2
The \fB\-\-path\fP option instead shows the path to your configuration file.
@@ -409,8 +409,8 @@
.UNINDENT
.SH GLOBAL FLAGS
.sp
-Beets has a few "global" flags that affect all commands. These must appear
-between the executable name (\fBbeet\fP) and the command\-\-\-for example, \fBbeet \-v
+Beets has a few “global” flags that affect all commands. These must appear
+between the executable name (\fBbeet\fP) and the command—for example, \fBbeet \-v
import ...\fP\&.
.INDENT 0.0
.IP \(bu 2
@@ -472,8 +472,8 @@
.UNINDENT
.UNINDENT
.sp
-(Don\(aqt worry about the slash in front of the colon: this is a escape
-sequence for the shell and won\(aqt be seen by beets.)
+(Don’t worry about the slash in front of the colon: this is a escape
+sequence for the shell and won’t be seen by beets.)
.sp
Completion of plugin commands only works for those plugins
that were enabled when running \fBbeet completion\fP\&. If you add a plugin
@@ -485,7 +485,7 @@
sourced in your \fB\&.zshrc\fP\&. Running \fBecho $fpath\fP will give you a list of
valid directories.
.sp
-Another approach is to use zsh\(aqs bash completion compatibility. This snippet
+Another approach is to use zsh’s bash completion compatibility. This snippet
defines some bash\-specific functions to make this work without errors:
.INDENT 0.0
.INDENT 3.5
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/beets-1.4.8/man/beetsconfig.5 new/beets-1.4.9/man/beetsconfig.5
--- old/beets-1.4.8/man/beetsconfig.5 2019-05-17 02:44:22.000000000 +0200
+++ new/beets-1.4.9/man/beetsconfig.5 2019-05-31 02:06:33.000000000 +0200
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "BEETSCONFIG" "5" "May 16, 2019" "1.4" "beets"
+.TH "BEETSCONFIG" "5" "May 30, 2019" "1.4" "beets"
.SH NAME
beetsconfig \- beets configuration file
.
@@ -226,7 +226,7 @@
.UNINDENT
.SH GLOBAL OPTIONS
.sp
-These options control beets\(aq global operation.
+These options control beets’ global operation.
.SS library
.sp
Path to the beets library file. By default, beets will use a file called
@@ -248,7 +248,7 @@
Directories to search for plugins. Each Python file or directory in a plugin
path represents a plugin and should define a subclass of \fBBeetsPlugin\fP\&.
A plugin can then be loaded by adding the filename to the \fIplugins\fP configuration.
-The plugin path can either be a single string or a list of strings\-\-\-so, if you
+The plugin path can either be a single string or a list of strings—so, if you
have multiple paths, format them as a YAML list like so:
.INDENT 0.0
.INDENT 3.5
@@ -272,8 +272,8 @@
.SS ignore_hidden
.sp
Either \fByes\fP or \fBno\fP; whether to ignore hidden files when importing. On
-Windows, the "Hidden" property of files is used to detect whether or not a file
-is hidden. On OS X, the file\(aqs "IsHidden" flag is used to detect whether or not
+Windows, the “Hidden” property of files is used to detect whether or not a file
+is hidden. On OS X, the file’s “IsHidden” flag is used to detect whether or not
a file is hidden. On both OS X and other platforms (excluding Windows), files
(and directories) starting with a dot are detected as hidden files.
.SS replace
@@ -311,7 +311,7 @@
.sp
These substitutions remove forward and back slashes, leading dots, and
control characters—all of which is a good idea on any OS. The fourth line
-removes the Windows "reserved characters" (useful even on Unix for for
+removes the Windows “reserved characters” (useful even on Unix for for
compatibility with Windows\-influenced network filesystems like Samba).
Trailing dots and trailing whitespace, which can cause problems on Windows
clients, are also removed.
@@ -323,7 +323,7 @@
.sp
Note that paths might contain special characters such as typographical
quotes (\fB“”\fP). With the configuration above, those will not be
-replaced as they don\(aqt match the typewriter quote (\fB"\fP). To also strip these
+replaced as they don’t match the typewriter quote (\fB"\fP). To also strip these
special characters, you can either add them to the replacement list or use the
\fI\%asciify_paths\fP configuration option below.
.SS asciify_paths
@@ -331,7 +331,7 @@
Convert all non\-ASCII characters in paths to ASCII equivalents.
.sp
For example, if your path template for
-singletons is \fBsingletons/$title\fP and the title of a track is "Café",
+singletons is \fBsingletons/$title\fP and the title of a track is “Café”,
then the track will be saved as \fBsingletons/Cafe.mp3\fP\&. The changes
take place before applying the \fI\%replace\fP configuration and are roughly
equivalent to wrapping all your path templates in the \fB%asciify{}\fP
@@ -344,7 +344,7 @@
cover art image should be placed. This is a template string, so you can use any
of the syntax available to /reference/pathformat\&. Defaults to \fBcover\fP
(i.e., images will be named \fBcover.jpg\fP or \fBcover.png\fP and placed in the
-album\(aqs directory).
+album’s directory).
.SS threaded
.sp
Either \fByes\fP or \fBno\fP, indicating whether the autotagger should use
@@ -418,7 +418,7 @@
.UNINDENT
.UNINDENT
.sp
-When this option is off (the default), even "pregap" hidden tracks are
+When this option is off (the default), even “pregap” hidden tracks are
numbered from one, not zero, so other track numbers may appear to be bumped up
by one. When it is on, the pregap track for each disc can be numbered zero.
.SS aunique
@@ -445,17 +445,17 @@
.SS terminal_encoding
.sp
The text encoding, as \fI\%known to Python\fP, to use for messages printed to the
-standard output. It\(aqs also used to read messages from the standard input.
+standard output. It’s also used to read messages from the standard input.
By default, this is determined automatically from the locale
environment variables.
.SS clutter
.sp
When beets imports all the files in a directory, it tries to remove the
-directory if it\(aqs empty. A directory is considered empty if it only contains
+directory if it’s empty. A directory is considered empty if it only contains
files whose names match the glob patterns in \fIclutter\fP, which should be a list
-of strings. The default list consists of "Thumbs.DB" and ".DS_Store".
+of strings. The default list consists of “Thumbs.DB” and “.DS_Store”.
.sp
-The importer only removes recursively searched subdirectories\-\-\-the top\-level
+The importer only removes recursively searched subdirectories—the top\-level
directory you specify on the command line is never deleted.
.SS max_filename_length
.sp
@@ -481,7 +481,7 @@
.SS color
.sp
Either \fByes\fP or \fBno\fP; whether to use color in console output (currently
-only in the \fBimport\fP command). Turn this off if your terminal doesn\(aqt
+only in the \fBimport\fP command). Turn this off if your terminal doesn’t
support ANSI colors.
.sp
\fBNOTE:\fP
@@ -552,7 +552,7 @@
overridden with the \fB\-c\fP and \fB\-C\fP command\-line options.
.sp
The option is ignored if \fBmove\fP is enabled (i.e., beets can move or
-copy files but it doesn\(aqt make sense to do both).
+copy files but it doesn’t make sense to do both).
.SS move
.sp
Either \fByes\fP or \fBno\fP, indicating whether to \fBmove\fP files into the
@@ -560,10 +560,10 @@
Defaults to \fBno\fP\&.
.sp
The effect is similar to the \fBcopy\fP option but you end up with only
-one copy of the imported file. ("Moving" works even across filesystems; if
+one copy of the imported file. (“Moving” works even across filesystems; if
necessary, beets will copy and then delete when a simple rename is
-impossible.) Moving files can be risky—it\(aqs a good idea to keep a backup in
-case beets doesn\(aqt do what you expect with your files.
+impossible.) Moving files can be risky—it’s a good idea to keep a backup in
+case beets doesn’t do what you expect with your files.
.sp
This option \fIoverrides\fP \fBcopy\fP, so enabling it will always move
(and not copy) files. The \fB\-c\fP switch to the \fBbeet import\fP command,
@@ -577,7 +577,7 @@
This option only works on platforms that support symbolic links: i.e., Unixes.
It will fail on Windows.
.sp
-It\(aqs likely that you\(aqll also want to set \fBwrite\fP to \fBno\fP if you use this
+It’s likely that you’ll also want to set \fBwrite\fP to \fBno\fP if you use this
option to preserve the metadata on the linked files.
.SS hardlink
.sp
@@ -591,10 +591,10 @@
.SS resume
.sp
Either \fByes\fP, \fBno\fP, or \fBask\fP\&. Controls whether interrupted imports
-should be resumed. "Yes" means that imports are always resumed when
-possible; "no" means resuming is disabled entirely; "ask" (the default)
+should be resumed. “Yes” means that imports are always resumed when
+possible; “no” means resuming is disabled entirely; “ask” (the default)
means that the user should be prompted when resuming is possible. The \fB\-p\fP
-and \fB\-P\fP flags correspond to the "yes" and "no" settings and override this
+and \fB\-P\fP flags correspond to the “yes” and “no” settings and override this
option.
.SS incremental
.sp
@@ -606,7 +606,7 @@
Either \fByes\fP or \fBno\fP, controlling whether skipped directories are
recorded in the incremental list. When set to \fByes\fP, skipped directories
will be recorded, and skipped later. When set to \fBno\fP, skipped
-directories won\(aqt be recorded, and beets will try to import them again
+directories won’t be recorded, and beets will try to import them again
later. Defaults to \fBno\fP\&.
.SS from_scratch
.sp
@@ -632,7 +632,7 @@
controls the same setting.
.SS log
.sp
-Specifies a filename where the importer\(aqs log should be kept. By default,
+Specifies a filename where the importer’s log should be kept. By default,
no log is written. This can be overridden with the \fB\-l\fP flag to
\fBimport\fP\&.
.SS default_action
@@ -644,8 +644,8 @@
.SS languages
.sp
A list of locale names to search for preferred aliases. For example, setting
-this to \fBen\fP uses the transliterated artist name "Pyotr Ilyich Tchaikovsky"
-instead of the Cyrillic script for the composer\(aqs name when tagging from
+this to \fBen\fP uses the transliterated artist name “Pyotr Ilyich Tchaikovsky”
+instead of the Cyrillic script for the composer’s name when tagging from
MusicBrainz. You can use a space\-separated list of language abbreviations, like
\fBen jp es\fP, to specify a preference order. Defaults to an empty list, meaning
that no language is preferred.
@@ -658,7 +658,7 @@
.SS group_albums
.sp
By default, the beets importer groups tracks into albums based on the
-directories they reside in. This option instead uses files\(aq metadata to
+directories they reside in. This option instead uses files’ metadata to
partition albums. Enable this option if you have directories that contain
tracks from many albums mixed together.
.sp
@@ -678,9 +678,9 @@
.sp
Either \fBskip\fP, \fBkeep\fP, \fBremove\fP, \fBmerge\fP or \fBask\fP\&.
Controls how duplicates are treated in import task.
-"skip" means that new item(album or track) will be skipped;
-"keep" means keep both old and new items; "remove" means remove old
-item; "merge" means merge into one album; "ask" means the user
+“skip” means that new item(album or track) will be skipped;
+“keep” means keep both old and new items; “remove” means remove old
+item; “merge” means merge into one album; “ask” means the user
should be prompted for the action each time. The default is \fBask\fP\&.
.SS bell
.sp
@@ -690,7 +690,7 @@
.SS set_fields
.sp
A dictionary indicating fields to set to values for newly imported music.
-Here\(aqs an example:
+Here’s an example:
.INDENT 0.0
.INDENT 3.5
.sp
@@ -731,8 +731,8 @@
The server must have search indices enabled (see \fI\%Building search indexes\fP).
.sp
The \fBratelimit\fP option, an integer, controls the number of Web service requests
-per second (default: 1). \fBDo not change the rate limit setting\fP if you\(aqre
-using the main MusicBrainz server\-\-\-on this public server, you\(aqre \fI\%limited\fP
+per second (default: 1). \fBDo not change the rate limit setting\fP if you’re
+using the main MusicBrainz server—on this public server, you’re \fI\%limited\fP
to one request per second.
.SS searchlimit
.sp
@@ -746,8 +746,8 @@
matching MusicBrainz results under the \fBmatch:\fP section. To control how
\fItolerant\fP the autotagger is of differences, use the \fBstrong_rec_thresh\fP
option, which reflects the distance threshold below which beets will make a
-"strong recommendation" that the metadata be used. Strong recommendations
-are accepted automatically (except in "timid" mode), so you can use this to
+“strong recommendation” that the metadata be used. Strong recommendations
+are accepted automatically (except in “timid” mode), so you can use this to
make beets ask your opinion more or less often.
.sp
The threshold is a \fIdistance\fP value between 0.0 and 1.0, so you can think of it
@@ -770,7 +770,7 @@
The \fBmedium_rec_thresh\fP and \fBrec_gap_thresh\fP options work similarly. When a
match is below the \fImedium\fP recommendation threshold or the distance between it
and the next\-best match is above the \fIgap\fP threshold, the importer will suggest
-that match but not automatically confirm it. Otherwise, you\(aqll see a list of
+that match but not automatically confirm it. Otherwise, you’ll see a list of
options to choose from.
.SS max_rec
.sp
@@ -781,7 +781,7 @@
\fImaximum\fP recommendations for each field:
.sp
To define maxima, use keys under \fBmax_rec:\fP in the \fBmatch\fP section. The
-defaults are "medium" for missing and unmatched tracks and "strong" (i.e., no
+defaults are “medium” for missing and unmatched tracks and “strong” (i.e., no
maximum) for everything else:
.INDENT 0.0
.INDENT 3.5
@@ -800,7 +800,7 @@
If a recommendation is higher than the configured maximum and the indicated
penalty is applied, the recommendation is downgraded. The setting for
each field can be one of \fBnone\fP, \fBlow\fP, \fBmedium\fP or \fBstrong\fP\&. When the
-maximum recommendation is \fBstrong\fP, no "downgrading" occurs. The available
+maximum recommendation is \fBstrong\fP, no “downgrading” occurs. The available
penalty names here are:
.INDENT 0.0
.IP \(bu 2
@@ -849,15 +849,15 @@
media types.
.sp
A distance penalty will be applied if the country or media type from the match
-metadata doesn\(aqt match. The specified values are preferred in descending order
+metadata doesn’t match. The specified values are preferred in descending order
(i.e., the first item will be most preferred). Each item may be a regular
expression, and will be matched case insensitively. The number of media will
-be stripped when matching preferred media (e.g. "2x" in "2xCD").
+be stripped when matching preferred media (e.g. “2x” in “2xCD”).
.sp
You can also tell the autotagger to prefer matches that have a release year
closest to the original year for an album.
.sp
-Here\(aqs an example:
+Here’s an example:
.INDENT 0.0
.INDENT 3.5
.sp
@@ -892,7 +892,7 @@
.sp
The available penalties are the same as those for the \fI\%max_rec\fP setting.
.sp
-For example, setting \fBignored: missing_tracks\fP will skip any album matches where your audio files are missing some of the tracks. The importer will not attempt to display these matches. It does not ignore the fact that the album is missing tracks, which would allow these matches to apply more easily. To do that, you\(aqll want to adjust the penalty for missing tracks.
+For example, setting \fBignored: missing_tracks\fP will skip any album matches where your audio files are missing some of the tracks. The importer will not attempt to display these matches. It does not ignore the fact that the album is missing tracks, which would allow these matches to apply more easily. To do that, you’ll want to adjust the penalty for missing tracks.
.SS required
.sp
You can avoid matches that lack certain required information. Add the tags you
@@ -932,7 +932,7 @@
.SS ignore_data_tracks
.sp
By default, audio files contained in data tracks within a release are included
-in the album\(aqs tracklist. If you want them to be included, set it \fBno\fP\&.
+in the album’s tracklist. If you want them to be included, set it \fBno\fP\&.
.sp
Default: \fByes\fP\&.
.SS ignore_video_tracks
@@ -948,7 +948,7 @@
These settings appear under the \fBpaths:\fP key. Each string is a template
string that can refer to metadata fields like \fB$artist\fP or \fB$title\fP\&. The
filename extension is added automatically. At the moment, you can specify three
-special paths: \fBdefault\fP for most releases, \fBcomp\fP for "various artist"
+special paths: \fBdefault\fP for most releases, \fBcomp\fP for “various artist”
releases with no dominant artist, and \fBsingleton\fP for non\-album tracks. The
defaults look like this:
.INDENT 0.0
@@ -1003,7 +1003,7 @@
First, you can set the \fBBEETSDIR\fP environment variable to a directory
containing a \fBconfig.yaml\fP file. This replaces your configuration in the
default location. This also affects where auxiliary files, like the library
-database, are stored by default (that\(aqs where relative paths are resolved to).
+database, are stored by default (that’s where relative paths are resolved to).
This environment variable is useful if you need to manage multiple beets
libraries with separate configurations.
.SS Command\-Line Option
@@ -1030,11 +1030,11 @@
the environment variable is set.
.UNINDENT
.sp
-Beets uses the first directory in your platform\(aqs list that contains
+Beets uses the first directory in your platform’s list that contains
\fBconfig.yaml\fP\&. If no config file exists, the last path in the list is used.
.SH EXAMPLE
.sp
-Here\(aqs an example file:
+Here’s an example file:
.INDENT 0.0
.INDENT 3.5
.sp
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/beets-1.4.8/setup.py new/beets-1.4.9/setup.py
--- old/beets-1.4.8/setup.py 2019-05-17 02:42:57.000000000 +0200
+++ new/beets-1.4.9/setup.py 2019-05-31 00:15:09.000000000 +0200
@@ -56,7 +56,7 @@
setup(
name='beets',
- version='1.4.8',
+ version='1.4.9',
description='music tagger and library organizer',
author='Adrian Sampson',
author_email='adrian(a)radbox.org',
@@ -115,10 +115,12 @@
'rarfile',
'responses',
'pyxdg',
- 'pathlib',
'python-mpd2',
'discogs-client'
- ],
+ ] + (
+ # Tests for the thumbnails plugin need pathlib on Python 2 too.
+ ['pathlib'] if (sys.version_info < (3, 4, 0)) else []
+ ),
# Plugin (optional) dependencies:
extras_require={
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/beets-1.4.8/test/test_player.py new/beets-1.4.9/test/test_player.py
--- old/beets-1.4.8/test/test_player.py 2019-05-17 02:42:57.000000000 +0200
+++ new/beets-1.4.9/test/test_player.py 2019-05-31 00:15:09.000000000 +0200
@@ -29,6 +29,7 @@
import yaml
import tempfile
from contextlib import contextmanager
+import random
from beets.util import confit, py3_path
from beetsplug import bpd
@@ -261,12 +262,17 @@
self.unload_plugins()
@contextmanager
- def run_bpd(self, host='localhost', port=9876, password=None,
+ def run_bpd(self, host='localhost', port=None, password=None,
do_hello=True, second_client=False):
""" Runs BPD in another process, configured with the same library
database as we created in the setUp method. Exposes a client that is
connected to the server, and kills the server at the end.
"""
+ # Choose a port (randomly) to avoid conflicts between parallel
+ # tests.
+ if not port:
+ port = 9876 + random.randint(0, 10000)
+
# Create a config file:
config = {
'pluginpath': [py3_path(self.temp_dir)],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/beets-1.4.8/test/test_random.py new/beets-1.4.9/test/test_random.py
--- old/beets-1.4.8/test/test_random.py 2019-05-16 22:32:48.000000000 +0200
+++ new/beets-1.4.9/test/test_random.py 2019-05-30 15:08:39.000000000 +0200
@@ -80,3 +80,10 @@
self.assertAlmostEqual(0, median1, delta=1)
self.assertAlmostEqual(len(self.items) // 2, median2, delta=1)
self.assertGreater(stdev2, stdev1)
+
+
+def suite():
+ return unittest.TestLoader().loadTestsFromName(__name__)
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='suite')
1
0
Hello community,
here is the log from the commit of package libyami for openSUSE:Factory checked in at 2019-06-30 10:21:57
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libyami (Old)
and /work/SRC/openSUSE:Factory/.libyami.new.4615 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libyami"
Sun Jun 30 10:21:57 2019 rev:9 rq:712512 version:1.3.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/libyami/libyami.changes 2019-01-03 18:07:39.164085735 +0100
+++ /work/SRC/openSUSE:Factory/.libyami.new.4615/libyami.changes 2019-06-30 10:21:57.611662968 +0200
@@ -1,0 +2,6 @@
+Tue Jun 25 21:05:08 UTC 2019 - Bjørn Lie <bjorn.lie(a)gmail.com>
+
+- Add export CXXFLAGS="-Wno-error", needed to fix build after gcc9.
+ This needs to be fixed upstream.
+
+-------------------------------------------------------------------
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ libyami.spec ++++++
--- /var/tmp/diff_new_pack.pLwcIq/_old 2019-06-30 10:21:59.199665434 +0200
+++ /var/tmp/diff_new_pack.pLwcIq/_new 2019-06-30 10:21:59.235665491 +0200
@@ -21,6 +21,7 @@
Name: libyami
Version: 1.3.1
+### FIXME ### On next version bump, please remove export CXXFLAGS="-Wno-error" -- WIP progress upstream to fix gcc9 buildfail
Release: 0
Summary: Media Library with support for Intel hardware acceleration
License: Apache-2.0
@@ -73,6 +74,7 @@
%autosetup
%build
+export CXXFLAGS="-Wno-error"
autoreconf -fiv
%configure \
--disable-static \
1
0
Hello community,
here is the log from the commit of package ghc-yaml for openSUSE:Factory checked in at 2019-06-30 10:21:52
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-yaml (Old)
and /work/SRC/openSUSE:Factory/.ghc-yaml.new.4615 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-yaml"
Sun Jun 30 10:21:52 2019 rev:30 rq:712508 version:0.11.1.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-yaml/ghc-yaml.changes 2018-10-25 08:19:41.539982456 +0200
+++ /work/SRC/openSUSE:Factory/.ghc-yaml.new.4615/ghc-yaml.changes 2019-06-30 10:21:54.111657531 +0200
@@ -1,0 +2,9 @@
+Sat Jun 29 02:01:17 UTC 2019 - psimons(a)suse.com
+
+- Update yaml to version 0.11.1.0.
+ ## 0.11.1.0
+
+ * Better error messages in the `Data.Yaml.Config` module [#168](https://github.com/snoyberg/yaml/issues/168)
+ * Add `LoadSettingsException` exception and remove error printing from `loadYamlSettings` [#172](https://github.com/snoyberg/yaml/pull/172)
+
+-------------------------------------------------------------------
Old:
----
yaml-0.11.0.0.tar.gz
New:
----
yaml-0.11.1.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ghc-yaml.spec ++++++
--- /var/tmp/diff_new_pack.YrCj5R/_old 2019-06-30 10:21:56.539661302 +0200
+++ /var/tmp/diff_new_pack.YrCj5R/_new 2019-06-30 10:21:56.567661346 +0200
@@ -1,7 +1,7 @@
#
# spec file for package ghc-yaml
#
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -19,7 +19,7 @@
%global pkg_name yaml
%bcond_with tests
Name: ghc-%{pkg_name}
-Version: 0.11.0.0
+Version: 0.11.1.0
Release: 0
Summary: Support for parsing and rendering YAML documents
License: BSD-3-Clause
++++++ yaml-0.11.0.0.tar.gz -> yaml-0.11.1.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yaml-0.11.0.0/ChangeLog.md new/yaml-0.11.1.0/ChangeLog.md
--- old/yaml-0.11.0.0/ChangeLog.md 2018-10-12 08:00:28.000000000 +0200
+++ new/yaml-0.11.1.0/ChangeLog.md 2019-06-28 03:50:21.000000000 +0200
@@ -1,5 +1,10 @@
# ChangeLog for yaml
+## 0.11.1.0
+
+* Better error messages in the `Data.Yaml.Config` module [#168](https://github.com/snoyberg/yaml/issues/168)
+* Add `LoadSettingsException` exception and remove error printing from `loadYamlSettings` [#172](https://github.com/snoyberg/yaml/pull/172)
+
## 0.11.0.0
* Split out the `libyaml` and `Text.Libyaml` code into its own package. [#145](https://github.com/snoyberg/yaml/issues/145)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yaml-0.11.0.0/src/Data/Yaml/Config.hs new/yaml-0.11.1.0/src/Data/Yaml/Config.hs
--- old/yaml-0.11.0.0/src/Data/Yaml/Config.hs 2018-10-12 08:00:28.000000000 +0200
+++ new/yaml-0.11.1.0/src/Data/Yaml/Config.hs 2019-06-26 15:22:21.000000000 +0200
@@ -180,9 +180,7 @@
runValues <- forM runTimeFiles $ \fp -> do
eres <- YI.decodeFileEither fp
case eres of
- Left e -> do
- putStrLn $ "loadYamlSettings: Could not parse file as YAML: " ++ fp
- throwIO e
+ Left e -> throwIO (Y.LoadSettingsException fp e)
Right value -> return value
value' <-
@@ -197,9 +195,9 @@
UseCustomEnv env -> return $ applyEnvValue False env value'
RequireCustomEnv env -> return $ applyEnvValue True env value'
- case fromJSON value of
- Error s -> error $ "Could not convert to expected type: " ++ s
- Success settings -> return settings
+ case Y.parseEither parseJSON value of
+ Left s -> error $ "Could not convert to expected type: " ++ s
+ Right settings -> return settings
-- | Same as @loadYamlSettings@, but get the list of runtime config files from
-- the command line arguments.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yaml-0.11.0.0/src/Data/Yaml/Internal.hs new/yaml-0.11.1.0/src/Data/Yaml/Internal.hs
--- old/yaml-0.11.0.0/src/Data/Yaml/Internal.hs 2018-10-12 08:00:28.000000000 +0200
+++ new/yaml-0.11.1.0/src/Data/Yaml/Internal.hs 2019-06-26 15:22:21.000000000 +0200
@@ -62,6 +62,7 @@
| OtherParseException SomeException
| NonStringKeyAlias Y.AnchorName Value
| CyclicIncludes
+ | LoadSettingsException FilePath ParseException
deriving (Show, Typeable)
instance Exception ParseException where
@@ -113,6 +114,7 @@
, " Value: " ++ show value
]
CyclicIncludes -> "Cyclic includes"
+ LoadSettingsException fp exc -> "Could not parse file as YAML: " ++ fp ++ "\n" ++ prettyPrintParseException exc
defineAnchor :: Value -> String -> ReaderT JSONPath (ConduitM e o Parse) ()
defineAnchor value name = modify (modifyAnchors $ Map.insert name value)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yaml-0.11.0.0/test/Data/YamlSpec.hs new/yaml-0.11.1.0/test/Data/YamlSpec.hs
--- old/yaml-0.11.0.0/test/Data/YamlSpec.hs 2018-10-12 08:00:28.000000000 +0200
+++ new/yaml-0.11.1.0/test/Data/YamlSpec.hs 2019-02-12 09:48:15.000000000 +0100
@@ -8,6 +8,7 @@
module Data.YamlSpec (main, spec) where
import qualified Text.Libyaml as Y
+import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as B8
import Data.Int (Int64)
@@ -55,6 +56,13 @@
actual <- D.decodeThrow bs
actual `shouldBe` expected
+testEncodeWith :: Y.FormatOptions -> [Y.Event] -> IO BS.ByteString
+testEncodeWith opts es = runConduitRes (CL.sourceList events .| Y.encodeWith opts)
+ where
+ events =
+ [Y.EventStreamStart, Y.EventDocumentStart] ++ es ++
+ [Y.EventDocumentEnd, Y.EventStreamEnd]
+
main :: IO ()
main = hspec spec
@@ -205,6 +213,103 @@
go "12.3015e+02" (1230.15 :: Scientific)
go "1230.15" (1230.15 :: Scientific)
+ describe "Text.Libyaml with default tag rendering" $ do
+ let enc = testEncodeWith Y.defaultFormatOptions
+ it "elides custom sequence tags" $
+ enc taggedSequence `shouldReturn` "[]\n"
+ it "elides custom mapping tags" $
+ enc taggedMapping `shouldReturn` "{}\n"
+ it "elides default sequence tags" $
+ enc defaultTaggedSequence `shouldReturn` "[]\n"
+ it "elides default mapping tags" $
+ enc defaultTaggedMapping `shouldReturn` "{}\n"
+ it "handles NoTag on sequences" $
+ enc untaggedSequence `shouldReturn` "[]\n"
+ it "handles NoTag on mappings" $
+ enc untaggedMapping `shouldReturn` "{}\n"
+ it "handles mixed tag usages but elides all mapping and sequence tags" $
+ enc mixedTagSampleA `shouldReturn` "- {}\n"
+ it "in combination of tags, anchors and styles, outputs only the scalar tags" $
+ enc mixedTagSampleB `shouldReturn` "&a\n&b !<bar> foo: &c [&d !!null '']\n"
+ it "outputs tags when double quoted" $
+ enc [Y.EventScalar "foo" Y.StrTag Y.DoubleQuoted Nothing] `shouldReturn` "!!str \"foo\"\n"
+ it "outputs tags when single quoted" $
+ enc [Y.EventScalar "foo" Y.StrTag Y.SingleQuoted Nothing] `shouldReturn` "!!str 'foo'\n"
+ it "outputs tags on literal text" $
+ enc [Y.EventScalar "foo" Y.StrTag Y.Literal Nothing] `shouldReturn` "!!str |-\n foo\n"
+ it "outputs tags on folded text" $
+ enc [Y.EventScalar "foo" Y.StrTag Y.Folded Nothing] `shouldReturn` "!!str >-\n foo\n"
+ describe "Text.Libyaml with all tags on" $ do
+ let enc = testEncodeWith $ Y.setTagRendering Y.renderAllTags Y.defaultFormatOptions
+ it "will output custom sequence tags" $
+ enc taggedSequence `shouldReturn` "!foo []\n"
+ it "will output custom mapping tags" $
+ enc taggedMapping `shouldReturn` "!foo {}\n"
+ it "will output default sequence tags" $
+ enc defaultTaggedSequence `shouldReturn` "!!seq []\n"
+ it "will output default mapping tags" $
+ enc defaultTaggedMapping `shouldReturn` "!!map {}\n"
+ it "handles NoTag on sequences" $
+ enc untaggedSequence `shouldReturn` "[]\n"
+ it "handles NoTag on mappings" $
+ enc untaggedMapping `shouldReturn` "{}\n"
+ it "handles mixed tag usages outputting all mapping and sequence tags" $
+ enc mixedTagSampleA `shouldReturn` "- !foo {}\n"
+ it "in combination of tags, anchors and styles, outputs all the tags" $
+ enc mixedTagSampleB `shouldReturn` "&a\n&b !<bar> foo: &c !baz [&d !!null '']\n"
+ it "outputs plain tags" $
+ enc [Y.EventScalar "foo" Y.StrTag Y.Plain Nothing] `shouldReturn` "!!str foo\n"
+ it "respects PlainNoTag tags" $
+ enc [Y.EventScalar "foo" Y.StrTag Y.PlainNoTag Nothing] `shouldReturn` "foo\n"
+ describe "Text.Libyaml with uri tags on" $ do
+ let enc = testEncodeWith $ Y.setTagRendering Y.renderUriTags Y.defaultFormatOptions
+ it "will output custom sequence tags" $
+ enc taggedSequence `shouldReturn` "!foo []\n"
+ it "will output custom mapping tags" $
+ enc taggedMapping `shouldReturn` "!foo {}\n"
+ it "will output default sequence tags" $
+ enc defaultTaggedSequence `shouldReturn` "[]\n"
+ it "will output default mapping tags" $
+ enc defaultTaggedMapping `shouldReturn` "{}\n"
+ it "handles NoTag on sequences" $
+ enc untaggedSequence `shouldReturn` "[]\n"
+ it "handles NoTag on mappings" $
+ enc untaggedMapping `shouldReturn` "{}\n"
+ it "handles mixed tag usages outputting all mapping and sequence tags" $
+ enc mixedTagSampleA `shouldReturn` "- !foo {}\n"
+ it "in combination of tags, anchors and styles, outputs all the tags" $
+ enc mixedTagSampleB `shouldReturn` "&a\n&b !<bar> foo: &c !baz [&d '']\n"
+ describe "Text.Libyaml with tags off" $ do
+ let enc = testEncodeWith $ Y.setTagRendering Y.renderNoTags Y.defaultFormatOptions
+ it "outputs plain tags" $
+ enc [Y.EventScalar "foo" Y.StrTag Y.Plain Nothing] `shouldReturn` "foo\n"
+ it "respects PlainNoTag tags" $
+ enc [Y.EventScalar "foo" Y.StrTag Y.PlainNoTag Nothing] `shouldReturn` "foo\n"
+ it "elides tags when double quoted" $
+ enc [Y.EventScalar "foo" Y.StrTag Y.DoubleQuoted Nothing] `shouldReturn` "\"foo\"\n"
+ it "elides tags when single quoted" $
+ enc [Y.EventScalar "foo" Y.StrTag Y.SingleQuoted Nothing] `shouldReturn` "'foo'\n"
+ it "elides tags on literal text" $
+ enc [Y.EventScalar "foo" Y.StrTag Y.Literal Nothing] `shouldReturn` "|-\n foo\n"
+ it "elides tags on folded text" $
+ enc [Y.EventScalar "foo" Y.StrTag Y.Folded Nothing] `shouldReturn` ">-\n foo\n"
+ describe "Text.Libyaml with only UriTags set to render " $ do
+ let enc =
+ testEncodeWith $
+ Y.setTagRendering Y.renderUriTags $ Y.defaultFormatOptions
+ it "outputs only UriTags" $
+ enc
+ [ Y.EventSequenceStart Y.NoTag Y.FlowSequence Nothing
+ , Y.EventScalar "foo" Y.StrTag Y.DoubleQuoted Nothing
+ , Y.EventScalar "99" Y.IntTag Y.Plain Nothing
+ , Y.EventScalar "99.99" Y.FloatTag Y.Plain Nothing
+ , Y.EventScalar "bar" Y.NoTag Y.Plain Nothing
+ , Y.EventScalar "foo" (Y.UriTag "!foo") Y.DoubleQuoted Nothing
+ , Y.EventScalar "foo" (Y.UriTag "!foo") Y.Plain Nothing
+ , Y.EventSequenceEnd
+ ] `shouldReturn`
+ "[\"foo\", 99, 99.99, bar, !foo \"foo\", !foo foo]\n"
+
specialStrings :: [T.Text]
specialStrings =
[ "fo\"o"
@@ -622,3 +727,50 @@
D.encodeFile fp val
res <- D.decodeFileEither fp
either (Left . show) Right res `shouldBe` Right val
+
+
+taggedSequence :: [Y.Event]
+taggedSequence =
+ [ Y.EventSequenceStart (Y.UriTag "!foo") Y.FlowSequence Nothing
+ , Y.EventSequenceEnd
+ ]
+
+taggedMapping :: [Y.Event]
+taggedMapping =
+ [ Y.EventMappingStart (Y.UriTag "!foo") Y.FlowMapping Nothing
+ , Y.EventMappingEnd
+ ]
+
+defaultTaggedSequence :: [Y.Event]
+defaultTaggedSequence =
+ [Y.EventSequenceStart Y.SeqTag Y.FlowSequence Nothing, Y.EventSequenceEnd]
+
+defaultTaggedMapping :: [Y.Event]
+defaultTaggedMapping =
+ [Y.EventMappingStart Y.MapTag Y.FlowMapping Nothing, Y.EventMappingEnd]
+
+untaggedSequence :: [Y.Event]
+untaggedSequence =
+ [Y.EventSequenceStart Y.NoTag Y.FlowSequence Nothing, Y.EventSequenceEnd]
+
+untaggedMapping :: [Y.Event]
+untaggedMapping =
+ [Y.EventMappingStart Y.NoTag Y.FlowMapping Nothing, Y.EventMappingEnd]
+
+mixedTagSampleA :: [Y.Event]
+mixedTagSampleA =
+ [ Y.EventSequenceStart Y.NoTag Y.BlockSequence Nothing
+ , Y.EventMappingStart (Y.UriTag "!foo") Y.FlowMapping Nothing
+ , Y.EventMappingEnd
+ , Y.EventSequenceEnd
+ ]
+
+mixedTagSampleB :: [Y.Event]
+mixedTagSampleB =
+ [ Y.EventMappingStart Y.NoTag Y.BlockMapping (Just "a")
+ , Y.EventScalar "foo" (Y.UriTag "bar") Y.Plain (Just "b")
+ , Y.EventSequenceStart (Y.UriTag "!baz") Y.FlowSequence (Just "c")
+ , Y.EventScalar "" Y.NullTag Y.Plain (Just "d")
+ , Y.EventSequenceEnd
+ , Y.EventMappingEnd
+ ]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yaml-0.11.0.0/yaml.cabal new/yaml-0.11.1.0/yaml.cabal
--- old/yaml-0.11.0.0/yaml.cabal 2018-10-12 08:00:36.000000000 +0200
+++ new/yaml-0.11.1.0/yaml.cabal 2019-06-26 15:23:29.000000000 +0200
@@ -1,13 +1,13 @@
cabal-version: 1.12
--- This file has been generated from package.yaml by hpack version 0.30.0.
+-- This file has been generated from package.yaml by hpack version 0.31.2.
--
-- see: https://github.com/sol/hpack
--
--- hash: 44126ede97b8c2576f72b255726cbc3a06a12e3547a02cceca6e02c4933029cc
+-- hash: 3a4f2b1c1a7a978d5810ea6223b95b1c51f38f60610704c35e28f8bc667081ba
name: yaml
-version: 0.11.0.0
+version: 0.11.1.0
synopsis: Support for parsing and rendering YAML documents.
description: README and API documentation are available at <https://www.stackage.org/package/yaml>
category: Data
1
0
Hello community,
here is the log from the commit of package ghc-unix-time for openSUSE:Factory checked in at 2019-06-30 10:21:48
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-unix-time (Old)
and /work/SRC/openSUSE:Factory/.ghc-unix-time.new.4615 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-unix-time"
Sun Jun 30 10:21:48 2019 rev:13 rq:712507 version:0.4.7
Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-unix-time/ghc-unix-time.changes 2019-06-19 21:13:07.514784761 +0200
+++ /work/SRC/openSUSE:Factory/.ghc-unix-time.new.4615/ghc-unix-time.changes 2019-06-30 10:21:49.219649931 +0200
@@ -1,0 +2,6 @@
+Wed Jun 19 11:46:01 UTC 2019 - psimons(a)suse.com
+
+- Update unix-time to version 0.4.7.
+ Upstream does not provide a change log file.
+
+-------------------------------------------------------------------
Old:
----
unix-time-0.4.6.tar.gz
New:
----
unix-time-0.4.7.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ghc-unix-time.spec ++++++
--- /var/tmp/diff_new_pack.Wmsf97/_old 2019-06-30 10:21:50.735652286 +0200
+++ /var/tmp/diff_new_pack.Wmsf97/_new 2019-06-30 10:21:50.735652286 +0200
@@ -19,7 +19,7 @@
%global pkg_name unix-time
%bcond_with tests
Name: ghc-%{pkg_name}
-Version: 0.4.6
+Version: 0.4.7
Release: 0
Summary: Unix time parser/formatter and utilities
License: BSD-3-Clause
++++++ unix-time-0.4.6.tar.gz -> unix-time-0.4.7.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unix-time-0.4.6/Data/UnixTime/Conv.hs new/unix-time-0.4.7/Data/UnixTime/Conv.hs
--- old/unix-time-0.4.6/Data/UnixTime/Conv.hs 2019-06-13 05:15:06.000000000 +0200
+++ new/unix-time-0.4.7/Data/UnixTime/Conv.hs 2019-06-18 09:45:05.000000000 +0200
@@ -71,6 +71,7 @@
-- This is a wrapper for strftime_l().
-- 'utMicroSeconds' is ignored.
-- The result depends on the TZ environment variable.
+--
formatUnixTime :: Format -> UnixTime -> IO ByteString
formatUnixTime fmt t =
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unix-time-0.4.6/cbits/conv.c new/unix-time-0.4.7/cbits/conv.c
--- old/unix-time-0.4.6/cbits/conv.c 2019-06-13 05:15:06.000000000 +0200
+++ new/unix-time-0.4.7/cbits/conv.c 2019-06-18 09:45:05.000000000 +0200
@@ -50,7 +50,7 @@
char *tz;
tz = getenv("TZ");
#if defined(_WIN32)
- _patch_setenv("TZ", "", 1);
+ _patch_setenv("TZ", "UTC", 1);
#else
setenv("TZ", "", 1);
#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unix-time-0.4.6/cbits/strftime.c new/unix-time-0.4.7/cbits/strftime.c
--- old/unix-time-0.4.6/cbits/strftime.c 2019-06-13 05:15:06.000000000 +0200
+++ new/unix-time-0.4.7/cbits/strftime.c 2019-06-18 09:45:05.000000000 +0200
@@ -522,7 +522,8 @@
#ifdef ALTZONE
diff = -altzone;
#else /* !defined ALTZONE */
- continue;
+ // Fix the daylight saving time, see #54.
+ diff = -(_timezone - 3600 * t->tm_isdst);
#endif /* !defined ALTZONE */
#endif /* !defined TM_GMTOFF */
if (diff < 0) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unix-time-0.4.6/cbits/win_patch.c new/unix-time-0.4.7/cbits/win_patch.c
--- old/unix-time-0.4.6/cbits/win_patch.c 2019-06-13 05:15:06.000000000 +0200
+++ new/unix-time-0.4.7/cbits/win_patch.c 2019-06-18 09:45:05.000000000 +0200
@@ -100,18 +100,26 @@
};
-int _patch_setenv(const char *var, const char *val, int ovr) {
- BOOL b = SetEnvironmentVariableA(var, val);
- if (b) {
- return 0;
- } else {
- return 1;
+int _patch_setenv(const char *var, const char *val, int _ovr) {
+ if (val == NULL) {
+ return _patch_unsetenv(var);
}
+ int varlen = strlen(var);
+ int vallen = strlen(val);
+ int len = varlen + vallen + 2;
+ char *sname = (char *)malloc(len);
+ strcpy(sname, var);
+ sname[varlen] = '=';
+ strcpy(sname + varlen + 1, val);
+ sname[varlen + vallen + 1] = '\0';
+ int r = _putenv(sname);
+ free(sname);
+ return r;
}
int _patch_unsetenv(const char *name) {
- int len = strlen(name);
- char *sname = (char *)malloc(len + 2);
+ int len = strlen(name) + 2;
+ char *sname = (char *)malloc(len);
strcpy(sname, name);
sname[len] = '=';
sname[len + 1] = '\0';
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unix-time-0.4.6/unix-time.cabal new/unix-time-0.4.7/unix-time.cabal
--- old/unix-time-0.4.6/unix-time.cabal 2019-06-13 05:15:06.000000000 +0200
+++ new/unix-time-0.4.7/unix-time.cabal 2019-06-18 09:45:05.000000000 +0200
@@ -1,5 +1,5 @@
Name: unix-time
-Version: 0.4.6
+Version: 0.4.7
Author: Kazu Yamamoto <kazu(a)iij.ad.jp>
Maintainer: Kazu Yamamoto <kazu(a)iij.ad.jp>
License: BSD3
1
0
Hello community,
here is the log from the commit of package ghc-typed-process for openSUSE:Factory checked in at 2019-06-30 10:21:45
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-typed-process (Old)
and /work/SRC/openSUSE:Factory/.ghc-typed-process.new.4615 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-typed-process"
Sun Jun 30 10:21:45 2019 rev:9 rq:712506 version:0.2.5.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-typed-process/ghc-typed-process.changes 2019-06-12 13:18:54.952562159 +0200
+++ /work/SRC/openSUSE:Factory/.ghc-typed-process.new.4615/ghc-typed-process.changes 2019-06-30 10:21:46.835646227 +0200
@@ -1,0 +2,12 @@
+Thu Jun 27 02:02:48 UTC 2019 - psimons(a)suse.com
+
+- Update typed-process to version 0.2.5.0.
+ # ChangeLog for typed-process
+
+ ## 0.2.5.0
+
+ * Add a `nullStream` [#24](https://github.com/fpco/typed-process/pull/24)
+ * Add `withProcessWait`, `withProcessWait_`, `withProcessTerm`, and `withProcessTerm_`
+ [#25](https://github.com/fpco/typed-process/issues/25)
+
+-------------------------------------------------------------------
Old:
----
typed-process-0.2.4.1.tar.gz
New:
----
typed-process-0.2.5.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ghc-typed-process.spec ++++++
--- /var/tmp/diff_new_pack.FuVQeV/_old 2019-06-30 10:21:47.447647178 +0200
+++ /var/tmp/diff_new_pack.FuVQeV/_new 2019-06-30 10:21:47.451647184 +0200
@@ -19,7 +19,7 @@
%global pkg_name typed-process
%bcond_with tests
Name: ghc-%{pkg_name}
-Version: 0.2.4.1
+Version: 0.2.5.0
Release: 0
Summary: Run external processes, with strong typing of streams
License: MIT
++++++ typed-process-0.2.4.1.tar.gz -> typed-process-0.2.5.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/typed-process-0.2.4.1/ChangeLog.md new/typed-process-0.2.5.0/ChangeLog.md
--- old/typed-process-0.2.4.1/ChangeLog.md 2019-06-05 18:52:45.000000000 +0200
+++ new/typed-process-0.2.5.0/ChangeLog.md 2019-06-26 06:52:47.000000000 +0200
@@ -1,3 +1,11 @@
+# ChangeLog for typed-process
+
+## 0.2.5.0
+
+* Add a `nullStream` [#24](https://github.com/fpco/typed-process/pull/24)
+* Add `withProcessWait`, `withProcessWait_`, `withProcessTerm`, and `withProcessTerm_`
+ [#25](https://github.com/fpco/typed-process/issues/25)
+
## 0.2.4.1
* Fix a `Handle` leak in `withProcessInterleave` and its derivatives.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/typed-process-0.2.4.1/src/System/Process/Typed/Internal.hs new/typed-process-0.2.5.0/src/System/Process/Typed/Internal.hs
--- old/typed-process-0.2.4.1/src/System/Process/Typed/Internal.hs 1970-01-01 01:00:00.000000000 +0100
+++ new/typed-process-0.2.5.0/src/System/Process/Typed/Internal.hs 2019-06-25 10:03:14.000000000 +0200
@@ -0,0 +1,12 @@
+{-# LANGUAGE CPP #-}
+module System.Process.Typed.Internal (
+ nullDevice
+) where
+
+-- | The name of the system null device
+nullDevice :: FilePath
+#if WINDOWS
+nullDevice = "\\\\.\\NUL"
+#else
+nullDevice = "/dev/null"
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/typed-process-0.2.4.1/src/System/Process/Typed.hs new/typed-process-0.2.5.0/src/System/Process/Typed.hs
--- old/typed-process-0.2.4.1/src/System/Process/Typed.hs 2019-06-05 18:52:45.000000000 +0200
+++ new/typed-process-0.2.5.0/src/System/Process/Typed.hs 2019-06-26 06:52:47.000000000 +0200
@@ -4,6 +4,7 @@
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveFunctor #-}
+{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
-- | Please see the README.md file for examples of using this API.
module System.Process.Typed
@@ -44,6 +45,7 @@
-- * Stream specs
, mkStreamSpec
, inherit
+ , nullStream
, closed
, byteStringInput
, byteStringOutput
@@ -54,6 +56,10 @@
-- * Launch a process
, startProcess
, stopProcess
+ , withProcessWait
+ , withProcessWait_
+ , withProcessTerm
+ , withProcessTerm_
, withProcess
, withProcess_
, readProcess
@@ -96,12 +102,13 @@
import Control.Monad.IO.Class
import qualified System.Process as P
import Data.Typeable (Typeable)
-import System.IO (Handle, hClose)
+import System.IO (Handle, hClose, IOMode(ReadWriteMode), withBinaryFile)
import System.IO.Error (isPermissionError)
import Control.Concurrent (threadDelay)
import Control.Concurrent.Async (async, cancel, waitCatch)
import Control.Concurrent.STM (newEmptyTMVarIO, atomically, putTMVar, TMVar, readTMVar, tryReadTMVar, STM, tryPutTMVar, throwSTM, catchSTM)
import System.Exit (ExitCode (ExitSuccess))
+import System.Process.Typed.Internal
import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString.Lazy.Char8 as L8
import Data.String (IsString (fromString))
@@ -205,7 +212,7 @@
--
-- @since 0.1.0.0
data StreamSpec (streamType :: StreamType) a = StreamSpec
- { ssStream :: !P.StdStream
+ { ssStream :: !(forall b. (P.StdStream -> IO b) -> IO b)
, ssCreate :: !(ProcessConfig () () () -> Maybe Handle -> Cleanup a)
}
deriving Functor
@@ -490,7 +497,15 @@
mkStreamSpec :: P.StdStream
-> (ProcessConfig () () () -> Maybe Handle -> IO (a, IO ()))
-> StreamSpec streamType a
-mkStreamSpec ss f = StreamSpec ss (\pc mh -> Cleanup (f pc mh))
+mkStreamSpec ss f = mkManagedStreamSpec ($ ss) f
+
+-- | Create a new 'StreamSpec' from a function that accepts a
+-- 'P.StdStream' and a helper function. This function is the same as
+-- the helper in 'mkStreamSpec'
+mkManagedStreamSpec :: (forall b. (P.StdStream -> IO b) -> IO b)
+ -> (ProcessConfig () () () -> Maybe Handle -> IO (a, IO ()))
+ -> StreamSpec streamType a
+mkManagedStreamSpec ss f = StreamSpec ss (\pc mh -> Cleanup (f pc mh))
-- | A stream spec which simply inherits the stream of the parent
-- process.
@@ -499,7 +514,25 @@
inherit :: StreamSpec anyStreamType ()
inherit = mkStreamSpec P.Inherit (\_ Nothing -> pure ((), return ()))
+-- | A stream spec which is empty when used for for input and discards
+-- output. Note this requires your platform's null device to be
+-- available when the process is started.
+--
+-- @since 0.2.5.0
+nullStream :: StreamSpec anyStreamType ()
+nullStream = mkManagedStreamSpec opener cleanup
+ where
+ opener f =
+ withBinaryFile nullDevice ReadWriteMode $ \handle ->
+ f (P.UseHandle handle)
+ cleanup _ _ =
+ pure ((), return ())
+
-- | A stream spec which will close the stream for the child process.
+-- You usually do not want to use this, as it will leave the
+-- corresponding file descriptor unassigned and hence available for
+-- re-use in the child process. Prefer 'nullStream' unless you're
+-- certain you want this behavior.
--
-- @since 0.1.0.0
closed :: StreamSpec anyStreamType ()
@@ -595,100 +628,104 @@
=> ProcessConfig stdin stdout stderr
-> m (Process stdin stdout stderr)
startProcess pConfig'@ProcessConfig {..} = liftIO $ do
- let cp0 =
- case pcCmdSpec of
- P.ShellCommand cmd -> P.shell cmd
- P.RawCommand cmd args -> P.proc cmd args
- cp = cp0
- { P.std_in = ssStream pcStdin
- , P.std_out = ssStream pcStdout
- , P.std_err = ssStream pcStderr
- , P.cwd = pcWorkingDir
- , P.env = pcEnv
- , P.close_fds = pcCloseFds
- , P.create_group = pcCreateGroup
- , P.delegate_ctlc = pcDelegateCtlc
+ ssStream pcStdin $ \realStdin ->
+ ssStream pcStdout $ \realStdout ->
+ ssStream pcStderr $ \realStderr -> do
+
+ let cp0 =
+ case pcCmdSpec of
+ P.ShellCommand cmd -> P.shell cmd
+ P.RawCommand cmd args -> P.proc cmd args
+ cp = cp0
+ { P.std_in = realStdin
+ , P.std_out = realStdout
+ , P.std_err = realStderr
+ , P.cwd = pcWorkingDir
+ , P.env = pcEnv
+ , P.close_fds = pcCloseFds
+ , P.create_group = pcCreateGroup
+ , P.delegate_ctlc = pcDelegateCtlc
#if MIN_VERSION_process(1, 3, 0)
- , P.detach_console = pcDetachConsole
- , P.create_new_console = pcCreateNewConsole
- , P.new_session = pcNewSession
+ , P.detach_console = pcDetachConsole
+ , P.create_new_console = pcCreateNewConsole
+ , P.new_session = pcNewSession
#endif
#if MIN_VERSION_process(1, 4, 0) && !WINDOWS
- , P.child_group = pcChildGroup
- , P.child_user = pcChildUser
+ , P.child_group = pcChildGroup
+ , P.child_user = pcChildUser
#endif
- }
+ }
- (minH, moutH, merrH, pHandle) <- P.createProcess_ "startProcess" cp
+ (minH, moutH, merrH, pHandle) <- P.createProcess_ "startProcess" cp
- ((pStdin, pStdout, pStderr), pCleanup1) <- runCleanup $ (,,)
- <$> ssCreate pcStdin pConfig minH
- <*> ssCreate pcStdout pConfig moutH
- <*> ssCreate pcStderr pConfig merrH
-
- pExitCode <- newEmptyTMVarIO
- waitingThread <- async $ do
- ec <-
- if multiThreadedRuntime
- then P.waitForProcess pHandle
- else do
- switchTime <- fromIntegral . (`div` 1000) . ctxtSwitchTime
- <$> getConcFlags
- let minDelay = 1
- maxDelay = max minDelay switchTime
- loop delay = do
- threadDelay delay
- mec <- P.getProcessExitCode pHandle
- case mec of
- Nothing -> loop $ min maxDelay (delay * 2)
- Just ec -> pure ec
- loop minDelay
- atomically $ putTMVar pExitCode ec
- return ec
-
- let pCleanup = pCleanup1 `finally` do
- -- First: stop calling waitForProcess, so that we can
- -- avoid race conditions where the process is removed from
- -- the system process table while we're trying to
- -- terminate it.
- cancel waitingThread
-
- -- Now check if the process had already exited
- eec <- waitCatch waitingThread
-
- case eec of
- -- Process already exited, nothing to do
- Right _ec -> return ()
-
- -- Process didn't exit yet, let's terminate it and
- -- then call waitForProcess ourselves
- Left _ -> do
- eres <- try $ P.terminateProcess pHandle
- ec <-
- case eres of
- Left e
- -- On Windows, with the single-threaded runtime, it
- -- seems that if a process has already exited, the
- -- call to terminateProcess will fail with a
- -- permission denied error. To work around this, we
- -- catch this exception and then immediately
- -- waitForProcess. There's a chance that there may be
- -- other reasons for this permission error to appear,
- -- in which case this code may allow us to wait too
- -- long for a child process instead of erroring out.
- -- Recommendation: always use the multi-threaded
- -- runtime!
- | isPermissionError e && not multiThreadedRuntime && isWindows ->
- P.waitForProcess pHandle
- | otherwise -> throwIO e
- Right () -> P.waitForProcess pHandle
- success <- atomically $ tryPutTMVar pExitCode ec
- evaluate $ assert success ()
+ ((pStdin, pStdout, pStderr), pCleanup1) <- runCleanup $ (,,)
+ <$> ssCreate pcStdin pConfig minH
+ <*> ssCreate pcStdout pConfig moutH
+ <*> ssCreate pcStderr pConfig merrH
+
+ pExitCode <- newEmptyTMVarIO
+ waitingThread <- async $ do
+ ec <-
+ if multiThreadedRuntime
+ then P.waitForProcess pHandle
+ else do
+ switchTime <- fromIntegral . (`div` 1000) . ctxtSwitchTime
+ <$> getConcFlags
+ let minDelay = 1
+ maxDelay = max minDelay switchTime
+ loop delay = do
+ threadDelay delay
+ mec <- P.getProcessExitCode pHandle
+ case mec of
+ Nothing -> loop $ min maxDelay (delay * 2)
+ Just ec -> pure ec
+ loop minDelay
+ atomically $ putTMVar pExitCode ec
+ return ec
+
+ let pCleanup = pCleanup1 `finally` do
+ -- First: stop calling waitForProcess, so that we can
+ -- avoid race conditions where the process is removed from
+ -- the system process table while we're trying to
+ -- terminate it.
+ cancel waitingThread
+
+ -- Now check if the process had already exited
+ eec <- waitCatch waitingThread
+
+ case eec of
+ -- Process already exited, nothing to do
+ Right _ec -> return ()
+
+ -- Process didn't exit yet, let's terminate it and
+ -- then call waitForProcess ourselves
+ Left _ -> do
+ eres <- try $ P.terminateProcess pHandle
+ ec <-
+ case eres of
+ Left e
+ -- On Windows, with the single-threaded runtime, it
+ -- seems that if a process has already exited, the
+ -- call to terminateProcess will fail with a
+ -- permission denied error. To work around this, we
+ -- catch this exception and then immediately
+ -- waitForProcess. There's a chance that there may be
+ -- other reasons for this permission error to appear,
+ -- in which case this code may allow us to wait too
+ -- long for a child process instead of erroring out.
+ -- Recommendation: always use the multi-threaded
+ -- runtime!
+ | isPermissionError e && not multiThreadedRuntime && isWindows ->
+ P.waitForProcess pHandle
+ | otherwise -> throwIO e
+ Right () -> P.waitForProcess pHandle
+ success <- atomically $ tryPutTMVar pExitCode ec
+ evaluate $ assert success ()
- return Process {..}
+ return Process {..}
where
pConfig = clearStreams pConfig'
@@ -717,27 +754,73 @@
-- | Uses the bracket pattern to call 'startProcess' and ensures that
-- 'stopProcess' is called.
--
--- In version 0.2.0.0, this function was monomorphized to @IO@ to
--- avoid a dependency on the exceptions package.
+-- This function is usually /not/ what you want. You're likely better
+-- off using 'withProcessWait'. See
+-- <https://github.com/fpco/typed-process/issues/25>.
+--
+-- @since 0.2.5.0
+withProcessTerm
+ :: ProcessConfig stdin stdout stderr
+ -> (Process stdin stdout stderr -> IO a)
+ -> IO a
+withProcessTerm config = bracket (startProcess config) stopProcess
+
+-- | Uses the bracket pattern to call 'startProcess'. Unlike
+-- 'withProcessTerm', this function will wait for the child process to
+-- exit, and only kill it with 'stopProcess' in the event that the
+-- inner function throws an exception.
+--
+-- @since 0.2.5.0
+withProcessWait
+ :: ProcessConfig stdin stdout stderr
+ -> (Process stdin stdout stderr -> IO a)
+ -> IO a
+withProcessWait config f =
+ bracket
+ (startProcess config)
+ stopProcess
+ (\p -> f p <* waitExitCode p)
+
+-- | Deprecated synonym for 'withProcessTerm'.
--
-- @since 0.1.0.0
withProcess :: ProcessConfig stdin stdout stderr
-> (Process stdin stdout stderr -> IO a)
-> IO a
-withProcess config = bracket (startProcess config) stopProcess
+withProcess = withProcessTerm
+{-# DEPRECATED withProcess "Please consider using withProcessWait, or instead use withProcessTerm" #-}
--- | Same as 'withProcess', but also calls 'checkExitCode'
+-- | Same as 'withProcessTerm', but also calls 'checkExitCode'
--
--- In version 0.2.0.0, this function was monomorphized to @IO@ to
--- avoid a dependency on the exceptions package.
+-- @since 0.2.5.0
+withProcessTerm_
+ :: ProcessConfig stdin stdout stderr
+ -> (Process stdin stdout stderr -> IO a)
+ -> IO a
+withProcessTerm_ config = bracket
+ (startProcess config)
+ (\p -> stopProcess p `finally` checkExitCode p)
+
+-- | Same as 'withProcessWait', but also calls 'checkExitCode'
+--
+-- @since 0.2.5.0
+withProcessWait_
+ :: ProcessConfig stdin stdout stderr
+ -> (Process stdin stdout stderr -> IO a)
+ -> IO a
+withProcessWait_ config f = bracket
+ (startProcess config)
+ stopProcess
+ (\p -> f p <* checkExitCode p)
+
+-- | Deprecated synonym for 'withProcessTerm_'.
--
-- @since 0.1.0.0
withProcess_ :: ProcessConfig stdin stdout stderr
-> (Process stdin stdout stderr -> IO a)
-> IO a
-withProcess_ config = bracket
- (startProcess config)
- (\p -> stopProcess p `finally` checkExitCode p)
+withProcess_ = withProcessTerm_
+{-# DEPRECATED withProcess_ "Please consider using withProcessWait_, or instead use withProcessTerm_" #-}
-- | Run a process, capture its standard output and error as a
-- 'L.ByteString', wait for it to complete, and then return its exit
@@ -762,6 +845,8 @@
-- | Same as 'readProcess', but instead of returning the 'ExitCode',
-- checks it with 'checkExitCode'.
--
+-- Exceptions thrown by this function will include stdout and stderr.
+--
-- @since 0.1.0.0
readProcess_ :: MonadIO m
=> ProcessConfig stdin stdoutIgnored stderrIgnored
@@ -796,6 +881,8 @@
-- | Same as 'readProcessStdout', but instead of returning the
-- 'ExitCode', checks it with 'checkExitCode'.
--
+-- Exceptions thrown by this function will include stdout.
+--
-- @since 0.2.1.0
readProcessStdout_
:: MonadIO m
@@ -829,6 +916,8 @@
-- | Same as 'readProcessStderr', but instead of returning the
-- 'ExitCode', checks it with 'checkExitCode'.
--
+-- Exceptions thrown by this function will include stderr.
+--
-- @since 0.2.1.0
readProcessStderr_
:: MonadIO m
@@ -883,6 +972,8 @@
-- | Same as 'readProcessInterleaved', but instead of returning the 'ExitCode',
-- checks it with 'checkExitCode'.
--
+-- Exceptions thrown by this function will include stdout.
+--
-- @since 0.2.4.0
readProcessInterleaved_
:: MonadIO m
@@ -942,6 +1033,9 @@
-- | Wait for a process to exit, and ensure that it exited
-- successfully. If not, throws an 'ExitCodeException'.
--
+-- Exceptions thrown by this function will not include stdout or stderr (This prevents unbounded memory usage from reading them into memory).
+-- However, some callers such as 'readProcess_' catch the exception, add the stdout and stderr, and rethrow.
+--
-- @since 0.1.0.0
checkExitCode :: MonadIO m => Process stdin stdout stderr -> m ()
checkExitCode = liftIO . atomically . checkExitCodeSTM
@@ -991,6 +1085,9 @@
-- exit code. Note that 'checkExitCode' is called by other functions
-- as well, like 'runProcess_' or 'readProcess_'.
--
+-- Note that several functions that throw an 'ExitCodeException' intentionally do not populate 'eceStdout' or 'eceStderr'.
+-- This prevents unbounded memory usage for large stdout and stderrs.
+--
-- @since 0.1.0.0
data ExitCodeException = ExitCodeException
{ eceExitCode :: ExitCode
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/typed-process-0.2.4.1/test/System/Process/TypedSpec.hs new/typed-process-0.2.5.0/test/System/Process/TypedSpec.hs
--- old/typed-process-0.2.4.1/test/System/Process/TypedSpec.hs 2019-02-28 12:46:45.000000000 +0100
+++ new/typed-process-0.2.5.0/test/System/Process/TypedSpec.hs 2019-06-26 06:52:47.000000000 +0200
@@ -3,6 +3,7 @@
module System.Process.TypedSpec (spec) where
import System.Process.Typed
+import System.Process.Typed.Internal
import System.IO
import Control.Concurrent.Async (Concurrently (..))
import Control.Concurrent.STM (atomically)
@@ -21,12 +22,36 @@
spec :: Spec
spec = do
+ -- This is mainly to make sure we use the right device filename on Windows
+ it "Null device is accessible" $ do
+ withBinaryFile nullDevice WriteMode $ \fp -> do
+ hPutStrLn fp "Hello world"
+ withBinaryFile nullDevice ReadMode $ \fp -> do
+ atEnd <- hIsEOF fp
+ atEnd `shouldBe` True
+
it "bytestring stdin" $ do
let bs :: IsString s => s
bs = "this is a test"
res <- readProcess (setStdin bs "cat")
res `shouldBe` (ExitSuccess, bs, "")
+ it "null stdin" $ do
+ res <- readProcess (setStdin nullStream "cat")
+ res `shouldBe` (ExitSuccess, "", "")
+
+ it "null stdout" $ do
+ -- In particular, writing to that doesn't terminate the process with an error
+ bs <- readProcessStderr_ $ setStdout nullStream $ setStdin nullStream $
+ proc "sh" ["-c", "echo hello; echo world >&2"]
+ bs `shouldBe` "world\n"
+
+ it "null stderr" $ do
+ -- In particular, writing to that doesn't terminate the process with an error
+ bs <- readProcessStdout_ $ setStderr nullStream $ setStdin nullStream $
+ proc "sh" ["-c", "echo hello >&2; echo world"]
+ bs `shouldBe` "world\n"
+
it "useHandleOpen" $ withSystemTempFile "use-handle-open" $ \fp h -> do
let bs :: IsString s => s
bs = "this is a test 2"
@@ -74,7 +99,7 @@
runProcess_ "false" `shouldThrow` \ExitCodeException{} -> True
it "async" $ withSystemTempFile "httpbin" $ \fp h -> do
- lbs <- withProcess (setStdin createPipe $ setStdout byteStringOutput "base64") $ \p ->
+ lbs <- withProcessWait (setStdin createPipe $ setStdout byteStringOutput "base64") $ \p ->
runConcurrently $
Concurrently (do
bs <- S.readFile "README.md"
@@ -87,6 +112,31 @@
raw <- S.readFile fp
encoded `shouldBe` B64.encode raw
+ describe "withProcessWait" $ do
+ it "succeeds with sleep" $ do
+ p <- withProcessWait (proc "sleep" ["1"]) pure
+ checkExitCode p
+
+ describe "withProcessWait_" $ do
+ it "succeeds with sleep" $ do
+ withProcessWait_ (proc "sleep" ["1"]) $ const $ pure ()
+
+ -- These tests fail on older GHCs/process package versions
+ -- because, apparently, waitForProcess isn't interruptible. See
+ -- https://github.com/fpco/typed-process/pull/26#issuecomment-505702573.
+
+ {-
+ describe "withProcessTerm" $ do
+ it "fails with sleep" $ do
+ p <- withProcessTerm (proc "sleep" ["1"]) pure
+ checkExitCode p `shouldThrow` anyException
+
+ describe "withProcessTerm_" $ do
+ it "fails with sleep" $
+ withProcessTerm_ (proc "sleep" ["1"]) (const $ pure ())
+ `shouldThrow` anyException
+ -}
+
it "interleaved output" $ withSystemTempFile "interleaved-output" $ \fp h -> do
S.hPut h "\necho 'stdout'\n>&2 echo 'stderr'\necho 'stdout'"
hClose h
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/typed-process-0.2.4.1/typed-process.cabal new/typed-process-0.2.5.0/typed-process.cabal
--- old/typed-process-0.2.4.1/typed-process.cabal 2019-06-07 12:37:33.000000000 +0200
+++ new/typed-process-0.2.5.0/typed-process.cabal 2019-06-25 10:04:51.000000000 +0200
@@ -1,13 +1,13 @@
cabal-version: 1.12
--- This file has been generated from package.yaml by hpack version 0.31.1.
+-- This file has been generated from package.yaml by hpack version 0.31.2.
--
-- see: https://github.com/sol/hpack
--
--- hash: 377b4644a4d63eb0b81f60f4e7ec4b477eae658e463f90a600c923053da58712
+-- hash: ad27eee8ecda9f23b7e99ea05885ad76c916b5210115a132a56a28c79437d01c
name: typed-process
-version: 0.2.4.1
+version: 0.2.5.0
synopsis: Run external processes, with strong typing of streams
description: Please see the tutorial at <https://haskell-lang.org/library/typed-process>
category: System
@@ -29,6 +29,7 @@
library
exposed-modules:
System.Process.Typed
+ System.Process.Typed.Internal
other-modules:
Paths_typed_process
hs-source-dirs:
1
0
Hello community,
here is the log from the commit of package ghc-microlens-th for openSUSE:Factory checked in at 2019-06-30 10:21:43
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-microlens-th (Old)
and /work/SRC/openSUSE:Factory/.ghc-microlens-th.new.4615 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-microlens-th"
Sun Jun 30 10:21:43 2019 rev:11 rq:712505 version:0.4.3.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-microlens-th/ghc-microlens-th.changes 2019-06-19 21:12:31.146749426 +0200
+++ /work/SRC/openSUSE:Factory/.ghc-microlens-th.new.4615/ghc-microlens-th.changes 2019-06-30 10:21:44.419642474 +0200
@@ -1,0 +2,17 @@
+Fri Jun 21 02:03:05 UTC 2019 - psimons(a)suse.com
+
+- Update microlens-th to version 0.4.3.1.
+ # 0.4.3.1
+
+ * No more conditional `Safe` (see [#122](https://github.com/monadfix/microlens/issues/122)).
+
+-------------------------------------------------------------------
+Wed Jun 19 11:46:07 UTC 2019 - psimons(a)suse.com
+
+- Update microlens-th to version 0.4.3.
+ Upstream has edited the change log file since the last release in
+ a non-trivial way, i.e. they did more than just add a new entry
+ at the top. You can review the file at:
+ http://hackage.haskell.org/package/microlens-th-0.4.3/src/CHANGELOG.md
+
+-------------------------------------------------------------------
Old:
----
microlens-th-0.4.2.3.tar.gz
microlens-th.cabal
New:
----
microlens-th-0.4.3.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ghc-microlens-th.spec ++++++
--- /var/tmp/diff_new_pack.pfSpvY/_old 2019-06-30 10:21:45.179643654 +0200
+++ /var/tmp/diff_new_pack.pfSpvY/_new 2019-06-30 10:21:45.183643660 +0200
@@ -19,14 +19,13 @@
%global pkg_name microlens-th
%bcond_with tests
Name: ghc-%{pkg_name}
-Version: 0.4.2.3
+Version: 0.4.3.1
Release: 0
Summary: Automatic generation of record lenses for microlens
License: BSD-3-Clause
Group: Development/Libraries/Haskell
URL: https://hackage.haskell.org/package/%{pkg_name}
Source0: https://hackage.haskell.org/package/%{pkg_name}-%{version}/%{pkg_name}-%{ve…
-Source1: https://hackage.haskell.org/package/%{pkg_name}-%{version}/revision/1.cabal…
BuildRequires: ghc-Cabal-devel
BuildRequires: ghc-containers-devel
BuildRequires: ghc-microlens-devel
@@ -42,8 +41,8 @@
microlens).
This package is a part of the <http://hackage.haskell.org/package/microlens
-microlens> family; see the readme <https://github.com/aelve/microlens#readme on
-Github>.
+microlens> family; see the readme <https://github.com/monadfix/microlens#readme
+on Github>.
%package devel
Summary: Haskell %{pkg_name} library development files
@@ -58,7 +57,6 @@
%prep
%setup -q -n %{pkg_name}-%{version}
-cp -p %{SOURCE1} %{pkg_name}.cabal
%build
%ghc_lib_build
++++++ microlens-th-0.4.2.3.tar.gz -> microlens-th-0.4.3.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/microlens-th-0.4.2.3/CHANGELOG.md new/microlens-th-0.4.3.1/CHANGELOG.md
--- old/microlens-th-0.4.2.3/CHANGELOG.md 2018-09-28 08:48:04.000000000 +0200
+++ new/microlens-th-0.4.3.1/CHANGELOG.md 2019-06-20 07:44:15.000000000 +0200
@@ -1,3 +1,13 @@
+# 0.4.3.1
+
+* No more conditional `Safe` (see [#122](https://github.com/monadfix/microlens/issues/122)).
+
+# 0.4.3
+
+* Bumped th-abstraction version.
+* `Lens.Micro.TH` is now properly marked as `Safe` or `Trustworthy`.
+* The `-f-inlining` flag is not supported anymore.
+
# 0.4.2.3
* Bumped template-haskell version.
@@ -33,7 +43,7 @@
# 0.4.0.1
-* Ported a lens commit that (probably) makes lens generation deterministic. See [issue #83](https://github.com/aelve/microlens/issues/83).
+* Ported a lens commit that (probably) makes lens generation deterministic. See [issue #83](https://github.com/monadfix/microlens/issues/83).
# 0.4.0.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/microlens-th-0.4.2.3/LICENSE new/microlens-th-0.4.3.1/LICENSE
--- old/microlens-th-0.4.2.3/LICENSE 2018-09-28 08:41:06.000000000 +0200
+++ new/microlens-th-0.4.3.1/LICENSE 2019-04-27 15:54:34.000000000 +0200
@@ -1,4 +1,5 @@
-Copyright (c) 2013-2016 Eric Mertens, Edward Kmett, Artyom
+Copyright (c) 2013-2016 Eric Mertens, Edward Kmett, Artyom Kazak
+ 2018 Monadfix
All rights reserved.
@@ -13,7 +14,7 @@
disclaimer in the documentation and/or other materials provided
with the distribution.
- * Neither the name of Artyom nor the names of other
+ * Neither the name of Monadfix nor the names of other
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/microlens-th-0.4.2.3/microlens-th.cabal new/microlens-th-0.4.3.1/microlens-th.cabal
--- old/microlens-th-0.4.2.3/microlens-th.cabal 2018-09-28 08:48:12.000000000 +0200
+++ new/microlens-th-0.4.3.1/microlens-th.cabal 2019-06-20 07:44:05.000000000 +0200
@@ -1,30 +1,33 @@
name: microlens-th
-version: 0.4.2.3
+version: 0.4.3.1
synopsis: Automatic generation of record lenses for microlens
description:
This package lets you automatically generate lenses for data types; code was extracted from the lens package, and therefore generated lenses are fully compatible with ones generated by lens (and can be used both from lens and microlens).
.
- This package is a part of the <http://hackage.haskell.org/package/microlens microlens> family; see the readme <https://github.com/aelve/microlens#readme on Github>.
+ This package is a part of the <http://hackage.haskell.org/package/microlens microlens> family; see the readme <https://github.com/monadfix/microlens#readme on Github>.
license: BSD3
license-file: LICENSE
-author: Eric Mertens, Edward Kmett, Artyom
-maintainer: Artyom <yom(a)artyom.me>
-homepage: http://github.com/aelve/microlens
-bug-reports: http://github.com/aelve/microlens/issues
+author: Eric Mertens, Edward Kmett, Artyom Kazak
+maintainer: Monadfix <hi(a)monadfix.io>
+homepage: http://github.com/monadfix/microlens
+bug-reports: http://github.com/monadfix/microlens/issues
category: Data, Lenses
build-type: Simple
extra-source-files:
CHANGELOG.md
cabal-version: >=1.10
+tested-with: GHC==7.4.2
+ GHC==7.6.3
+ GHC==7.8.4
+ GHC==7.10.3
+ GHC==8.0.2
+ GHC==8.2.2
+ GHC==8.4.4
+ GHC==8.6.4
source-repository head
type: git
- location: git://github.com/aelve/microlens.git
-
-flag inlining
- description: Generate inline pragmas
- manual: True
- default: True
+ location: git://github.com/monadfix/microlens.git
library
exposed-modules: Lens.Micro.TH
@@ -36,10 +39,7 @@
, transformers
-- lens has >=2.4, but GHC 7.4 shipped with 2.7
, template-haskell >=2.7 && <2.15
- , th-abstraction >=0.2.1 && <0.3
-
- if flag(inlining)
- cpp-options: -DINLINING
+ , th-abstraction >=0.2.1 && <0.4
ghc-options:
-Wall -fwarn-tabs
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/microlens-th-0.4.2.3/src/Lens/Micro/TH.hs new/microlens-th-0.4.3.1/src/Lens/Micro/TH.hs
--- old/microlens-th-0.4.2.3/src/Lens/Micro/TH.hs 2018-09-28 08:41:06.000000000 +0200
+++ new/microlens-th-0.4.3.1/src/Lens/Micro/TH.hs 2019-06-18 23:51:14.000000000 +0200
@@ -1,16 +1,8 @@
{-# LANGUAGE CPP #-}
-{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
-
-#ifdef TRUSTWORTHY
-# if MIN_VERSION_template_haskell(2,12,0)
-{-# LANGUAGE Safe #-}
-# else
{-# LANGUAGE Trustworthy #-}
-# endif
-#endif
#ifndef MIN_VERSION_template_haskell
#define MIN_VERSION_template_haskell(x,y,z) (defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 706)
@@ -20,10 +12,16 @@
#define MIN_VERSION_containers(x,y,z) 1
#endif
+#if __GLASGOW_HASKELL__ >= 800
+{-# LANGUAGE TemplateHaskellQuotes #-}
+#else
+{-# LANGUAGE TemplateHaskell #-}
+#endif
+
{- |
Module : Lens.Micro.TH
-Copyright : (C) 2013-2016 Eric Mertens, Edward Kmett, Artyom
+Copyright : (C) 2013-2016 Eric Mertens, Edward Kmett, Artyom Kazak; 2018 Monadfix
License : BSD-style (see the file LICENSE)
-}
module Lens.Micro.TH
@@ -1371,26 +1369,8 @@
------------------------------------------------------------------------
inlinePragma :: Name -> [DecQ]
-
-#ifdef INLINING
-
#if MIN_VERSION_template_haskell(2,8,0)
-
-# ifdef OLD_INLINE_PRAGMAS
--- 7.6rc1?
-inlinePragma methodName = [pragInlD methodName (inlineSpecNoPhase Inline False)]
-# else
--- 7.7.20120830
inlinePragma methodName = [pragInlD methodName Inline FunLike AllPhases]
-# endif
-
#else
--- GHC <7.6, TH <2.8.0
inlinePragma methodName = [pragInlD methodName (inlineSpecNoPhase True False)]
#endif
-
-#else
-
-inlinePragma _ = []
-
-#endif
1
0
Hello community,
here is the log from the commit of package ghc-microlens for openSUSE:Factory checked in at 2019-06-30 10:21:36
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-microlens (Old)
and /work/SRC/openSUSE:Factory/.ghc-microlens.new.4615 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-microlens"
Sun Jun 30 10:21:36 2019 rev:13 rq:712504 version:0.4.11.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-microlens/ghc-microlens.changes 2018-12-24 11:37:30.637658788 +0100
+++ /work/SRC/openSUSE:Factory/.ghc-microlens.new.4615/ghc-microlens.changes 2019-06-30 10:21:38.735633643 +0200
@@ -1,0 +2,17 @@
+Fri Jun 21 02:02:59 UTC 2019 - psimons(a)suse.com
+
+- Update microlens to version 0.4.11.1.
+ # 0.4.11.1
+
+ * Reverted marking `Lens.Micro.Internal` as `Trustworthy`, see [#122](https://github.com/monadfix/microlens/issues/122).
+
+-------------------------------------------------------------------
+Wed Jun 19 11:46:02 UTC 2019 - psimons(a)suse.com
+
+- Update microlens to version 0.4.11.
+ Upstream has edited the change log file since the last release in
+ a non-trivial way, i.e. they did more than just add a new entry
+ at the top. You can review the file at:
+ http://hackage.haskell.org/package/microlens-0.4.11/src/CHANGELOG.md
+
+-------------------------------------------------------------------
Old:
----
microlens-0.4.10.tar.gz
New:
----
microlens-0.4.11.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ghc-microlens.spec ++++++
--- /var/tmp/diff_new_pack.fBBrsg/_old 2019-06-30 10:21:39.263634464 +0200
+++ /var/tmp/diff_new_pack.fBBrsg/_new 2019-06-30 10:21:39.267634470 +0200
@@ -1,7 +1,7 @@
#
# spec file for package ghc-microlens
#
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -18,9 +18,9 @@
%global pkg_name microlens
Name: ghc-%{pkg_name}
-Version: 0.4.10
+Version: 0.4.11.1
Release: 0
-Summary: Tiny lens library for Haskell
+Summary: A tiny lens library with no dependencies
License: BSD-3-Clause
Group: Development/Libraries/Haskell
URL: https://hackage.haskell.org/package/%{pkg_name}
@@ -29,12 +29,6 @@
BuildRequires: ghc-rpm-macros
%description
-NOTE: If you're writing an app, you probably want
-<http://hackage.haskell.org/package/microlens-platform microlens-platform> – it
-has the most features. <http://hackage.haskell.org/package/microlens microlens>
-is intended more for library writers who want a tiny lens library (after all,
-lenses are pretty useful for everything, not just for updating records!).
-
This library is an extract from <http://hackage.haskell.org/package/lens lens>
(with no dependencies). It's not a toy lenses library, unsuitable for “real
world”, but merely a small one. It is compatible with lens, and should have
++++++ microlens-0.4.10.tar.gz -> microlens-0.4.11.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/microlens-0.4.10/CHANGELOG.md new/microlens-0.4.11.1/CHANGELOG.md
--- old/microlens-0.4.10/CHANGELOG.md 2018-11-03 12:53:50.000000000 +0100
+++ new/microlens-0.4.11.1/CHANGELOG.md 2019-06-20 07:46:05.000000000 +0200
@@ -1,3 +1,14 @@
+# 0.4.11.1
+
+* Reverted marking `Lens.Micro.Internal` as `Trustworthy`, see [#122](https://github.com/monadfix/microlens/issues/122).
+
+# 0.4.11
+
+* Added fixity declarations for `+~` and `-~` (thanks to Francesco Ariis).
+* Added `rewriteOf` and `transformOf` (thanks to @quasicomputational).
+* Added an instance `Each (Either a a) (Either b b) a b`, following `lens`'s suit.
+* Marked `Lens.Micro.Internal` as `Trustworthy` starting from GHC 7.8.
+
# 0.4.10
* Added `+~` and `-~`.
@@ -95,7 +106,7 @@
# 0.3.4.1
-* Changed the description of the package from “A tiny part of the lens library which you can depend upon” to “A tiny part of the lens library with no dependencies” because the previous one was ambiguous (I admit I kinda liked that ambiguity, tho).
+* Changed the description of the package from “A tiny part of the lens library which you can depend upon” to “A tiny part of the lens library with no dependencies” because the previous one was ambiguous (I admit I kinda liked that ambiguity, though).
# 0.3.4.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/microlens-0.4.10/microlens.cabal new/microlens-0.4.11.1/microlens.cabal
--- old/microlens-0.4.10/microlens.cabal 2018-11-03 12:54:15.000000000 +0100
+++ new/microlens-0.4.11.1/microlens.cabal 2019-06-20 07:46:10.000000000 +0200
@@ -1,6 +1,6 @@
name: microlens
-version: 0.4.10
-synopsis: A tiny lens library with no dependencies. If you're writing an app, you probably want microlens-platform, not this.
+version: 0.4.11.1
+synopsis: A tiny lens library with no dependencies
description:
NOTE: If you're writing an app, you probably want <http://hackage.haskell.org/package/microlens-platform microlens-platform> – it has the most features. <http://hackage.haskell.org/package/microlens microlens> is intended more for library writers who want a tiny lens library (after all, lenses are pretty useful for everything, not just for updating records!).
.
@@ -18,7 +18,7 @@
.
However, don't use this library if:
.
- * You need @Iso@s, @Prism@s, indexed traversals, or actually anything else which isn't defined here (tho some indexed functions are available elsewhere – containers and vector provide them for their types, and <http://hackage.haskell.org/package/ilist ilist> provides indexed functions for lists).
+ * You need @Iso@s, @Prism@s, indexed traversals, or actually anything else which isn't defined here (though some indexed functions are available elsewhere – containers and vector provide them for their types, and <http://hackage.haskell.org/package/ilist ilist> provides indexed functions for lists).
.
* You want a library with a clean, understandable implementation (in which case you're looking for <http://hackage.haskell.org/package/lens-simple lens-simple>).
.
@@ -41,6 +41,14 @@
extra-source-files:
CHANGELOG.md
cabal-version: >=1.10
+tested-with: GHC==7.4.2
+ GHC==7.6.3
+ GHC==7.8.4
+ GHC==7.10.3
+ GHC==8.0.2
+ GHC==8.2.2
+ GHC==8.4.4
+ GHC==8.6.4
source-repository head
type: git
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/microlens-0.4.10/src/Lens/Micro/Internal.hs new/microlens-0.4.11.1/src/Lens/Micro/Internal.hs
--- old/microlens-0.4.10/src/Lens/Micro/Internal.hs 2018-11-03 12:52:00.000000000 +0100
+++ new/microlens-0.4.11.1/src/Lens/Micro/Internal.hs 2019-06-18 23:48:44.000000000 +0200
@@ -10,8 +10,9 @@
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE ImplicitParams #-}
-{-# LANGUAGE Unsafe #-}
+-- Note: this module is marked 'Unsafe' because it exports (#.), which is essentially 'coerce', and Data.Coerce is marked 'Unsafe' in base. As per <https://github.com/ekmett/lens/issues/661>, this is an issue for 'lens' as well but they have opted for 'Trustworthy' instead.
+{-# LANGUAGE Unsafe #-}
{- |
Module : Lens.Micro.Internal
@@ -156,6 +157,10 @@
-- Data.Profunctor.Unsafe
------------------------------------------------------------------------------
+-- Note: 'lens' defines a type-restricted version of (#.) to work around a
+-- bug, but our version is restricted enough that we don't need it. See
+-- <https://github.com/ekmett/lens/commit/cde2fc39c0dba413d1a6f814b47bd14431a5e…>
+
#if __GLASGOW_HASKELL__ >= 708
( #. ) :: Coercible c b => (b -> c) -> (a -> b) -> (a -> c)
( #. ) _ = coerce (\x -> x :: b) :: forall a b. Coercible b a => a -> b
@@ -198,6 +203,7 @@
'each' :: 'Traversal' [a] [b] a b
'each' :: 'Traversal' ('Maybe' a) ('Maybe' b) a b
+'each' :: 'Traversal' ('Either' a a) ('Either' b b) a b -- since 0.4.11
'each' :: 'Traversal' (a,a) (b,b) a b
'each' :: 'Traversal' (a,a,a) (b,b,b) a b
@@ -239,12 +245,22 @@
each = traverse
{-# INLINE each #-}
+{- |
+@since 0.4.11
+-}
+instance (a~a', b~b') => Each (Either a a') (Either b b') a b where
+ each f (Left a) = Left <$> f a
+ each f (Right a ) = Right <$> f a
+ {-# INLINE each #-}
+
#if __GLASGOW_HASKELL__ >= 800
instance Each (NonEmpty a) (NonEmpty b) a b where
each = traversed
{-# INLINE each #-}
#endif
+-- NOTE: when adding new instances of 'Each', update the docs for 'each'.
+
type family Index (s :: *) :: *
type family IxValue (m :: *) :: *
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/microlens-0.4.10/src/Lens/Micro.hs new/microlens-0.4.11.1/src/Lens/Micro.hs
--- old/microlens-0.4.10/src/Lens/Micro.hs 2018-11-03 12:51:53.000000000 +0100
+++ new/microlens-0.4.11.1/src/Lens/Micro.hs 2019-06-18 01:03:47.000000000 +0200
@@ -44,6 +44,8 @@
(?~),
(<%~), (<<%~), (<<.~),
mapped,
+ rewriteOf,
+ transformOf,
-- * Getter: extracts a value from a structure
-- $getters-note
@@ -112,7 +114,12 @@
import Data.Maybe
import Data.Tuple
import qualified Data.Foldable as F
+
+#if __GLASGOW_HASKELL__ >= 708
+import Data.Coerce
+#else
import Unsafe.Coerce
+#endif
#if MIN_VERSION_base(4,8,0)
import Data.Function ((&))
@@ -304,57 +311,69 @@
{-# INLINE over #-}
--- | Increment the target(s) of a numerically valued 'Lens' or 'Traversal'.
---
--- >>> (a,b) & _1 +~ c
--- (a + c,b)
---
--- >>> (a,b) & both +~ c
--- (a + c,b + c)
---
--- >>> (1,2) & _2 +~ 1
--- (1,3)
---
--- >>> [(a,b),(c,d)] & traverse.both +~ e
--- [(a + e,b + e),(c + e,d + e)]
---
--- @
--- ('+~') :: 'Num' a => 'Lens'' s a -> a -> s -> s
--- ('+~') :: 'Num' a => 'Traversal'' s a -> a -> s -> s
--- @
+{- |
+Increment the target(s) of a numerically valued 'Lens' or 'Traversal'.
+
+>>> (a,b) & _1 +~ c
+(a + c,b)
+
+>>> (a,b) & both +~ c
+(a + c,b + c)
+
+>>> (1,2) & _2 +~ 1
+(1,3)
+
+>>> [(a,b),(c,d)] & traverse.both +~ e
+[(a + e,b + e),(c + e,d + e)]
+
+@
+('+~') :: 'Num' a => 'Lens'' s a -> a -> s -> s
+('+~') :: 'Num' a => 'Traversal'' s a -> a -> s -> s
+@
+
+@since 0.4.10
+-}
(+~) :: Num a => ASetter s t a a -> a -> s -> t
l +~ n = over l (+ n)
{-# INLINE (+~) #-}
--- | Decrement the target(s) of a numerically valued 'Lens', or 'Traversal'.
---
--- >>> (a,b) & _1 -~ c
--- (a - c,b)
---
--- >>> (a,b) & both -~ c
--- (a - c,b - c)
---
--- >>> _1 -~ 2 $ (1,2)
--- (-1,2)
---
--- >>> mapped.mapped -~ 1 $ [[4,5],[6,7]]
--- [[3,4],[5,6]]
---
--- @
--- ('-~') :: 'Num' a => 'Lens'' s a -> a -> s -> s
--- ('-~') :: 'Num' a => 'Traversal'' s a -> a -> s -> s
--- @
+infixr 4 +~
+
+{- |
+Decrement the target(s) of a numerically valued 'Lens', or 'Traversal'.
+
+>>> (a,b) & _1 -~ c
+(a - c,b)
+
+>>> (a,b) & both -~ c
+(a - c,b - c)
+
+>>> _1 -~ 2 $ (1,2)
+(-1,2)
+
+>>> mapped.mapped -~ 1 $ [[4,5],[6,7]]
+[[3,4],[5,6]]
+
+@
+('-~') :: 'Num' a => 'Lens'' s a -> a -> s -> s
+('-~') :: 'Num' a => 'Traversal'' s a -> a -> s -> s
+@
+
+@since 0.4.10
+-}
(-~) :: Num a => ASetter s t a a -> a -> s -> t
l -~ n = over l (subtract n)
{-# INLINE (-~) #-}
-
+infixr 4 -~
{- |
('<>~') appends a value monoidally to the target.
>>> ("hello", "goodbye") & both <>~ " world!"
("hello world!", "goodbye world!")
+
+@since 0.4.9
-}
(<>~) :: (Monoid a) => ASetter s t a a -> a -> s -> t
(<>~) l a = over l (`mappend` a)
@@ -498,6 +517,30 @@
infixr 4 <<.~
+{- |
+→ See <https://github.com/monadfix/microlens/pull/119#issuecomment-496004851 an example> on GitHub.
+
+Rewrite by applying a rule everywhere you can. Ensures that the rule cannot be applied anywhere in the result.
+
+Usually 'transformOf' is more appropriate, but 'rewriteOf' can give better compositionality. Given two single transformations @f@ and @g@, you can construct @\\a -> f a '<|>' g a@ which performs both rewrites until a fixed point.
+
+@since 0.4.11
+-}
+rewriteOf :: ASetter a b a b -> (b -> Maybe a) -> a -> b
+rewriteOf l f = go where
+ go = transformOf l (\x -> maybe x go (f x))
+{-# INLINE rewriteOf #-}
+
+{- |
+Transform every element by recursively applying a given 'ASetter' in a bottom-up manner.
+
+@since 0.4.11
+-}
+transformOf :: ASetter a b a b -> (b -> b) -> a -> b
+transformOf l f = go where
+ go = f . over l go
+{-# INLINE transformOf #-}
+
-- Getting -----------------------------------------------------------------
{- $getters-note
@@ -1015,8 +1058,13 @@
where
Bazaar b = l sell s
sell w = Bazaar ($ w)
+#if __GLASGOW_HASKELL__ >= 708
+ ins f = (coerce :: [Identity a] -> [a])
+ (getConst (f (\ra -> Const [Identity ra])))
+#else
ins f = (unsafeCoerce :: [Identity a] -> [a])
(getConst (f (\ra -> Const [Identity ra])))
+#endif
unsafeOuts f = evalState (f (\_ -> state (unconsWithDefault fakeVal)))
where fakeVal = error "unsafeOuts: not enough elements were supplied"
unconsWithDefault d [] = (d,[])
1
0