Merge lp:~jelmer/brz/gpg into lp:brz

Proposed by Jelmer Vernooij
Status: Superseded
Proposed branch: lp:~jelmer/brz/gpg
Merge into: lp:brz
Diff against target: 781 lines (+137/-241)
11 files modified
breezy/config.py (+0/-17)
breezy/errors.py (+0/-24)
breezy/gpg.py (+97/-81)
breezy/help_topics/en/configuration.txt (+0/-10)
breezy/tests/blackbox/test_log.py (+5/-2)
breezy/tests/features.py (+3/-1)
breezy/tests/test_commit.py (+1/-5)
breezy/tests/test_config.py (+0/-2)
breezy/tests/test_gpg.py (+24/-97)
breezy/tests/test_merge_directive.py (+0/-2)
doc/en/release-notes/brz-3.0.txt (+7/-0)
To merge this branch: bzr merge lp:~jelmer/brz/gpg
Reviewer Review Type Date Requested Status
Martin Packman Pending
Review via email: mp+326812@code.launchpad.net

This proposal has been superseded by a proposal from 2017-07-04.

Commit message

Switch to using python-gpg (part of gpgme) rather than deprecated python-gpgme.

Description of the change

Switch to using python-gpg (part of gpgme) rather than deprecated python-gpgme.

