1
# Copyright (C) 2006, 2007, 2009, 2010, 2011 Canonical Ltd
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.
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.
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
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
"""Command which looks for unsigned commits by the current user, and signs them.
20
from __future__ import absolute_import
22
from bzrlib.lazy_import import lazy_import
23
lazy_import(globals(), """
28
revision as _mod_revision,
31
from bzrlib.commands import Command
32
from bzrlib.option import Option
33
from bzrlib.i18n import gettext, ngettext
35
class cmd_sign_my_commits(Command):
36
__doc__ = """Sign all commits by a given committer.
38
If location is not specified the local tree is used.
39
If committer is not specified the default committer is used.
41
This does not sign commits that already have signatures.
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
49
help='Don\'t actually sign anything, just print'
50
' the revisions that would be signed.'),
52
takes_args = ['location?', 'committer?']
54
def run(self, location=None, committer=None, dry_run=False):
56
bzrdir = controldir.ControlDir.open_containing('.')[0]
58
# Passed in locations should be exact
59
bzrdir = controldir.ControlDir.open(location)
60
branch = bzrdir.open_branch()
61
repo = branch.repository
62
branch_config = branch.get_config_stack()
65
committer = branch_config.get('email')
66
gpg_strategy = gpg.GPGStrategy(branch_config)
71
graph = repo.get_graph()
72
repo.start_write_group()
74
for rev_id, parents in graph.iter_ancestry(
75
[branch.last_revision()]):
76
if _mod_revision.is_null(rev_id):
81
if repo.has_signature_for_revision_id(rev_id):
83
rev = repo.get_revision(rev_id)
84
if rev.committer != committer:
86
# We have a revision without a signature who has a
87
# matching committer, start signing
91
repo.sign_revision(rev_id, gpg_strategy)
93
repo.abort_write_group()
96
repo.commit_write_group()
99
print 'Signed %d revisions' % (count,)
102
class cmd_verify_signatures(Command):
103
__doc__ = """Verify all commit signatures.
105
Verifies that all commits in the branch are signed by known GnuPG keys.
109
Option('acceptable-keys',
110
help='Comma separated list of GPG key patterns which are'
111
' acceptable for verification.',
117
takes_args = ['location?']
119
def run(self, acceptable_keys=None, revision=None, verbose=None,
121
bzrdir = controldir.ControlDir.open_containing(location)[0]
122
branch = bzrdir.open_branch()
123
repo = branch.repository
124
branch_config = branch.get_config_stack()
125
gpg_strategy = gpg.GPGStrategy(branch_config)
127
gpg_strategy.set_acceptable_keys(acceptable_keys)
130
self.outf.write(string + "\n")
131
def write_verbose(string):
132
self.outf.write(" " + string + "\n")
134
#get our list of 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)
144
to_revno = branch.revno()
145
if from_revno is None or to_revno is None:
146
raise errors.BzrCommandError(gettext(
147
'Cannot verify a range of non-revision-history revisions'))
148
for revno in range(from_revno, to_revno + 1):
149
revisions.append(branch.get_rev_id(revno))
151
#all revisions by default including merges
152
graph = repo.get_graph()
155
for rev_id, parents in graph.iter_ancestry(
156
[branch.last_revision()]):
157
if _mod_revision.is_null(rev_id):
162
revisions.append(rev_id)
164
count, result, all_verifiable =\
165
gpg_strategy.do_verifications(revisions, repo)
168
"All commits signed with verifiable keys"))
170
write(gpg_strategy.verbose_valid_message(result))
173
write(gpg_strategy.valid_commits_message(count))
175
for message in gpg_strategy.verbose_valid_message(result):
176
write_verbose(message)
177
write(gpg_strategy.expired_commit_message(count))
179
for message in gpg_strategy.verbose_expired_key_message(result,
181
write_verbose(message)
182
write(gpg_strategy.unknown_key_message(count))
184
for message in gpg_strategy.verbose_missing_key_message(result):
185
write_verbose(message)
186
write(gpg_strategy.commit_not_valid_message(count))
188
for message in gpg_strategy.verbose_not_valid_message(result,
190
write_verbose(message)
191
write(gpg_strategy.commit_not_signed_message(count))
193
for message in gpg_strategy.verbose_not_signed_message(result,
195
write_verbose(message)