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
26
revision as _mod_revision,
28
from bzrlib.commands import Command
29
from bzrlib.option import Option
30
from bzrlib.i18n import gettext, ngettext
33
class cmd_sign_my_commits(Command):
34
__doc__ = """Sign all commits by a given committer.
36
If location is not specified the local tree is used.
37
If committer is not specified the default committer is used.
39
This does not sign commits that already have signatures.
41
# Note that this signs everything on the branch's ancestry
42
# (both mainline and merged), but not other revisions that may be in the
47
help='Don\'t actually sign anything, just print'
48
' the revisions that would be signed.'),
50
takes_args = ['location?', 'committer?']
52
def run(self, location=None, committer=None, dry_run=False):
54
bzrdir = controldir.ControlDir.open_containing('.')[0]
56
# Passed in locations should be exact
57
bzrdir = controldir.ControlDir.open(location)
58
branch = bzrdir.open_branch()
59
repo = branch.repository
60
branch_config = branch.get_config_stack()
63
committer = branch_config.get('email')
64
gpg_strategy = gpg.GPGStrategy(branch_config)
69
graph = repo.get_graph()
70
repo.start_write_group()
72
for rev_id, parents in graph.iter_ancestry(
73
[branch.last_revision()]):
74
if _mod_revision.is_null(rev_id):
79
if repo.has_signature_for_revision_id(rev_id):
81
rev = repo.get_revision(rev_id)
82
if rev.committer != committer:
84
# We have a revision without a signature who has a
85
# matching committer, start signing
86
self.outf.write("%s\n" % rev_id)
89
repo.sign_revision(rev_id, gpg_strategy)
91
repo.abort_write_group()
94
repo.commit_write_group()
98
ngettext('Signed %d revision.\n', 'Signed %d revisions.\n', 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
self.add_cleanup(repo.lock_read().unlock)
135
#get our list of revisions
137
if revision is not None:
138
if len(revision) == 1:
139
revno, rev_id = revision[0].in_history(branch)
140
revisions.append(rev_id)
141
elif len(revision) == 2:
142
from_revno, from_revid = revision[0].in_history(branch)
143
to_revno, to_revid = revision[1].in_history(branch)
145
to_revno = branch.revno()
146
if from_revno is None or to_revno is None:
147
raise errors.BzrCommandError(gettext(
148
'Cannot verify a range of non-revision-history revisions'))
149
for revno in range(from_revno, to_revno + 1):
150
revisions.append(branch.get_rev_id(revno))
152
#all revisions by default including merges
153
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)
163
count, result, all_verifiable = gpg.bulk_verify_signatures(
164
repo, revisions, gpg_strategy)
166
write(gettext("All commits signed with verifiable keys"))
168
for message in gpg.verbose_valid_message(result):
169
write_verbose(message)
172
write(gpg.valid_commits_message(count))
174
for message in gpg.verbose_valid_message(result):
175
write_verbose(message)
176
write(gpg.expired_commit_message(count))
178
for message in gpg.verbose_expired_key_message(result, repo):
179
write_verbose(message)
180
write(gpg.unknown_key_message(count))
182
for message in gpg.verbose_missing_key_message(result):
183
write_verbose(message)
184
write(gpg.commit_not_valid_message(count))
186
for message in gpg.verbose_not_valid_message(result, repo):
187
write_verbose(message)
188
write(gpg.commit_not_signed_message(count))
190
for message in gpg.verbose_not_signed_message(result, repo):
191
write_verbose(message)