Also, switch to using gpgme for signing, while we're at it.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'breezy/config.py'
2--- breezy/config.py 2017-06-15 01:07:35 +0000
3+++ breezy/config.py 2017-07-04 21:10:26 +0000
4@@ -27,7 +27,6 @@
5 email=Your Name <your@email.address>
6 check_signatures=require|ignore|check-available(default)
7 create_signatures=always|never|when-required(default)
8-gpg_signing_command=name-of-program
9 log_format=name-of-format
10 validate_signatures_in_log=true|false(default)
11 acceptable_keys=pattern1,pattern2
12@@ -798,10 +797,6 @@
13 else:
14 return None
15
16- def _gpg_signing_command(self):
17- """See Config.gpg_signing_command."""
18- return self._get_user_option('gpg_signing_command')
19-
20 def _log_format(self):
21 """See Config.log_format."""
22 return self._get_user_option('log_format')
23@@ -1314,10 +1309,6 @@
24 def remove_user_option(self, option_name, section_name=None):
25 self._get_branch_data_config().remove_option(option_name, section_name)
26
27- def _gpg_signing_command(self):
28- """See Config.gpg_signing_command."""
29- return self._get_safe_value('_gpg_signing_command')
30-
31 def _post_commit(self):
32 """See Config.post_commit."""
33 return self._get_safe_value('_post_commit')
34@@ -2706,14 +2697,6 @@
35 Option('email', override_from_env=['BRZ_EMAIL'], default=default_email,
36 help='The users identity'))
37 option_registry.register(
38- Option('gpg_signing_command',
39- default='gpg',
40- help="""\
41-Program to use use for creating signatures.
42-
43-This should support at least the -u and --clearsign options.
44-"""))
45-option_registry.register(
46 Option('gpg_signing_key',
47 default=None,
48 help="""\
49
50=== modified file 'breezy/errors.py'
51--- breezy/errors.py 2017-06-10 18:39:27 +0000
52+++ breezy/errors.py 2017-07-04 21:10:26 +0000
53@@ -1771,22 +1771,6 @@
54 self.username = username
55
56
57-class SigningFailed(BzrError):
58-
59- _fmt = 'Failed to GPG sign data with command "%(command_line)s"'
60-
61- def __init__(self, command_line):
62- BzrError.__init__(self, command_line=command_line)
63-
64-
65-class SignatureVerificationFailed(BzrError):
66-
67- _fmt = 'Failed to verify GPG signature data with error "%(error)s"'
68-
69- def __init__(self, error):
70- BzrError.__init__(self, error=error)
71-
72-
73 class DependencyNotPresent(BzrError):
74
75 _fmt = 'Unable to import library "%(library)s": %(error)s'
76@@ -1795,14 +1779,6 @@
77 BzrError.__init__(self, library=library, error=error)
78
79
80-class GpgmeNotInstalled(DependencyNotPresent):
81-
82- _fmt = 'python-gpgme is not installed, it is needed to verify signatures'
83-
84- def __init__(self, error):
85- DependencyNotPresent.__init__(self, 'gpgme', error)
86-
87-
88 class WorkingTreeNotRevision(BzrError):
89
90 _fmt = ("The working tree for %(basedir)s has changed since"
91
92=== modified file 'breezy/gpg.py'
93--- breezy/gpg.py 2017-06-05 20:48:31 +0000
94+++ breezy/gpg.py 2017-07-04 21:10:26 +0000
95@@ -29,7 +29,6 @@
96
97 from breezy import (
98 config,
99- errors,
100 trace,
101 ui,
102 )
103@@ -39,6 +38,9 @@
104 )
105 """)
106
107+from . import (
108+ errors,
109+ )
110 from .sixish import (
111 BytesIO,
112 )
113@@ -51,6 +53,30 @@
114 SIGNATURE_EXPIRED = 4
115
116
117+class GpgNotInstalled(errors.DependencyNotPresent):
118+
119+ _fmt = 'python-gpg is not installed, it is needed to verify signatures'
120+
121+ def __init__(self, error):
122+ errors.DependencyNotPresent.__init__(self, 'gpg', error)
123+
124+
125+class SigningFailed(errors.BzrError):
126+
127+ _fmt = 'Failed to GPG sign data: "%(error)s"'
128+
129+ def __init__(self, error):
130+ errors.BzrError.__init__(self, error=error)
131+
132+
133+class SignatureVerificationFailed(errors.BzrError):
134+
135+ _fmt = 'Failed to verify GPG signature data with error "%(error)s"'
136+
137+ def __init__(self, error):
138+ errors.BzrError.__init__(self, error=error)
139+
140+
141 def bulk_verify_signatures(repository, revids, strategy,
142 process_events_callback=None):
143 """Do verifications on a set of revisions
144@@ -101,10 +127,10 @@
145 """Real strategies take a configuration."""
146
147 def sign(self, content):
148- raise errors.SigningFailed('Signing is disabled.')
149+ raise SigningFailed('Signing is disabled.')
150
151 def verify(self, content, testament):
152- raise errors.SignatureVerificationFailed('Signature verification is \
153+ raise SignatureVerificationFailed('Signature verification is \
154 disabled.')
155
156 def set_acceptable_keys(self, command_line_input):
157@@ -162,11 +188,32 @@
158 def __init__(self, config_stack):
159 self._config_stack = config_stack
160 try:
161- import gpgme
162- self.context = gpgme.Context()
163+ import gpg
164+ self.context = gpg.Context()
165 except ImportError as error:
166 pass # can't use verify()
167
168+ self.context.signers = self._get_signing_keys()
169+
170+ def _get_signing_keys(self):
171+ import gpg
172+ keyname = self._config_stack.get('gpg_signing_key')
173+ if keyname:
174+ try:
175+ return [self.context.get_key(keyname)]
176+ except gpg.errors.KeyNotFound:
177+ pass
178+
179+ if keyname is None or keyname == 'default':
180+ # 'default' or not setting gpg_signing_key at all means we should
181+ # use the user email address
182+ keyname = config.extract_email_address(self._config_stack.get('email'))
183+ possible_keys = self.context.keylist(keyname, secret=True)
184+ try:
185+ return [possible_keys.next()]
186+ except StopIteration:
187+ return []
188+
189 @staticmethod
190 def verify_signatures_available():
191 """
192@@ -175,55 +222,24 @@
193 :return: boolean if this strategy can verify signatures
194 """
195 try:
196- import gpgme
197+ import gpg
198 return True
199 except ImportError as error:
200 return False
201
202- def _command_line(self):
203- key = self._config_stack.get('gpg_signing_key')
204- if key is None or key == 'default':
205- # 'default' or not setting gpg_signing_key at all means we should
206- # use the user email address
207- key = config.extract_email_address(self._config_stack.get('email'))
208- return [self._config_stack.get('gpg_signing_command'), '--clearsign',
209- '-u', key]
210-
211 def sign(self, content):
212+ import gpg
213 if isinstance(content, unicode):
214 raise errors.BzrBadParameterUnicode('content')
215- ui.ui_factory.clear_term()
216
217- preexec_fn = _set_gpg_tty
218- if sys.platform == 'win32':
219- # Win32 doesn't support preexec_fn, but wouldn't support TTY anyway.
220- preexec_fn = None
221+ plain_text = gpg.Data(content)
222 try:
223- process = subprocess.Popen(self._command_line(),
224- stdin=subprocess.PIPE,
225- stdout=subprocess.PIPE,
226- preexec_fn=preexec_fn)
227- try:
228- result = process.communicate(content)[0]
229- if process.returncode is None:
230- process.wait()
231- if process.returncode != 0:
232- raise errors.SigningFailed(self._command_line())
233- return result
234- except OSError as e:
235- if e.errno == errno.EPIPE:
236- raise errors.SigningFailed(self._command_line())
237- else:
238- raise
239- except ValueError:
240- # bad subprocess parameters, should never happen.
241- raise
242- except OSError as e:
243- if e.errno == errno.ENOENT:
244- # gpg is not installed
245- raise errors.SigningFailed(self._command_line())
246- else:
247- raise
248+ output, result = self.context.sign(
249+ plain_text, mode=gpg.constants.sig.mode.CLEAR)
250+ except gpg.errors.GPGMEError as error:
251+ raise SigningFailed(str(error))
252+
253+ return output
254
255 def verify(self, content, testament):
256 """Check content has a valid signature.
257@@ -234,74 +250,74 @@
258 :return: SIGNATURE_VALID or a failed SIGNATURE_ value, key uid if valid
259 """
260 try:
261- import gpgme
262+ import gpg
263 except ImportError as error:
264- raise errors.GpgmeNotInstalled(error)
265+ raise errors.GpgNotInstalled(error)
266
267- signature = BytesIO(content)
268- plain_output = BytesIO()
269+ signature = gpg.Data(content)
270+ sink = gpg.Data()
271 try:
272- result = self.context.verify(signature, None, plain_output)
273- except gpgme.GpgmeError as error:
274- raise errors.SignatureVerificationFailed(error[2])
275+ plain_output, result = self.context.verify(signature)
276+ except gpg.errors.BadSignatures as error:
277+ fingerprint = error.result.signatures[0].fpr
278+ if error.result.signatures[0].summary & gpg.constants.SIGSUM_KEY_EXPIRED:
279+ expires = self.context.get_key(error.result.signatures[0].fpr).subkeys[0].expires
280+ if expires > error.result.signatures[0].timestamp:
281+ # The expired key was not expired at time of signing.
282+ # test_verify_expired_but_valid()
283+ return SIGNATURE_EXPIRED, fingerprint[-8:]
284+ else:
285+ # I can't work out how to create a test where the signature
286+ # was expired at the time of signing.
287+ return SIGNATURE_NOT_VALID, None
288+
289+ # GPG does not know this key.
290+ # test_verify_unknown_key()
291+ if error.result.signatures[0].summary & gpg.constants.SIGSUM_KEY_MISSING:
292+ return SIGNATURE_KEY_MISSING, fingerprint[-8:]
293+
294+ return SIGNATURE_NOT_VALID, None
295+ except gpg.errors.GPGMEError as error:
296+ raise SignatureVerificationFailed(error[2])
297
298 # No result if input is invalid.
299 # test_verify_invalid()
300- if len(result) == 0:
301+ if len(result.signatures) == 0:
302 return SIGNATURE_NOT_VALID, None
303 # User has specified a list of acceptable keys, check our result is in
304 # it. test_verify_unacceptable_key()
305- fingerprint = result[0].fpr
306+ fingerprint = result.signatures[0].fpr
307 if self.acceptable_keys is not None:
308 if not fingerprint in self.acceptable_keys:
309 return SIGNATURE_KEY_MISSING, fingerprint[-8:]
310 # Check the signature actually matches the testament.
311 # test_verify_bad_testament()
312- if testament != plain_output.getvalue():
313+ if testament != plain_output:
314 return SIGNATURE_NOT_VALID, None
315- # Yay gpgme set the valid bit.
316+ # Yay gpg set the valid bit.
317 # Can't write a test for this one as you can't set a key to be
318- # trusted using gpgme.
319- if result[0].summary & gpgme.SIGSUM_VALID:
320+ # trusted using gpg.
321+ if result.signatures[0].summary & gpg.constants.SIGSUM_VALID:
322 key = self.context.get_key(fingerprint)
323 name = key.uids[0].name
324 email = key.uids[0].email
325 return SIGNATURE_VALID, name + " <" + email + ">"
326 # Sigsum_red indicates a problem, unfortunatly I have not been able
327 # to write any tests which actually set this.
328- if result[0].summary & gpgme.SIGSUM_RED:
329+ if result.signatures[0].summary & gpg.constants.SIGSUM_RED:
330 return SIGNATURE_NOT_VALID, None
331- # GPG does not know this key.
332- # test_verify_unknown_key()
333- if result[0].summary & gpgme.SIGSUM_KEY_MISSING:
334- return SIGNATURE_KEY_MISSING, fingerprint[-8:]
335 # Summary isn't set if sig is valid but key is untrusted but if user
336 # has explicity set the key as acceptable we can validate it.
337- if result[0].summary == 0 and self.acceptable_keys is not None:
338+ if result.signatures[0].summary == 0 and self.acceptable_keys is not None:
339 if fingerprint in self.acceptable_keys:
340 # test_verify_untrusted_but_accepted()
341 return SIGNATURE_VALID, None
342 # test_verify_valid_but_untrusted()
343- if result[0].summary == 0 and self.acceptable_keys is None:
344- return SIGNATURE_NOT_VALID, None
345- if result[0].summary & gpgme.SIGSUM_KEY_EXPIRED:
346- expires = self.context.get_key(result[0].fpr).subkeys[0].expires
347- if expires > result[0].timestamp:
348- # The expired key was not expired at time of signing.
349- # test_verify_expired_but_valid()
350- return SIGNATURE_EXPIRED, fingerprint[-8:]
351- else:
352- # I can't work out how to create a test where the signature
353- # was expired at the time of signing.
354- return SIGNATURE_NOT_VALID, None
355- # A signature from a revoked key gets this.
356- # test_verify_revoked_signature()
357- if ((result[0].summary & gpgme.SIGSUM_SYS_ERROR
358- or result[0].status.strerror == 'Certificate revoked')):
359+ if result.signatures[0].summary == 0 and self.acceptable_keys is None:
360 return SIGNATURE_NOT_VALID, None
361 # Other error types such as revoked keys should (I think) be caught by
362 # SIGSUM_RED so anything else means something is buggy.
363- raise errors.SignatureVerificationFailed(
364+ raise SignatureVerificationFailed(
365 "Unknown GnuPG key verification result")
366
367 def set_acceptable_keys(self, command_line_input):
368
369=== modified file 'breezy/help_topics/en/configuration.txt'
370--- breezy/help_topics/en/configuration.txt 2017-06-12 23:25:04 +0000
371+++ breezy/help_topics/en/configuration.txt 2017-07-04 21:10:26 +0000
372@@ -498,16 +498,6 @@
373 This section only applies to the branch at this directory and not
374 branches below it.
375
376-gpg_signing_command
377-~~~~~~~~~~~~~~~~~~~
378-
379-(Default: "gpg"). Which program should be used to sign and check revisions.
380-For example::
381-
382- gpg_signing_command = /usr/bin/gnpg
383-
384-The specified command must accept the options "--clearsign" and "-u <email>".
385-
386 bzr_remote_path
387 ~~~~~~~~~~~~~~~
388
389
390=== modified file 'breezy/tests/blackbox/test_log.py'
391--- breezy/tests/blackbox/test_log.py 2017-06-22 01:52:28 +0000
392+++ breezy/tests/blackbox/test_log.py 2017-07-04 21:10:26 +0000
393@@ -17,6 +17,9 @@
394
395 """Black-box tests for brz log."""
396
397+from __future__ import absolute_import
398+
399+
400 import os
401
402 from breezy import (
403@@ -474,7 +477,7 @@
404 class TestLogSignatures(TestLog):
405
406 def test_log_with_signatures(self):
407- self.requireFeature(features.gpgme)
408+ self.requireFeature(features.gpg)
409
410 tree = self.make_linear_branch(format='dirstate-tags')
411
412@@ -482,7 +485,7 @@
413 self.assertTrue('signature: no signature' in log)
414
415 def test_log_without_signatures(self):
416- self.requireFeature(features.gpgme)
417+ self.requireFeature(features.gpg)
418
419 tree = self.make_linear_branch(format='dirstate-tags')
420
421
422=== modified file 'breezy/tests/features.py'
423--- breezy/tests/features.py 2017-06-17 12:58:29 +0000
424+++ breezy/tests/features.py 2017-07-04 21:10:26 +0000
425@@ -17,6 +17,8 @@
426 """A collection of commonly used 'Features' to optionally run tests.
427 """
428
429+from __future__ import absolute_import
430+
431 import os
432 import subprocess
433 import stat
434@@ -373,7 +375,7 @@
435 not_running_as_root = _NotRunningAsRoot()
436
437 apport = ModuleAvailableFeature('apport')
438-gpgme = ModuleAvailableFeature('gpgme')
439+gpg = ModuleAvailableFeature('gpg')
440 lzma = ModuleAvailableFeature('lzma')
441 meliae = ModuleAvailableFeature('meliae.scanner')
442 paramiko = ModuleAvailableFeature('paramiko')
443
444=== modified file 'breezy/tests/test_commit.py'
445--- breezy/tests/test_commit.py 2017-06-18 22:23:02 +0000
446+++ breezy/tests/test_commit.py 2017-07-04 21:10:26 +0000
447@@ -33,7 +33,6 @@
448 from ..errors import (
449 PointlessCommit,
450 BzrError,
451- SigningFailed,
452 LockContention,
453 )
454 from . import (
455@@ -53,7 +52,6 @@
456
457 def __init__(self):
458 super(MustSignConfig, self).__init__('''
459-gpg_signing_command=cat -
460 create_signatures=always
461 ''')
462
463@@ -431,7 +429,6 @@
464 # monkey patch gpg signing mechanism
465 breezy.gpg.GPGStrategy = breezy.gpg.LoopbackGPGStrategy
466 conf = config.MemoryStack('''
467-gpg_signing_command=cat -
468 create_signatures=always
469 ''')
470 commit.Commit(config_stack=conf).commit(
471@@ -457,10 +454,9 @@
472 # monkey patch gpg signing mechanism
473 breezy.gpg.GPGStrategy = breezy.gpg.DisabledGPGStrategy
474 conf = config.MemoryStack('''
475-gpg_signing_command=cat -
476 create_signatures=always
477 ''')
478- self.assertRaises(SigningFailed,
479+ self.assertRaises(breezy.gpg.SigningFailed,
480 commit.Commit(config_stack=conf).commit,
481 message="base",
482 allow_pointless=True,
483
484=== modified file 'breezy/tests/test_config.py'
485--- breezy/tests/test_config.py 2017-06-12 23:25:04 +0000
486+++ breezy/tests/test_config.py 2017-07-04 21:10:26 +0000
487@@ -176,7 +176,6 @@
488 email=Erik B\u00e5gfors <erik@bagfors.nu>
489 editor=vim
490 change_editor=vimdiff -of @new_path @old_path
491-gpg_signing_command=gnome-gpg
492 gpg_signing_key=DD4D5088
493 log_format=short
494 validate_signatures_in_log=true
495@@ -232,7 +231,6 @@
496 # test trailing / matching with no children
497 [/a/]
498 check_signatures=check-available
499-gpg_signing_command=false
500 gpg_signing_key=default
501 user_local_option=local
502 # test trailing / matching
503
504=== modified file 'breezy/tests/test_gpg.py'
505--- breezy/tests/test_gpg.py 2017-05-22 00:56:52 +0000
506+++ breezy/tests/test_gpg.py 2017-07-04 21:10:26 +0000
507@@ -43,90 +43,17 @@
508 if content is None:
509 content = '''
510 gpg_signing_key=amy@example.com
511-gpg_signing_command=false'''
512+'''
513 super(FakeConfig, self).__init__(content)
514
515
516-class TestCommandLine(tests.TestCase):
517-
518- def setUp(self):
519- super(TestCommandLine, self).setUp()
520- self.my_gpg = gpg.GPGStrategy(FakeConfig())
521-
522- def test_signing_command_line(self):
523- self.assertEqual(['false', '--clearsign', '-u', 'amy@example.com'],
524- self.my_gpg._command_line())
525-
526- def test_signing_command_line_from_default(self):
527- # Using 'default' for gpg_signing_key will use the mail part of 'email'
528- my_gpg = gpg.GPGStrategy(FakeConfig('''
529-email=Amy <amy@example.com>
530-gpg_signing_key=default
531-gpg_signing_command=false'''))
532- self.assertEqual(['false', '--clearsign', '-u', 'amy@example.com'],
533- my_gpg._command_line())
534-
535- def test_signing_command_line_from_email(self):
536- # Not setting gpg_signing_key will use the mail part of 'email'
537- my_gpg = gpg.GPGStrategy(FakeConfig('''
538-email=Amy <amy@example.com>
539-gpg_signing_command=false'''))
540- self.assertEqual(['false', '--clearsign', '-u', 'amy@example.com'],
541- my_gpg._command_line())
542-
543- def test_checks_return_code(self):
544- # This test needs a unix like platform - one with 'false' to run.
545- # if you have one, please make this work :)
546- self.assertRaises(errors.SigningFailed, self.my_gpg.sign, 'content')
547-
548- def assertProduces(self, content):
549- # This needs a 'cat' command or similar to work.
550- if sys.platform == 'win32':
551- # Windows doesn't come with cat, and we don't require it
552- # so lets try using python instead.
553- # But stupid windows and line-ending conversions.
554- # It is too much work to make sys.stdout be in binary mode.
555- # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65443
556- self.my_gpg._command_line = lambda:[sys.executable, '-c',
557- 'import sys; sys.stdout.write(sys.stdin.read())']
558- new_content = content.replace('\n', '\r\n')
559-
560- self.assertEqual(new_content, self.my_gpg.sign(content))
561- else:
562- self.my_gpg._command_line = lambda:['cat', '-']
563- self.assertEqual(content, self.my_gpg.sign(content))
564-
565- def test_returns_output(self):
566- content = "some content\nwith newlines\n"
567- self.assertProduces(content)
568-
569- def test_clears_progress(self):
570- content = "some content\nwith newlines\n"
571- old_clear_term = ui.ui_factory.clear_term
572- clear_term_called = []
573- def clear_term():
574- old_clear_term()
575- clear_term_called.append(True)
576- ui.ui_factory.clear_term = clear_term
577- try:
578- self.assertProduces(content)
579- finally:
580- ui.ui_factory.clear_term = old_clear_term
581- self.assertEqual([True], clear_term_called)
582-
583- def test_aborts_on_unicode(self):
584- """You can't sign Unicode text; it must be encoded first."""
585- self.assertRaises(errors.BzrBadParameterUnicode,
586- self.assertProduces, u'foo')
587-
588-
589 class TestVerify(TestCase):
590
591 def import_keys(self):
592- import gpgme
593- context = gpgme.Context()
594+ import gpg
595+ context = gpg.Context()
596
597- key = BytesIO(b"""-----BEGIN PGP PUBLIC KEY BLOCK-----
598+ key = gpg.Data(b"""-----BEGIN PGP PUBLIC KEY BLOCK-----
599 Version: GnuPG v1.4.11 (GNU/Linux)
600
601 mQENBE343IgBCADwzPW7kmKb2bjB+UU+1ER/ABMZspvtoZMPusUw7bk6coXHF/0W
602@@ -158,7 +85,7 @@
603 -----END PGP PUBLIC KEY BLOCK-----
604 """)
605
606- secret_key = BytesIO(b"""-----BEGIN PGP PRIVATE KEY BLOCK-----
607+ secret_key = gpg.Data(b"""-----BEGIN PGP PRIVATE KEY BLOCK-----
608 Version: GnuPG v1.4.11 (GNU/Linux)
609
610 lQOYBE343IgBCADwzPW7kmKb2bjB+UU+1ER/ABMZspvtoZMPusUw7bk6coXHF/0W
611@@ -217,7 +144,7 @@
612 -----END PGP PRIVATE KEY BLOCK-----
613 """)
614
615- revoked_key = BytesIO(b"""-----BEGIN PGP PUBLIC KEY BLOCK-----
616+ revoked_key = gpg.Data(b"""-----BEGIN PGP PUBLIC KEY BLOCK-----
617 Version: GnuPG v1.4.11 (GNU/Linux)
618
619 mI0ETjlW5gEEAOb/6P+TVM59E897wRtatxys2BhsHCXM4T7xjIiANfDwejDdifqh
620@@ -242,7 +169,7 @@
621 -----END PGP PUBLIC KEY BLOCK-----
622 """)
623
624- expired_key = BytesIO(b"""-----BEGIN PGP PUBLIC KEY BLOCK-----
625+ expired_key = gpg.Data(b"""-----BEGIN PGP PUBLIC KEY BLOCK-----
626 Version: GnuPG v1.4.11 (GNU/Linux)
627
628 mI0ETjZ6PAEEALkR4GcFQidCCxV7pgQwQd5MZua0YO2l92fVqHX+PhnZ6egCLKdD
629@@ -263,14 +190,14 @@
630 =p0gt
631 -----END PGP PUBLIC KEY BLOCK-----
632 """)
633- context.import_(key)
634- context.import_(secret_key)
635- context.import_(revoked_key)
636- context.import_(expired_key)
637+ context.op_import(key)
638+ context.op_import(secret_key)
639+ context.op_import(revoked_key)
640+ context.op_import(expired_key)
641
642 def test_verify_untrusted_but_accepted(self):
643 #untrusted by gpg but listed as acceptable_keys by user
644- self.requireFeature(features.gpgme)
645+ self.requireFeature(features.gpg)
646 self.import_keys()
647
648 content = """-----BEGIN PGP SIGNED MESSAGE-----
649@@ -301,7 +228,7 @@
650 plain))
651
652 def test_verify_unacceptable_key(self):
653- self.requireFeature(features.gpgme)
654+ self.requireFeature(features.gpg)
655 self.import_keys()
656
657 content = """-----BEGIN PGP SIGNED MESSAGE-----
658@@ -332,7 +259,7 @@
659 my_gpg.verify(content, plain))
660
661 def test_verify_valid_but_untrusted(self):
662- self.requireFeature(features.gpgme)
663+ self.requireFeature(features.gpg)
664 self.import_keys()
665
666 content = """-----BEGIN PGP SIGNED MESSAGE-----
667@@ -362,7 +289,7 @@
668 plain))
669
670 def test_verify_bad_testament(self):
671- self.requireFeature(features.gpgme)
672+ self.requireFeature(features.gpg)
673 self.import_keys()
674
675 content = """-----BEGIN PGP SIGNED MESSAGE-----
676@@ -394,7 +321,7 @@
677
678
679 def test_verify_revoked_signature(self):
680- self.requireFeature(features.gpgme)
681+ self.requireFeature(features.gpg)
682 self.import_keys()
683
684 content = """-----BEGIN PGP SIGNED MESSAGE-----
685@@ -418,7 +345,7 @@
686 plain))
687
688 def test_verify_invalid(self):
689- self.requireFeature(features.gpgme)
690+ self.requireFeature(features.gpg)
691 self.import_keys()
692 content = """-----BEGIN PGP SIGNED MESSAGE-----
693 Hash: SHA1
694@@ -443,7 +370,7 @@
695 my_gpg.verify(content, plain))
696
697 def test_verify_expired_but_valid(self):
698- self.requireFeature(features.gpgme)
699+ self.requireFeature(features.gpg)
700 self.import_keys()
701 content = """-----BEGIN PGP SIGNED MESSAGE-----
702 Hash: SHA1
703@@ -470,7 +397,7 @@
704 my_gpg.verify(content, plain))
705
706 def test_verify_unknown_key(self):
707- self.requireFeature(features.gpgme)
708+ self.requireFeature(features.gpg)
709 self.import_keys()
710 content = """-----BEGIN PGP SIGNED MESSAGE-----
711 Hash: SHA1
712@@ -494,7 +421,7 @@
713 my_gpg.verify(content, plain))
714
715 def test_set_acceptable_keys(self):
716- self.requireFeature(features.gpgme)
717+ self.requireFeature(features.gpg)
718 self.import_keys()
719 my_gpg = gpg.GPGStrategy(FakeConfig())
720 my_gpg.set_acceptable_keys("bazaar@example.com")
721@@ -502,7 +429,7 @@
722 [u'B5DEED5FCB15DAE6ECEF919587681B1EE3080E45'])
723
724 def test_set_acceptable_keys_from_config(self):
725- self.requireFeature(features.gpgme)
726+ self.requireFeature(features.gpg)
727 self.import_keys()
728 my_gpg = gpg.GPGStrategy(FakeConfig(
729 'acceptable_keys=bazaar@example.com'))
730@@ -511,7 +438,7 @@
731 [u'B5DEED5FCB15DAE6ECEF919587681B1EE3080E45'])
732
733 def test_set_acceptable_keys_unknown(self):
734- self.requireFeature(features.gpgme)
735+ self.requireFeature(features.gpg)
736 my_gpg = gpg.GPGStrategy(FakeConfig())
737 self.notes = []
738 def note(*args):
739@@ -526,10 +453,10 @@
740 class TestDisabled(TestCase):
741
742 def test_sign(self):
743- self.assertRaises(errors.SigningFailed,
744+ self.assertRaises(gpg.SigningFailed,
745 gpg.DisabledGPGStrategy(None).sign, 'content')
746
747 def test_verify(self):
748- self.assertRaises(errors.SignatureVerificationFailed,
749+ self.assertRaises(gpg.SignatureVerificationFailed,
750 gpg.DisabledGPGStrategy(None).verify, 'content',
751 'testament')
752
753=== modified file 'breezy/tests/test_merge_directive.py'
754--- breezy/tests/test_merge_directive.py 2017-06-10 00:17:06 +0000
755+++ breezy/tests/test_merge_directive.py 2017-07-04 21:10:26 +0000
756@@ -464,8 +464,6 @@
757 class FakeBranch(object):
758 def get_config_stack(self):
759 return self
760- def gpg_signing_command(self):
761- return 'loopback'
762 md = self.make_merge_directive('example:', 'sha', time, timezone,
763 'http://example.com', source_branch="http://example.org",
764 patch='booga', patch_type='diff')
765
766=== modified file 'doc/en/release-notes/brz-3.0.txt'
767--- doc/en/release-notes/brz-3.0.txt 2017-06-22 01:52:28 +0000
768+++ doc/en/release-notes/brz-3.0.txt 2017-07-04 21:10:26 +0000
769@@ -56,6 +56,13 @@
770 This simplifies ``brz init --help``.
771 (Neil Martinsen-Burrell, #330494)
772
773+ * ``python-gpg`` is now used for checking GPG signatures rather than
774+ ``python-gpgme``. (Jelmer Vernooij, #1702308)
775+
776+ * ``python-gpg`` is now used for signing commits, rather than shelling
777+ out to the gnupg command. The ``gpg_signing_command`` option has been
778+ removed. (Jelmer Vernooij, #847388)
779+
780 New Features
781 ************
782

Subscribers

People subscribed via source and target branches