Rev 6093: (jr) Document gpgme usage in comments. (Jonathan Riddell) in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Tue Aug 23 13:14:57 UTC 2011


At file:///home/pqm/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 6093 [merge]
revision-id: pqm at pqm.ubuntu.com-20110823131455-25rwamcvm0il00ps
parent: pqm at pqm.ubuntu.com-20110822103857-e7kb6tge3sfw4dt7
parent: jriddell at canonical.com-20110823103453-0b99yoab8ymva8sb
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Tue 2011-08-23 13:14:55 +0000
message:
  (jr) Document gpgme usage in comments. (Jonathan Riddell)
modified:
  bzrlib/commit_signature_commands.py sign_my_commits.py-20060215152201-5a6363365180e671
  bzrlib/gpg.py                  gpg.py-20051017065112-8654536d415dacc6
  bzrlib/tests/blackbox/test_sign_my_commits.py test_sign_my_commits.py-20060215152957-270238a1ffacc841
  bzrlib/tests/test_gpg.py       testgpg.py-20051017042228-9276cd40a784c93c
  doc/en/release-notes/bzr-2.5.txt bzr2.5.txt-20110708125756-587p0hpw7oke4h05-1
=== modified file 'bzrlib/commit_signature_commands.py'
--- a/bzrlib/commit_signature_commands.py	2011-06-24 13:57:59 +0000
+++ b/bzrlib/commit_signature_commands.py	2011-08-04 10:28:02 +0000
@@ -172,6 +172,11 @@
             if verbose:
                for message in gpg_strategy.verbose_valid_message(result):
                    write_verbose(message)
+            write(gpg_strategy.expired_commit_message(count))
+            if verbose:
+               for message in gpg_strategy.verbose_expired_key_message(result,
+                                                                          repo):
+                   write_verbose(message)
             write(gpg_strategy.unknown_key_message(count))
             if verbose:
                 for message in gpg_strategy.verbose_missing_key_message(result):

=== modified file 'bzrlib/gpg.py'
--- a/bzrlib/gpg.py	2011-07-11 10:53:46 +0000
+++ b/bzrlib/gpg.py	2011-08-23 10:34:53 +0000
@@ -52,6 +52,7 @@
 SIGNATURE_KEY_MISSING = 1
 SIGNATURE_NOT_VALID = 2
 SIGNATURE_NOT_SIGNED = 3
+SIGNATURE_EXPIRED = 4
 
 
 class DisabledGPGStrategy(object):
@@ -108,7 +109,8 @@
         count = {SIGNATURE_VALID: 0,
                  SIGNATURE_KEY_MISSING: 0,
                  SIGNATURE_NOT_VALID: 0,
-                 SIGNATURE_NOT_SIGNED: 0}
+                 SIGNATURE_NOT_SIGNED: 0,
+                 SIGNATURE_EXPIRED: 0}
         result = []
         all_verifiable = True
         for rev_id in revisions:
@@ -142,6 +144,12 @@
                              count[SIGNATURE_NOT_SIGNED]).format(
                                         count[SIGNATURE_NOT_SIGNED])
 
+    def expired_commit_message(self, count):
+        return i18n.ngettext(u"{0} commit with key now expired",
+                             u"{0} commits with key now expired",
+                             count[SIGNATURE_EXPIRED]).format(
+                                        count[SIGNATURE_EXPIRED])
+
 
 def _set_gpg_tty():
     tty = os.environ.get('TTY')
@@ -244,29 +252,61 @@
         except gpgme.GpgmeError,error:
             raise errors.SignatureVerificationFailed(error[2])
 
+        # No result if input is invalid.
+        # test_verify_invalid()
         if len(result) == 0:
             return SIGNATURE_NOT_VALID, None
+        # User has specified a list of acceptable keys, check our result is in it.
+        # test_verify_unacceptable_key()
         fingerprint = result[0].fpr
         if self.acceptable_keys is not None:
-            if not fingerprint in self.acceptable_keys:
+            if not fingerprint in self.acceptable_keys:                
                 return SIGNATURE_KEY_MISSING, fingerprint[-8:]
+        # Check the signature actually matches the testament.
+        # test_verify_bad_testament()
         if testament != plain_output.getvalue():
