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 that signs unsigned commits by the current user. """
23
repository as _mod_repository,
24
revision as _mod_revision,
26
from .commands import Command
27
from .option import Option
28
from .i18n import gettext, ngettext
31
class cmd_sign_my_commits(Command):
32
__doc__ = """Sign all commits by a given committer.
34
If location is not specified the local tree is used.
35
If committer is not specified the default committer is used.
37
This does not sign commits that already have signatures.
39
# Note that this signs everything on the branch's ancestry
40
# (both mainline and merged), but not other revisions that may be in the
45
help='Don\'t actually sign anything, just print'
46
' the revisions that would be signed.'),
48
takes_args = ['location?', 'committer?']
50
def run(self, location=None, committer=None, dry_run=False):
52
bzrdir = controldir.ControlDir.open_containing('.')[0]
54
# Passed in locations should be exact
55
bzrdir = controldir.ControlDir.open(location)
56
branch = bzrdir.open_branch()
57
repo = branch.repository
58
branch_config = branch.get_config_stack()
61
committer = branch_config.get('email')
62
gpg_strategy = gpg.GPGStrategy(branch_config)
65
with repo.lock_write():
66
graph = repo.get_graph()
67
with _mod_repository.WriteGroup(repo):
68
for rev_id, parents in graph.iter_ancestry(
69
[branch.last_revision()]):
70
if _mod_revision.is_null(rev_id):
75
if repo.has_signature_for_revision_id(rev_id):
77
rev = repo.get_revision(rev_id)
78
if rev.committer != committer:
80
# We have a revision without a signature who has a
81
# matching committer, start signing
82
self.outf.write("%s\n" % rev_id)
85
repo.sign_revision(rev_id, gpg_strategy)
87
ngettext('Signed %d revision.\n', 'Signed %d revisions.\n',
91
class cmd_verify_signatures(Command):
92
__doc__ = """Verify all commit signatures.
94
Verifies that all commits in the branch are signed by known GnuPG keys.
98
Option('acceptable-keys',
99
help='Comma separated list of GPG key patterns which are'
100
' acceptable for verification.',
106
takes_args = ['location?']
108
def run(self, acceptable_keys=None, revision=None, verbose=None,
110
bzrdir = controldir.ControlDir.open_containing(location)[0]
111
branch = bzrdir.open_branch()
112
repo = branch.repository
113
branch_config = branch.get_config_stack()
114
gpg_strategy = gpg.GPGStrategy(branch_config)
116
gpg_strategy.set_acceptable_keys(acceptable_keys)
119
self.outf.write(string + "\n")
121
def write_verbose(string):
122
self.outf.write(" " + string + "\n")
124
self.add_cleanup(repo.lock_read().unlock)
125
# get our list of revisions
127
if revision is not None:
128
if len(revision) == 1:
129
revno, rev_id = revision[0].in_history(branch)
130
revisions.append(rev_id)
131
elif len(revision) == 2:
132
from_revno, from_revid = revision[0].in_history(branch)
133
to_revno, to_revid = revision[1].in_history(branch)
135
to_revno = branch.revno()
136
if from_revno is None or to_revno is None:
137
raise errors.BzrCommandError(
138
gettext('Cannot verify a range of non-revision-history'
140
for revno in range(from_revno, to_revno + 1):
141
revisions.append(branch.get_rev_id(revno))
143
# all revisions by default including merges
144
graph = repo.get_graph()
146
for rev_id, parents in graph.iter_ancestry(
147
[branch.last_revision()]):
148
if _mod_revision.is_null(rev_id):
153
revisions.append(rev_id)
154
count, result, all_verifiable = gpg.bulk_verify_signatures(
155
repo, revisions, gpg_strategy)
157
write(gettext("All commits signed with verifiable keys"))
159
for message in gpg.verbose_valid_message(result):
160
write_verbose(message)
163
write(gpg.valid_commits_message(count))
165
for message in gpg.verbose_valid_message(result):
166
write_verbose(message)
167
write(gpg.expired_commit_message(count))
169
for message in gpg.verbose_expired_key_message(result, repo):
170
write_verbose(message)
171
write(gpg.unknown_key_message(count))
173
for message in gpg.verbose_missing_key_message(result):
174
write_verbose(message)
175
write(gpg.commit_not_valid_message(count))
177
for message in gpg.verbose_not_valid_message(result, repo):
178
write_verbose(message)
179
write(gpg.commit_not_signed_message(count))
181
for message in gpg.verbose_not_signed_message(result, repo):
182
write_verbose(message)