~bzr-pqm/bzr/bzr.dev

5752.3.8 by John Arbash Meinel
Merge bzr.dev 5764 to resolve release-notes (aka NEWS) conflicts
1
# Copyright (C) 2006, 2007, 2009, 2010, 2011 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1185.78.6 by John Arbash Meinel
Adding sign-my-commits as a builtin, along with some simple tests.
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1185.78.6 by John Arbash Meinel
Adding sign-my-commits as a builtin, along with some simple tests.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1185.78.6 by John Arbash Meinel
Adding sign-my-commits as a builtin, along with some simple tests.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1732.2.3 by Martin Pool
sign-my-commits just signs revisions in the branch's ancestry.
16
1185.78.6 by John Arbash Meinel
Adding sign-my-commits as a builtin, along with some simple tests.
17
"""Command which looks for unsigned commits by the current user, and signs them.
18
"""
19
6379.6.7 by Jelmer Vernooij
Move importing from future until after doc string, otherwise the doc string will disappear.
20
from __future__ import absolute_import
21
1996.3.14 by John Arbash Meinel
lazy_import osutils and sign_my_commits
22
from bzrlib.lazy_import import lazy_import
23
lazy_import(globals(), """
24
from bzrlib import (
6207.3.3 by jelmer at samba
Fix tests and the like.
25
    controldir,
5972.3.23 by Jelmer Vernooij
Fix handling of ghosts in sign_my_commits.
26
    errors,
1996.3.14 by John Arbash Meinel
lazy_import osutils and sign_my_commits
27
    gpg,
5972.3.2 by Jelmer Vernooij
Use iter_ancestry rather than get_ancestry.
28
    revision as _mod_revision,
1996.3.14 by John Arbash Meinel
lazy_import osutils and sign_my_commits
29
    )
30
""")
1185.78.6 by John Arbash Meinel
Adding sign-my-commits as a builtin, along with some simple tests.
31
from bzrlib.commands import Command
32
from bzrlib.option import Option
5971.1.24 by Jonathan Riddell
fix translations for plural forms
33
from bzrlib.i18n import gettext, ngettext
1185.78.6 by John Arbash Meinel
Adding sign-my-commits as a builtin, along with some simple tests.
34
35
class cmd_sign_my_commits(Command):
5131.2.1 by Martin
Permit bzrlib to run under python -OO by explictly assigning to __doc__ for user-visible docstrings
36
    __doc__ = """Sign all commits by a given committer.
1185.78.6 by John Arbash Meinel
Adding sign-my-commits as a builtin, along with some simple tests.
37
38
    If location is not specified the local tree is used.
39
    If committer is not specified the default committer is used.
40
41
    This does not sign commits that already have signatures.
42
    """
1732.2.3 by Martin Pool
sign-my-commits just signs revisions in the branch's ancestry.
43
    # Note that this signs everything on the branch's ancestry
44
    # (both mainline and merged), but not other revisions that may be in the
45
    # repository
1185.78.6 by John Arbash Meinel
Adding sign-my-commits as a builtin, along with some simple tests.
46
2598.1.2 by Martin Pool
Also check that option help ends in a period, and fix those that don't
47
    takes_options = [
48
            Option('dry-run',
49
                   help='Don\'t actually sign anything, just print'
50
                        ' the revisions that would be signed.'),
51
            ]
1185.78.6 by John Arbash Meinel
Adding sign-my-commits as a builtin, along with some simple tests.
52
    takes_args = ['location?', 'committer?']
53
54
    def run(self, location=None, committer=None, dry_run=False):
55
        if location is None:
6207.3.3 by jelmer at samba
Fix tests and the like.
56
            bzrdir = controldir.ControlDir.open_containing('.')[0]
1185.78.6 by John Arbash Meinel
Adding sign-my-commits as a builtin, along with some simple tests.
57
        else:
58
            # Passed in locations should be exact
6207.3.3 by jelmer at samba
Fix tests and the like.
59
            bzrdir = controldir.ControlDir.open(location)
1732.2.3 by Martin Pool
sign-my-commits just signs revisions in the branch's ancestry.
60
        branch = bzrdir.open_branch()
61
        repo = branch.repository
6449.6.4 by Jelmer Vernooij
Use config stack.
62
        branch_config = branch.get_config_stack()
1185.78.6 by John Arbash Meinel
Adding sign-my-commits as a builtin, along with some simple tests.
63
64
        if committer is None:
6449.6.4 by Jelmer Vernooij
Use config stack.
65
            committer = branch_config.get('email')