-            return SIGNATURE_NOT_VALID, None
+            return SIGNATURE_NOT_VALID, None 
+        # Yay gpgme set the valid bit.
+        # Can't write a test for this one as you can't set a key to be
+        # trusted using gpgme.
         if result[0].summary & gpgme.SIGSUM_VALID:
             key = self.context.get_key(fingerprint)
             name = key.uids[0].name
             email = key.uids[0].email
             return SIGNATURE_VALID, name + " <" + email + ">"
+        # Sigsum_red indicates a problem, unfortunatly I have not been able
+        # to write any tests which actually set this.
         if result[0].summary & gpgme.SIGSUM_RED:
             return SIGNATURE_NOT_VALID, None
+        # GPG does not know this key.
+        # test_verify_unknown_key()
         if result[0].summary & gpgme.SIGSUM_KEY_MISSING:
             return SIGNATURE_KEY_MISSING, fingerprint[-8:]
-        #summary isn't set if sig is valid but key is untrusted
+        # Summary isn't set if sig is valid but key is untrusted
+        # but if user has explicity set the key as acceptable we can validate it.
         if result[0].summary == 0 and self.acceptable_keys is not None:
             if fingerprint in self.acceptable_keys:
-                return SIGNATURE_VALID, None
-        else:
-            return SIGNATURE_KEY_MISSING, None
+                # test_verify_untrusted_but_accepted()
+                return SIGNATURE_VALID, None 
+        # test_verify_valid_but_untrusted()
+        if result[0].summary == 0 and self.acceptable_keys is None:
+            return SIGNATURE_NOT_VALID, None
+        if result[0].summary & gpgme.SIGSUM_KEY_EXPIRED:
+            expires = self.context.get_key(result[0].fpr).subkeys[0].expires
+            if expires > result[0].timestamp:
+                # The expired key was not expired at time of signing.
+                # test_verify_expired_but_valid()
+                return SIGNATURE_EXPIRED, fingerprint[-8:]
+            else:
+                # I can't work out how to create a test where the signature
+                # was expired at the time of signing.
+                return SIGNATURE_NOT_VALID, None
+        # A signature from a revoked key gets this.
+        # test_verify_revoked_signature()
+        if result[0].summary & gpgme.SIGSUM_SYS_ERROR:
+            return SIGNATURE_NOT_VALID, None
+        # Other error types such as revoked keys should (I think) be caught by
+        # SIGSUM_RED so anything else means something is buggy.
         raise errors.SignatureVerificationFailed("Unknown GnuPG key "\
                                                  "verification result")
 
@@ -322,7 +362,8 @@
         count = {SIGNATURE_VALID: 0,
                  SIGNATURE_KEY_MISSING: 0,
                  SIGNATURE_NOT_VALID: 0,
-                 SIGNATURE_NOT_SIGNED: 0}
+                 SIGNATURE_NOT_SIGNED: 0,
+                 SIGNATURE_EXPIRED: 0}
         result = []
         all_verifiable = True
         for rev_id in revisions:
@@ -397,6 +438,27 @@
                                  number).format(fingerprint, number) )
         return result
 
+    def verbose_expired_key_message(self, result, repo):
+        """takes a verify result and returns list of expired key info"""
+        signers = {}
+        fingerprint_to_authors = {}
+        for rev_id, validity, fingerprint in result:
+            if validity == SIGNATURE_EXPIRED:
+                revision = repo.get_revision(rev_id)
+                authors = ', '.join(revision.get_apparent_authors())
+                signers.setdefault(fingerprint, 0)
+                signers[fingerprint] += 1
+                fingerprint_to_authors[fingerprint] = authors
+        result = []
+        for fingerprint, number in signers.items():
+            result.append( i18n.ngettext(u"{0} commit by author {1} with "\
+                                          "key {2} now expired", 
+                                 u"{0} commits by author {1} with key {2} now "\
+                                  "expired",
+                                 number).format(number,
+                            fingerprint_to_authors[fingerprint], fingerprint) )
+        return result
+
     def valid_commits_message(self, count):
         """returns message for number of commits"""
         return i18n.gettext(u"{0} commits with valid signatures").format(
@@ -422,3 +484,10 @@
                              u"{0} commits not signed",
                              count[SIGNATURE_NOT_SIGNED]).format(
                                         count[SIGNATURE_NOT_SIGNED])
