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 .commands import Command
29
from .option import Option
30
from .i18n import gettext, ngettext
31
from .sixish import text_type
34
class cmd_sign_my_commits(Command):
35
__doc__ = """Sign all commits by a given committer.
37
If location is not specified the local tree is used.
38
If committer is not specified the default committer is used.
40
This does not sign commits that already have signatures.
42
# Note that this signs everything on the branch's ancestry
43
# (both mainline and merged), but not other revisions that may be in the
48
help='Don\'t actually sign anything, just print'
49
' the revisions that would be signed.'),
51
takes_args = ['location?', 'committer?']
53
def run(self, location=None, committer=None, dry_run=False):
55
bzrdir = controldir.ControlDir.open_containing('.')[0]
57
# Passed in locations should be exact
58
bzrdir = controldir.ControlDir.open(location)
59
branch = bzrdir.open_branch()
60
repo = branch.repository
61
branch_config = branch.get_config_stack()
64
committer = branch_config.get('email')
65
gpg_strategy = gpg.GPGStrategy(branch_config)
70
graph = repo.get_graph()
71
repo.start_write_group()
73
for rev_id, parents in graph.iter_ancestry(
74
[branch.last_revision()]):
75
if _mod_revision.is_null(rev_id):
80
if repo.has_signature_for_revision_id(rev_id):
82
rev = repo.get_revision(rev_id)
83
if rev.committer != committer:
85
# We have a revision without a signature who has a
86
# matching committer, start signing
87
self.outf.write("%s\n" % rev_id)
90
repo.sign_revision(rev_id, gpg_strategy)
92
repo.abort_write_group()
95
repo.commit_write_group()
99
ngettext('Signed %d revision.\n', 'Signed %d revisions.\n', count) %
103
class cmd_verify_signatures(Command):
104
__doc__ = """Verify all commit signatures.
106
Verifies that all commits in the branch are signed by known GnuPG keys.
110
Option('acceptable-keys',
111
help='Comma separated list of GPG key patterns which are'
112
' acceptable for verification.',
118
takes_args = ['location?']
120
def run(self, acceptable_keys=None, revision=None, verbose=None,
122
bzrdir = controldir.ControlDir.open_containing(location)[0]
123
branch = bzrdir.open_branch()
124
repo = branch.repository
125
branch_config = branch.get_config_stack()
126
gpg_strategy = gpg.GPGStrategy(branch_config)
128
gpg_strategy.set_acceptable_keys(acceptable_keys)
131
self.outf.write(string + "\n")
132
def write_verbose(string):
133
self.outf.write(" " + string + "\n")
135
self.add_cleanup(repo.lock_read().unlock)
136
#get our list of revisions
138
if revision is not None:
139
if len(revision) == 1:
140
revno, rev_id = revision[0].in_history(branch)
141
revisions.append(rev_id)
142
elif len(revision) == 2:
143
from_revno, from_revid = revision[0].in_history(branch)
144
to_revno, to_revid = revision[1].in_history(branch)
146
to_revno = branch.revno()
147
if from_revno is None or to_revno is None:
148
raise errors.BzrCommandError(gettext(
149
'Cannot verify a range of non-revision-history revisions'))
150
for revno in range(from_revno, to_revno + 1):
151
revisions.append(branch.get_rev_id(revno))
153
#all revisions by default including merges
154
graph = repo.get_graph()
156
for rev_id, parents in graph.iter_ancestry(
157
[branch.last_revision()]):
158
if _mod_revision.is_null(rev_id):
163
revisions.append(rev_id)
164
count, result, all_verifiable = gpg.bulk_verify_signatures(
165
repo, revisions, gpg_strategy)
167
write(gettext("All commits signed with verifiable keys"))
169
for message in gpg.verbose_valid_message(result):
170
write_verbose(message)
173
write(gpg.valid_commits_message(count))
175
for message in gpg.verbose_valid_message(result):
176
write_verbose(message)
177
write(gpg.expired_commit_message(count))
179
for message in gpg.verbose_expired_key_message(result, repo):
180
write_verbose(message)
181
write(gpg.unknown_key_message(count))
183
for message in gpg.verbose_missing_key_message(result):
184
write_verbose(message)
185
write(gpg.commit_not_valid_message(count))
187
for message in gpg.verbose_not_valid_message(result, repo):
188
write_verbose(message)
189
write(gpg.commit_not_signed_message(count))
191
for message in gpg.verbose_not_signed_message(result, repo):
192
write_verbose(message)