1
# Copyright (C) 2006, 2007, 2009, 2010, 2011 Canonical Ltd
1
# Copyright (C) 2005, 2006 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
11
# GNU General Public License for more details.
13
13
# You should have received a copy of the GNU General Public License
14
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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
16
"""Command which looks for unsigned commits by the current user, and signs them.
20
from bzrlib.lazy_import import lazy_import
21
lazy_import(globals(), """
23
bzrdir as _mod_bzrdir,
26
revision as _mod_revision,
29
19
from bzrlib.commands import Command
21
import bzrlib.errors as errors
30
23
from bzrlib.option import Option
31
from bzrlib.i18n import gettext, ngettext
33
26
class cmd_sign_my_commits(Command):
34
__doc__ = """Sign all commits by a given committer.
27
"""Sign all commits by a given committer.
36
29
If location is not specified the local tree is used.
37
30
If committer is not specified the default committer is used.
39
32
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.'),
35
takes_options = [Option('dry-run'
36
, help='Don\'t actually sign anything, just print'
37
' the revisions that would be signed')
50
39
takes_args = ['location?', 'committer?']
52
41
def run(self, location=None, committer=None, dry_run=False):
53
42
if location is None:
54
bzrdir = _mod_bzrdir.BzrDir.open_containing('.')[0]
43
from bzrlib.workingtree import WorkingTree
44
# Open the containing directory
45
wt = WorkingTree.open_containing('.')[0]
56
48
# Passed in locations should be exact
57
bzrdir = _mod_bzrdir.BzrDir.open(location)
58
branch = bzrdir.open_branch()
59
repo = branch.repository
60
branch_config = branch.get_config()
49
from bzrlib.branch import Branch
50
b = Branch.open(location)
51
repo = getattr(b, 'repository', b)
53
config = bzrlib.config.BranchConfig(b)
62
55
if committer is None:
63
committer = branch_config.username()
64
gpg_strategy = gpg.GPGStrategy(branch_config)
56
committer = config.username()
58
gpg_strategy = bzrlib.gpg.GPGStrategy(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
89
repo.sign_revision(rev_id, gpg_strategy)
91
repo.abort_write_group()
94
repo.commit_write_group()
63
# return in partial topological order for the sake of reproducibility
64
for rev_id in repo.all_revision_ids():
65
if repo.has_signature_for_revision_id(rev_id):
68
rev = repo.get_revision(rev_id)
69
if rev.committer != committer:
72
# We have a revision without a signature who has a
73
# matching committer, start signing
77
repo.sign_revision(rev_id, gpg_strategy)
97
80
print 'Signed %d revisions' % (count,)
100
class cmd_verify_signatures(Command):
101
__doc__ = """Verify all commit signatures.
103
Verifies that all commits in the branch are signed by known GnuPG keys.
107
Option('acceptable-keys',
108
help='Comma separated list of GPG key patterns which are'
109
' acceptable for verification.',
115
takes_args = ['location?']
117
def run(self, acceptable_keys=None, revision=None, verbose=None,
119
bzrdir = _mod_bzrdir.BzrDir.open_containing(location)[0]
120
branch = bzrdir.open_branch()
121
repo = branch.repository
122
branch_config = branch.get_config()
123
gpg_strategy = gpg.GPGStrategy(branch_config)
125
gpg_strategy.set_acceptable_keys(acceptable_keys)
128
self.outf.write(string + "\n")
129
def write_verbose(string):
130
self.outf.write(" " + string + "\n")
132
#get our list of revisions
134
if revision is not None:
135
if len(revision) == 1:
136
revno, rev_id = revision[0].in_history(branch)
137
revisions.append(rev_id)
138
elif len(revision) == 2:
139
from_revno, from_revid = revision[0].in_history(branch)
140
to_revno, to_revid = revision[1].in_history(branch)
142
to_revno = branch.revno()
143
if from_revno is None or to_revno is None:
144
raise errors.BzrCommandError(gettext(
145
'Cannot verify a range of non-revision-history revisions'))
146
for revno in range(from_revno, to_revno + 1):
147
revisions.append(branch.get_rev_id(revno))
149
#all revisions by default including merges
150
graph = repo.get_graph()
153
for rev_id, parents in graph.iter_ancestry(
154
[branch.last_revision()]):
155
if _mod_revision.is_null(rev_id):
160
revisions.append(rev_id)
162
count, result, all_verifiable =\
163
gpg_strategy.do_verifications(revisions, repo)
166
"All commits signed with verifiable keys"))
168
write(gpg_strategy.verbose_valid_message(result))
171
write(gpg_strategy.valid_commits_message(count))
173
for message in gpg_strategy.verbose_valid_message(result):
174
write_verbose(message)
175
write(gpg_strategy.expired_commit_message(count))
177
for message in gpg_strategy.verbose_expired_key_message(result,
179
write_verbose(message)
180
write(gpg_strategy.unknown_key_message(count))
182
for message in gpg_strategy.verbose_missing_key_message(result):
183
write_verbose(message)
184
write(gpg_strategy.commit_not_valid_message(count))
186
for message in gpg_strategy.verbose_not_valid_message(result,
188
write_verbose(message)
189
write(gpg_strategy.commit_not_signed_message(count))
191
for message in gpg_strategy.verbose_not_signed_message(result,
193
write_verbose(message)