66
        gpg_strategy = gpg.GPGStrategy(branch_config)
1185.78.6 by John Arbash Meinel
Adding sign-my-commits as a builtin, along with some simple tests.
67
68
        count = 0
1711.2.35 by John Arbash Meinel
sign-my-commits should take out a write lock.
69
        repo.lock_write()
70
        try:
5972.3.2 by Jelmer Vernooij
Use iter_ancestry rather than get_ancestry.
71
            graph = repo.get_graph()
3010.1.15 by Robert Collins
Manage write groups in sign_my_commits, for efficiency.
72
            repo.start_write_group()
73
            try:
5972.3.2 by Jelmer Vernooij
Use iter_ancestry rather than get_ancestry.
74
                for rev_id, parents in graph.iter_ancestry(
75
                        [branch.last_revision()]):
76
                    if _mod_revision.is_null(rev_id):
77
                        continue
5972.3.24 by Jelmer Vernooij
Simplify ghost check.
78
                    if parents is None:
79
                        # Ignore ghosts
80
                        continue
81
                    if repo.has_signature_for_revision_id(rev_id):
3010.1.15 by Robert Collins
Manage write groups in sign_my_commits, for efficiency.
82
                        continue
83
                    rev = repo.get_revision(rev_id)
84
                    if rev.committer != committer:
85
                        continue
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
86
                    # We have a revision without a signature who has a
3010.1.15 by Robert Collins
Manage write groups in sign_my_commits, for efficiency.
87
                    # matching committer, start signing
88
                    print rev_id
89
                    count += 1
90
                    if not dry_run:
91
                        repo.sign_revision(rev_id, gpg_strategy)
92
            except:
93
                repo.abort_write_group()
94
                raise
95
            else:
96
                repo.commit_write_group()
1711.2.35 by John Arbash Meinel
sign-my-commits should take out a write lock.
97
        finally:
98
            repo.unlock()
1185.78.6 by John Arbash Meinel
Adding sign-my-commits as a builtin, along with some simple tests.
99
        print 'Signed %d revisions' % (count,)
100
101
5971.1.52 by Jonathan Riddell
change command name to verify-signatures
102
class cmd_verify_signatures(Command):
5971.1.3 by Jonathan Riddell
tidying up
103
    __doc__ = """Verify all commit signatures.
104
105
    Verifies that all commits in the branch are signed by known GnuPG keys.
5971.1.1 by Jonathan Riddell
add a verify command
106
    """
5971.1.3 by Jonathan Riddell
tidying up
107
5971.1.12 by Jonathan Riddell
add acceptable-keys option
108
    takes_options = [
109
            Option('acceptable-keys',
110
                   help='Comma separated list of GPG key patterns which are'
111
                        ' acceptable for verification.',
112
                   short_name='k',
113
                   type=str,),
5971.1.17 by Jonathan Riddell
add verbose option
114
            'revision', 
115
            'verbose',
5971.1.15 by Jonathan Riddell
add a revision argument to bzr verify
116
          ]
5971.1.76 by Jonathan Riddell
change directory option to location argument
117
    takes_args = ['location?']
5971.1.12 by Jonathan Riddell
add acceptable-keys option
118
5971.1.53 by Jonathan Riddell
add directory option
119
    def run(self, acceptable_keys=None, revision=None, verbose=None,
5971.1.76 by Jonathan Riddell
change directory option to location argument
120
                                                            location=u'.'):
6207.3.3 by jelmer at samba
Fix tests and the like.
121
        bzrdir = controldir.ControlDir.open_containing(location)[0]
5971.1.1 by Jonathan Riddell
add a verify command
122
        branch = bzrdir.open_branch()
123
        repo = branch.repository
6351.3.2 by Jelmer Vernooij
Convert some gpg options to config stacks.
124
        branch_config = branch.get_config_stack()
5971.1.1 by Jonathan Riddell
add a verify command
125
        gpg_strategy = gpg.GPGStrategy(branch_config)
5971.1.56 by Jonathan Riddell
add an option for acceptable_keys in config, also make config docs match reality for signature options
126
5971.1.69 by Jonathan Riddell
move some code from cmd_verify to gpg.set_acceptable_keys
127
        gpg_strategy.set_acceptable_keys(acceptable_keys)
5971.1.70 by Jonathan Riddell
move code which does verifications of revisions from cmd_verify_signatures to gpg.do_verifications
128
5971.1.74 by Jonathan Riddell
formatting changes necessary for qbzr
129
        def write(string):