+
+    def expired_commit_message(self, count):
+        """returns message for number of commits"""
+        return i18n.ngettext(u"{0} commit with key now expired",
+                             u"{0} commits with key now expired",
+                             count[SIGNATURE_EXPIRED]).format(
+                                        count[SIGNATURE_EXPIRED])

=== modified file 'bzrlib/tests/blackbox/test_sign_my_commits.py'
--- a/bzrlib/tests/blackbox/test_sign_my_commits.py	2011-06-23 11:13:43 +0000
+++ b/bzrlib/tests/blackbox/test_sign_my_commits.py	2011-08-16 11:05:38 +0000
@@ -121,6 +121,7 @@
         self.run_bzr('sign-my-commits')
         out = self.run_bzr('verify-signatures', retcode=1)
         self.assertEquals(('4 commits with valid signatures\n'
+                           '0 commits with key now expired\n'
                            '0 commits with unknown keys\n'
                            '0 commits not valid\n'
                            '1 commit not signed\n', ''), out)
@@ -132,6 +133,7 @@
         out = self.run_bzr(['verify-signatures', '--acceptable-keys=foo,bar'],
                             retcode=1)
         self.assertEquals(('4 commits with valid signatures\n'
+                           '0 commits with key now expired\n'
                            '0 commits with unknown keys\n'
                            '0 commits not valid\n'
                            '1 commit not signed\n', ''), out)

=== modified file 'bzrlib/tests/test_gpg.py'
--- a/bzrlib/tests/test_gpg.py	2011-07-12 13:20:12 +0000
+++ b/bzrlib/tests/test_gpg.py	2011-08-04 14:39:42 +0000
@@ -91,6 +91,8 @@
         self.assertRaises(errors.BzrBadParameterUnicode,
                           self.assertProduces, u'foo')
 
+class TestVerify(TestCase):
+
     def import_keys(self):
         from StringIO import StringIO
         import gpgme
