1
# Copyright (C) 2006 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
This is an attempt to take the internal delta object, and represent
18
it as a single-file text-only changeset.
19
This should have commands for both generating a changeset,
20
and for applying a changeset.
25
from bzrlib.lazy_import import lazy_import
26
lazy_import(globals(), """
30
revision as _mod_revision,
36
from bzrlib.commands import Command
37
from bzrlib.option import Option
38
from bzrlib.trace import note
41
class cmd_bundle_revisions(Command):
42
"""Generate a revision bundle.
44
This bundle contains all of the meta-information of a
45
diff, rather than just containing the patch information.
47
You can apply it to another tree using 'bzr merge'.
50
- Generate a bundle relative to a remembered location
52
bzr bundle-revisions BASE
53
- Bundle to apply the current tree into BASE
55
bzr bundle-revisions --revision A
56
- Bundle to apply revision A to remembered location
58
bzr bundle-revisions --revision A..B
59
- Bundle to transform A into B
61
takes_options = ['revision', 'remember',
62
Option("output", help="write bundle to specified file",
64
takes_args = ['base?']
66
encoding_type = 'exact'
68
def run(self, base=None, revision=None, output=None, remember=False):
69
from bzrlib import user_encoding
70
from bzrlib.bundle.serializer import write_bundle
72
target_branch = branch.Branch.open_containing(u'.')[0]
73
target_branch.lock_write()
74
locked = [target_branch]
78
base_specified = False
83
target_revision = target_branch.last_revision()
84
elif len(revision) < 3:
85
target_revision = revision[-1].in_history(target_branch).rev_id
86
if len(revision) == 2:
88
raise errors.BzrCommandError(
89
'Cannot specify base as well as two revision'
91
revspec = revision[0].in_history(target_branch)
92
base_revision = revspec.rev_id
94
raise errors.BzrCommandError('--revision takes 1 or 2 '
97
if revision is None or len(revision) < 2:
98
submit_branch = target_branch.get_submit_branch()
102
base = target_branch.get_parent()
104
raise errors.BzrCommandError("No base branch known or"
106
elif not base_specified:
108
# note() doesn't pay attention to terminal_encoding() so
109
# we must format with 'ascii' to be safe
110
note('Using saved location: %s',
111
urlutils.unescape_for_display(base, 'ascii'))
112
base_branch = branch.Branch.open(base)
113
base_branch.lock_read()
114
locked.append(base_branch)
115
if submit_branch is None or remember:
117
target_branch.set_submit_branch(base_branch.base)
119
raise errors.BzrCommandError(
120
'--remember requires a branch to be specified.')
121
target_branch.repository.fetch(base_branch.repository,
122
base_branch.last_revision())
123
graph = target_branch.repository.get_graph()
124
base_revision = graph.find_unique_lca(
125
_mod_revision.ensure_null(base_branch.last_revision()),
126
_mod_revision.ensure_null(target_revision))
128
if output is not None:
129
fileobj = file(output, 'wb')
132
write_bundle(target_branch.repository, target_revision,
133
base_revision, fileobj)
135
for item in reversed(locked):
139
class cmd_bundle_info(Command):
140
"""Output interesting stats about a bundle"""
143
takes_args = ['location']
144
takes_options = [Option('verbose', help="output decoded contents",
146
encoding_type = 'exact'
148
def run(self, location, verbose=False):
149
from bzrlib.bundle.serializer import read_bundle
150
from bzrlib import osutils
151
term_encoding = osutils.get_terminal_encoding()
152
dirname, basename = urlutils.split(location)
153
bundle_file = transport.get_transport(dirname).get(basename)
154
bundle_info = read_bundle(bundle_file)
155
reader_method = getattr(bundle_info, 'get_bundle_reader', None)
156
if reader_method is None:
157
raise errors.BzrCommandError('Bundle format not supported')
161
for bytes, parents, repo_kind, revision_id, file_id\
162
in reader_method().iter_records():
163
by_kind.setdefault(repo_kind, []).append(
164
(bytes, parents, repo_kind, revision_id, file_id))
165
if file_id is not None:
166
file_ids.add(file_id)
167
print >> self.outf, 'Records'
168
for kind, records in sorted(by_kind.iteritems()):
169
multiparent = sum(1 for b, p, k, r, f in records if len(p) > 1)
170
print >> self.outf, '%s: %d (%d multiparent)' % \
171
(kind, len(records), multiparent)
172
print >> self.outf, 'unique files: %d' % len(file_ids)
176
for revision in bundle_info.real_revisions:
177
if 'branch-nick' in revision.properties:
178
nicks.add(revision.properties['branch-nick'])
179
committers.add(revision.committer)
181
print >> self.outf, 'Revisions'
182
print >> self.outf, ('nicks: %s'
183
% ', '.join(sorted(nicks))).encode(term_encoding, 'replace')
184
print >> self.outf, ('committers: \n%s' %
185
'\n'.join(sorted(committers)).encode(term_encoding, 'replace'))
190
line = bundle_file.readline()
192
if line.rstrip('\n') == '# End of patch':
194
content = bundle_file.read().decode('base-64').decode('bz2')
195
print >> self.outf, "Decoded contents"
196
self.outf.write(content)