130
            self.outf.write(string + "\n")
131
        def write_verbose(string):
132
            self.outf.write("  " + string + "\n")
133
5971.1.70 by Jonathan Riddell
move code which does verifications of revisions from cmd_verify_signatures to gpg.do_verifications
134
        #get our list of revisions
5971.1.15 by Jonathan Riddell
add a revision argument to bzr verify
135
        revisions = []
136
        if revision is not None:
137
            if len(revision) == 1:
138
                revno, rev_id = revision[0].in_history(branch)
139
                revisions.append(rev_id)
140
            elif len(revision) == 2:
141
                from_revno, from_revid = revision[0].in_history(branch)
142
                to_revno, to_revid = revision[1].in_history(branch)
143
                if to_revid is None:
144
                    to_revno = branch.revno()
145
                if from_revno is None or to_revno is None:
6138.3.1 by Jonathan Riddell
use gettext() in more files
146
                    raise errors.BzrCommandError(gettext(
147
                    'Cannot verify a range of non-revision-history revisions'))
5971.1.15 by Jonathan Riddell
add a revision argument to bzr verify
148
                for revno in range(from_revno, to_revno + 1):
149
                    revisions.append(branch.get_rev_id(revno))
150
        else:
5971.1.16 by Jonathan Riddell
tidying
151
            #all revisions by default including merges
5971.1.50 by Jonathan Riddell
merge in trunk
152
            graph = repo.get_graph()
153
            revisions = []
154
            repo.lock_read()
155
            for rev_id, parents in graph.iter_ancestry(
156
                    [branch.last_revision()]):
157
                if _mod_revision.is_null(rev_id):
158
                    continue
159
                if parents is None:
160
                    # Ignore ghosts
161
                    continue
162
                revisions.append(rev_id)
163
            repo.unlock()
5971.1.70 by Jonathan Riddell
move code which does verifications of revisions from cmd_verify_signatures to gpg.do_verifications
164
        count, result, all_verifiable =\
165
                                gpg_strategy.do_verifications(revisions, repo)
166
        if all_verifiable:
5971.1.74 by Jonathan Riddell
formatting changes necessary for qbzr
167
               write(gettext(
5971.1.76 by Jonathan Riddell
change directory option to location argument
168
                            "All commits signed with verifiable keys"))
5971.1.17 by Jonathan Riddell
add verbose option
169
               if verbose:
5971.1.74 by Jonathan Riddell
formatting changes necessary for qbzr
170
                   write(gpg_strategy.verbose_valid_message(result))
5971.1.2 by Jonathan Riddell
give result to user
171
               return 0
172
        else:
5971.1.74 by Jonathan Riddell
formatting changes necessary for qbzr
173
            write(gpg_strategy.valid_commits_message(count))
174
            if verbose:
5971.1.75 by Jonathan Riddell
fix verbose messages, now return a list
175
               for message in gpg_strategy.verbose_valid_message(result):
176
                   write_verbose(message)
6043.3.1 by Jonathan Riddell
Report commits signed with expired keys in "verify-signatures".
177
            write(gpg_strategy.expired_commit_message(count))
178
            if verbose:
179
               for message in gpg_strategy.verbose_expired_key_message(result,
180
                                                                          repo):
181
                   write_verbose(message)
5971.1.74 by Jonathan Riddell
formatting changes necessary for qbzr
182
            write(gpg_strategy.unknown_key_message(count))
183
            if verbose:
5971.1.75 by Jonathan Riddell
fix verbose messages, now return a list
184
                for message in gpg_strategy.verbose_missing_key_message(result):
185
                    write_verbose(message)
5971.1.74 by Jonathan Riddell
formatting changes necessary for qbzr
186
            write(gpg_strategy.commit_not_valid_message(count))
187
            if verbose:
5971.1.75 by Jonathan Riddell
fix verbose messages, now return a list
188
                for message in gpg_strategy.verbose_not_valid_message(result,
189
                                                                        repo):
190
                   write_verbose(message)
5971.1.74 by Jonathan Riddell
formatting changes necessary for qbzr
191
            write(gpg_strategy.commit_not_signed_message(count))
192
            if verbose:
5971.1.75 by Jonathan Riddell
fix verbose messages, now return a list
193
                for message in gpg_strategy.verbose_not_signed_message(result,
194
                                                                          repo):
195
                    write_verbose(message)
5971.1.2 by Jonathan Riddell
give result to user
196
            return 1