@@ -187,10 +189,59 @@
 -----END PGP PRIVATE KEY BLOCK-----
 """)
 
+        revoked_key = StringIO("""-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1.4.11 (GNU/Linux)
+
+mI0ETjlW5gEEAOb/6P+TVM59E897wRtatxys2BhsHCXM4T7xjIiANfDwejDdifqh
+tluTfSJLLxPembtrrEjux1C0AJgc+f0MIfsc3Pr3eFJzKB2ot/1IVG1/1KnA0zt3
+W2xPT3lRib27WJ9Fag+dMtQaIzgJ7/n2DFxsFZ33FD2kxrEXB2exGg6FABEBAAGI
+pgQgAQIAEAUCTjlXkAkdAHJldm9rZWQACgkQjs6dvEpb0cQPHAP/Wi9rbx0e+1Sf
+ziGgyVdr3m3A6uvze5oXKVgFRbGRUYSH4/I8GW0W9x4TcRg9h+YaQ8NUdADr9kNE
+tKAljLqYA5qdqSfYuaij1M++Xj+KUZ359R74sHuQqwnRy1XXQNfRs/QpXA7vLdds
+rjg+pbWuXO92TZJUdnqtWW+VEyZBsPy0G3Rlc3Qga2V5IDx0ZXN0QGV4YW1wbGUu
+Y29tPoi4BBMBAgAiBQJOOVbmAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAK
+CRCOzp28SlvRxNWzA/42WVmI0b+6mF/imEOlY1TiyvrcpK250rkSDsCtL4lOwy7G
+antZhpgNfnXRd/ySfsS3EB6dpOWgOSxGRvWQhA+vxBT9BYNk49qd3JIrSaSWpR12
+rET8qO1rEQQFWsw03CxTGujxGlmEO+a1yguRXp2UWaY7FngcQmD+8q7BUIVm7riN
+BE45VuYBBADTEH2jHTjNCc5CMOhea6EJTrkx3upcEqB2oyhWeSWJiBGOxlcddsjo
+3J3/EmBB8kK1hM9TidD3SG64x1N287lg8ELJBlKv+pQVyxohGJ1u/THgpTDMMQcL
+luG5rAHQGSfyzKTiOnaTyBYg3M/nzgUOU9dKEFB0EA3tjUXFOT+r3wARAQABiJ8E
+GAECAAkFAk45VuYCGwwACgkQjs6dvEpb0cRSLQP/fzCWX2lXwlwWiVF8BOPF7o9z
+icHErc7/X17RGb4qj1kVf+UkRdUWJrbEVh4h6MncBIuA70WsYogiw+Kz/0LCtQAR
+YUJsPy/EL++OKPH1aFasOdTxwkTka85+RdYqhP1+z/aYLFMWq6mRFI+o6x2k5mGi
+7dMv2kKTJPoXUpiXJbg=
+=hLYO
+-----END PGP PUBLIC KEY BLOCK-----
+""")
+
+        expired_key = StringIO("""-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1.4.11 (GNU/Linux)
+
+mI0ETjZ6PAEEALkR4GcFQidCCxV7pgQwQd5MZua0YO2l92fVqHX+PhnZ6egCLKdD
+2bWlMUd6MLPF3FlRL7BBAxvW/DazkBOp7ljsnpMpptEzY49Uem1irYLYiVb9zK96
+0sQZzFxFkfEYetQEXC68mIck8tbySOX5NAOw++3jFm3J7dsU1R3XtYzRABEBAAG0
+G3Rlc3Qga2V5IDx0ZXN0QGV4YW1wbGUuY29tPoi+BBMBAgAoBQJONno8AhsDBQkA
+AVGABgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRAc4m97T40VEz+DA/9PBphG
+Yp9cHVaHSfTUKGTGgIbvRe60sFNpDCYZeAGDrygOMuI8MNzbVpwefRBFHVPx7jWd
+rrYMsLkcsNUS9D0baU+0D/qp7JVg7ZSQtG0O6IG4eTZhibteY1fu0+unlXmg9NHx
+5VvhwzBiJDYji00M2p/CZEMiYFUuy76CsxUpN7iNBE42ejwBBACkv2/mX7IPQg0C
+A3KSrJsJv+sdvKm4b4xuI4OwagwTIVz4KlTqV4IBrVjSBfwyMXucXz0bTW85qjgA
++n67td8vyjYYZUEz1uY9lSquQQDnAN0txL3cLHZXWiWOkmzZVddQtlflK2a/J9o0
+QkHPVUm+hc4l64dIzStrNl2S66fAvQARAQABiKUEGAECAA8FAk42ejwCGwwFCQAB
+UYAACgkQHOJve0+NFROEYQP/epg+o8iBs31hkSERyZjrRR66LpywezWj30Rn/3mX
+Fzi9HkF4xLemWOzdNt9C5PYrOep85PQg8haEjknxVjZFS0ikT1h3OWk/TF1ZrLVm
+WzyX8DaHQEjKpLJJjXcAbTiZBNMk0QaVC9RvIeHpCf3n3DC49DdjsPJRMKOn8KDi
+kRk=
+=p0gt
+-----END PGP PUBLIC KEY BLOCK-----
+""")
         context.import_(key)
         context.import_(secret_key)
+        context.import_(revoked_key)
+        context.import_(expired_key)
 
-    def test_verify_valid(self):
+    def test_verify_untrusted_but_accepted(self):
+        #untrusted by gpg but listed as acceptable_keys by user
         self.requireFeature(features.gpgme)
         self.import_keys()
             
@@ -221,6 +272,67 @@
         self.assertEqual((gpg.SIGNATURE_VALID, None), my_gpg.verify(content,
                             plain))
 
+    def test_verify_unacceptable_key(self):
+        self.requireFeature(features.gpgme)
+        self.import_keys()
+            
+        content = """-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+bazaar-ng testament short form 1
+revision-id: amy at example.com-20110527185938-hluafawphszb8dl1
+sha1: 6411f9bdf6571200357140c9ce7c0f50106ac9a4
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.11 (GNU/Linux)
+
+iQEcBAEBAgAGBQJN+ekFAAoJEIdoGx7jCA5FGtEH/i+XxJRvqU6wdBtLVrGBMAGk
+FZ5VP+KyXYtymSbgSstj/vM12NeMIeFs3xGnNnYuX1MIcY6We5TKtCH0epY6ym5+
+6g2Q2QpQ5/sT2d0mWzR0K4uVngmxVQaXTdk5PdZ40O7ULeDLW6CxzxMHyUL1rsIx
+7UBUTBh1O/1n3ZfD99hUkm3hVcnsN90uTKH59zV9NWwArU0cug60+5eDKJhSJDbG
+rIwlqbFAjDZ7L/48e+IaYIJwBZFzMBpJKdCxzALLtauMf+KK8hGiL2hrRbWm7ty6
+NgxfkMYOB4rDPdSstT35N+5uBG3n/UzjxHssi0svMfVETYYX40y57dm2eZQXFp8=
+=iwsn
+-----END PGP SIGNATURE-----
+"""
+        plain = """bazaar-ng testament short form 1
+revision-id: amy at example.com-20110527185938-hluafawphszb8dl1
+sha1: 6411f9bdf6571200357140c9ce7c0f50106ac9a4
+"""
+        my_gpg = gpg.GPGStrategy(FakeConfig())
+        my_gpg.set_acceptable_keys("foo at example.com")
+        self.assertEqual((gpg.SIGNATURE_KEY_MISSING, u'E3080E45'),
+                         my_gpg.verify(content, plain))
+
+    def test_verify_valid_but_untrusted(self):
+        self.requireFeature(features.gpgme)
+        self.import_keys()
+            
+        content = """-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+bazaar-ng testament short form 1
+revision-id: amy at example.com-20110527185938-hluafawphszb8dl1
+sha1: 6411f9bdf6571200357140c9ce7c0f50106ac9a4
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.11 (GNU/Linux)
+
+iQEcBAEBAgAGBQJN+ekFAAoJEIdoGx7jCA5FGtEH/i+XxJRvqU6wdBtLVrGBMAGk
+FZ5VP+KyXYtymSbgSstj/vM12NeMIeFs3xGnNnYuX1MIcY6We5TKtCH0epY6ym5+
+6g2Q2QpQ5/sT2d0mWzR0K4uVngmxVQaXTdk5PdZ40O7ULeDLW6CxzxMHyUL1rsIx
+7UBUTBh1O/1n3ZfD99hUkm3hVcnsN90uTKH59zV9NWwArU0cug60+5eDKJhSJDbG
+rIwlqbFAjDZ7L/48e+IaYIJwBZFzMBpJKdCxzALLtauMf+KK8hGiL2hrRbWm7ty6
+NgxfkMYOB4rDPdSstT35N+5uBG3n/UzjxHssi0svMfVETYYX40y57dm2eZQXFp8=
+=iwsn
+-----END PGP SIGNATURE-----
+"""
+        plain = """bazaar-ng testament short form 1
+revision-id: amy at example.com-20110527185938-hluafawphszb8dl1
+sha1: 6411f9bdf6571200357140c9ce7c0f50106ac9a4
+"""
+        my_gpg = gpg.GPGStrategy(FakeConfig())
+        self.assertEqual((gpg.SIGNATURE_NOT_VALID, None), my_gpg.verify(content,
+                            plain))
+
     def test_verify_bad_testament(self):
         self.requireFeature(features.gpgme)
         self.import_keys()
@@ -252,6 +364,31 @@
         self.assertEqual((gpg.SIGNATURE_NOT_VALID, None), my_gpg.verify(content,
                             plain))
 
+
+    def test_verify_revoked_signature(self):
+        self.requireFeature(features.gpgme)
+        self.import_keys()
+            
+        content = """-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+asdf
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.11 (GNU/Linux)
+
+iJwEAQECAAYFAk45V18ACgkQjs6dvEpb0cSIZQP/eOGTXGPlrNwvDkcX2d8O///I
+ecB4sUIUEpv1XAk1MkNu58lsjjK72lRaLusEGqd7HwrFmpxVeVs0oWLg23PNPCFs
+yJBID9ma+VxFVPtkEFnrc1R72sBJLfBcTxMkwVTC8eeznjdtn+cg+aLkxbPdrGnr
+JFA6kUIJU2w9LU/b88Y=
+=UuRX
+-----END PGP SIGNATURE-----
+"""
+        plain = """asdf\n"""
+        my_gpg = gpg.GPGStrategy(FakeConfig())
+        my_gpg.set_acceptable_keys("test at example.com")
+        self.assertEqual((gpg.SIGNATURE_NOT_VALID, None), my_gpg.verify(content,
+                            plain))
+
     def test_verify_invalid(self):
         self.requireFeature(features.gpgme)
         content = """-----BEGIN PGP SIGNED MESSAGE-----
@@ -276,6 +413,55 @@
         self.assertEqual((gpg.SIGNATURE_NOT_VALID, None),
                             my_gpg.verify(content, plain))
 
+    def test_verify_expired_but_valid(self):
+        self.requireFeature(features.gpgme)
+        content = """-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+ 
+bazaar-ng testament short form 1
+revision-id: test at example.com-20110801100657-f1dr1nompeex723z
+sha1: 59ab434be4c2d5d646dee84f514aa09e1b72feeb
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.10 (GNU/Linux)
+ 
+iJwEAQECAAYFAk42esUACgkQHOJve0+NFRPc5wP7BoZkzBU8JaHMLv/LmqLr0sUz
+zuE51ofZZ19L7KVtQWsOi4jFy0fi4A5TFwO8u9SOfoREGvkw292Uty9subSouK5/
+mFmDOYPQ+O83zWgYZsBmMJWYDZ+X9I6XXZSbPtV/7XyTjaxtl5uRnDVJjg+AzKvD
+dTp8VatVVrwuvzOPDVc=
+=uHen
+-----END PGP SIGNATURE-----
+"""
+        plain = """bazaar-ng testament short form 1
+revision-id: test at example.com-20110801100657-f1dr1nompeex723z
+sha1: 59ab434be4c2d5d646dee84f514aa09e1b72feeb
+"""
+        my_gpg = gpg.GPGStrategy(FakeConfig())
+        self.assertEqual((gpg.SIGNATURE_EXPIRED, u'4F8D1513'),
+                            my_gpg.verify(content, plain))
+
+    def test_verify_unknown_key(self):
+        self.requireFeature(features.gpgme)
+        content = """-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+asdf
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.11 (GNU/Linux)
+
+iQEcBAEBAgAGBQJOORKwAAoJENf6AkFdUeVvJDYH/1Cz+AJn1Jvy5n64o+0fZ5Ow
+Y7UQb4QQTIOV7jI7n4hv/yBzuHrtImFzYvQl/o2Ezzi8B8L5gZtQy+xCUF+Q8iWs
+gytZ5JUtSze7hDZo1NUl4etjoRGYqRfrUcvE2LkVH2dFbDGyyQfVmoeSHa5akuuP
+QZmyg2F983rACVIpGvsqTH6RcBdvE9vx68lugeKQA8ArDn39/74FBFipFzrXSPij
+eKFpl+yZmIb3g6HkPIC8o4j/tMvc37xF1OG5sBu8FT0+FC+VgY7vAblneDftAbyP
+sIODx4WcfJtjLG/qkRYqJ4gDHo0eMpTJSk2CWebajdm4b+JBrM1F9mgKuZFLruE=
+=RNR5
+-----END PGP SIGNATURE-----
+"""
+        plain = "asdf\n"
+        my_gpg = gpg.GPGStrategy(FakeConfig())
+        self.assertEqual((gpg.SIGNATURE_KEY_MISSING, u'5D51E56F'),
+                            my_gpg.verify(content, plain))
+
     def test_set_acceptable_keys(self):
         self.requireFeature(features.gpgme)
         self.import_keys()

=== modified file 'doc/en/release-notes/bzr-2.5.txt'
--- a/doc/en/release-notes/bzr-2.5.txt	2011-08-20 14:41:12 +0000
+++ b/doc/en/release-notes/bzr-2.5.txt	2011-08-23 10:27:54 +0000
@@ -81,11 +81,15 @@
 * Relative local paths can now be specified in URL syntax by using the
   "file:" prefix.  (Jelmer Vernooij)
 
+* Report commits signed with expired keys in "verify-signatures".
+  (Jonathan Riddell, #804254)
+
 * bzr add now skips large files in recursive mode. The default "large"
   size is 20MB, and is configurable via the add.maximum_file_size
   option. A value of 0 disables skipping. Named items passed to add are
   never skipped. (Shannon Weyrick, #54624)
 
+
 Improvements
 ************
 




More information about the bazaar-commits mailing list