bzr branch
http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
|
0.64.128
by Ian Clatworthy
fix encoding issue in bzr_exporter (Teemu Likonen) |
1 |
# -*- coding: utf-8 -*-
|
2 |
||
|
0.79.1
by Ian Clatworthy
turn bzr-fast-export into a fast-export command |
3 |
# Copyright (C) 2008 Canonical Ltd
|
4 |
#
|
|
5 |
# This program is free software; you can redistribute it and/or modify
|
|
6 |
# it under the terms of the GNU General Public License as published by
|
|
7 |
# the Free Software Foundation; either version 2 of the License, or
|
|
8 |
# (at your option) any later version.
|
|
9 |
#
|
|
10 |
# This program is distributed in the hope that it will be useful,
|
|
11 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13 |
# GNU General Public License for more details.
|
|
14 |
#
|
|
15 |
# You should have received a copy of the GNU General Public License
|
|
16 |
# along with this program; if not, write to the Free Software
|
|
17 |
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
18 |
#
|
|
|
0.79.10
by Ian Clatworthy
documentation clean-ups |
19 |
# Original Copyright (c) 2008 Adeodato Simó
|
20 |
# Original License: MIT (See exporters/bzr-fast-export.LICENSE)
|
|
21 |
#
|
|
|
0.64.57
by Ian Clatworthy
integrate dato's bzr-fast-export |
22 |
# vim: fileencoding=utf-8
|
|
0.79.1
by Ian Clatworthy
turn bzr-fast-export into a fast-export command |
23 |
|
24 |
"""Core engine for the fast-export command."""
|
|
|
0.64.57
by Ian Clatworthy
integrate dato's bzr-fast-export |
25 |
|
|
0.79.7
by Ian Clatworthy
trivial bzr_exporter clean-ups |
26 |
# TODO: if a new_git_branch below gets merged repeatedly, the tip of the branch
|
|
0.64.57
by Ian Clatworthy
integrate dato's bzr-fast-export |
27 |
# is not updated (because the parent of commit is already merged, so we don't
|
28 |
# set new_git_branch to the previously used name)
|
|
29 |
||
|
0.79.6
by Ian Clatworthy
refactor bzr_exporter to use Command objects |
30 |
from email.Utils import parseaddr |
|
0.64.173
by Ian Clatworthy
add -r option to fast-export |
31 |
import sys, time |
|
0.64.57
by Ian Clatworthy
integrate dato's bzr-fast-export |
32 |
|
33 |
import bzrlib.branch |
|
34 |
import bzrlib.revision |
|
|
0.64.176
by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export |
35 |
from bzrlib import ( |
36 |
builtins, |
|
37 |
errors as bazErrors, |
|
|
0.64.237
by Ian Clatworthy
implicitly rename children on export when directory renamed |
38 |
osutils, |
|
0.64.176
by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export |
39 |
progress, |
40 |
trace, |
|
41 |
)
|
|
|
0.79.4
by Ian Clatworthy
use note and warning APIs |
42 |
|
|
0.123.8
by Jelmer Vernooij
Use modes for FileModifyCommand. |
43 |
from bzrlib.plugins.fastimport import helpers, marks_file |
|
0.79.2
by Ian Clatworthy
extend & use marks_file API |
44 |
|
|
0.123.8
by Jelmer Vernooij
Use modes for FileModifyCommand. |
45 |
from fastimport import commands |
|
0.64.282
by Jelmer Vernooij
Fix output stream to stdout for bzr fast-export. |
46 |
from fastimport.helpers import binary_stream |
47 |
||
48 |
||
49 |
def _get_output_stream(destination): |
|
50 |
if destination is None or destination == '-': |
|
51 |
return binary_stream(sys.stdout) |
|
52 |
elif destination.endswith('gz'): |
|
53 |
import gzip |
|
54 |
return gzip.open(destination, 'wb') |
|
55 |
else: |
|
56 |
return open(destination, 'wb') |
|
57 |
||
|
0.64.57
by Ian Clatworthy
integrate dato's bzr-fast-export |
58 |
|
|
0.79.1
by Ian Clatworthy
turn bzr-fast-export into a fast-export command |
59 |
class BzrFastExporter(object): |
|
0.68.1
by Pieter de Bie
Classify bzr-fast-export |
60 |
|
|
0.64.222
by Ian Clatworthy
Support an explicit output destination for bzr fast-export |
61 |
def __init__(self, source, destination, git_branch=None, checkpoint=-1, |
|
0.64.176
by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export |
62 |
import_marks_file=None, export_marks_file=None, revision=None, |
|
0.102.3
by Ian Clatworthy
First cut at exporting additional metadata via 'features' |
63 |
verbose=False, plain_format=False): |
64 |
"""Export branch data in fast import format. |
|
65 |
||
66 |
:param plain_format: if True, 'classic' fast-import format is
|
|
67 |
used without any extended features; if False, the generated
|
|
68 |
data is richer and includes information like multiple
|
|
69 |
authors, revision properties, etc.
|
|
70 |
"""
|
|
|
0.79.1
by Ian Clatworthy
turn bzr-fast-export into a fast-export command |
71 |
self.source = source |
|
0.64.282
by Jelmer Vernooij
Fix output stream to stdout for bzr fast-export. |
72 |
self.outf = _get_output_stream(destination) |
|
0.79.1
by Ian Clatworthy
turn bzr-fast-export into a fast-export command |
73 |
self.git_branch = git_branch |
74 |
self.checkpoint = checkpoint |
|
75 |
self.import_marks_file = import_marks_file |
|
76 |
self.export_marks_file = export_marks_file |
|
|
0.64.173
by Ian Clatworthy
add -r option to fast-export |
77 |
self.revision = revision |
78 |
self.excluded_revisions = set() |
|
|
0.102.3
by Ian Clatworthy
First cut at exporting additional metadata via 'features' |
79 |
self.plain_format = plain_format |
|
0.64.176
by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export |
80 |
self._multi_author_api_available = hasattr(bzrlib.revision.Revision, |
81 |
'get_apparent_authors') |
|
|
0.102.3
by Ian Clatworthy
First cut at exporting additional metadata via 'features' |
82 |
self.properties_to_exclude = ['authors', 'author'] |
|
0.64.176
by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export |
83 |
|
84 |
# Progress reporting stuff
|
|
85 |
self.verbose = verbose |
|
86 |
if verbose: |
|
87 |
self.progress_every = 100 |
|
88 |
else: |
|
89 |
self.progress_every = 1000 |
|
90 |
self._start_time = time.time() |
|
|
0.64.230
by Ian Clatworthy
Fix ghost handling and improve progress tracking in fast-export |
91 |
self._commit_total = 0 |
|
0.64.176
by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export |
92 |
|
93 |
# Load the marks and initialise things accordingly
|
|
|
0.68.1
by Pieter de Bie
Classify bzr-fast-export |
94 |
self.revid_to_mark = {} |
95 |
self.branch_names = {} |
|
|
0.79.1
by Ian Clatworthy
turn bzr-fast-export into a fast-export command |
96 |
if self.import_marks_file: |
|
0.79.2
by Ian Clatworthy
extend & use marks_file API |
97 |
marks_info = marks_file.import_marks(self.import_marks_file) |
98 |
if marks_info is not None: |
|
|
0.64.134
by Ian Clatworthy
fix marks importing in fast-export |
99 |
self.revid_to_mark = dict((r, m) for m, r in |
100 |
marks_info[0].items()) |
|
|
0.79.2
by Ian Clatworthy
extend & use marks_file API |
101 |
self.branch_names = marks_info[1] |
|
0.64.173
by Ian Clatworthy
add -r option to fast-export |
102 |
|
103 |
def interesting_history(self): |
|
104 |
if self.revision: |
|
|
0.64.176
by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export |
105 |
rev1, rev2 = builtins._get_revision_range(self.revision, |
106 |
self.branch, "fast-export") |
|
|
0.64.173
by Ian Clatworthy
add -r option to fast-export |
107 |
start_rev_id = rev1.rev_id |
108 |
end_rev_id = rev2.rev_id |
|
109 |
else: |
|
110 |
start_rev_id = None |
|
111 |
end_rev_id = None |
|
|
0.64.176
by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export |
112 |
self.note("Calculating the revisions to include ...") |
|
0.100.1
by Ian Clatworthy
Stop fast-export from exceeding the maximum recursion depth |
113 |
view_revisions = reversed([rev_id for rev_id, _, _, _ in |
114 |
self.branch.iter_merge_sorted_revisions(end_rev_id, start_rev_id)]) |
|
|
0.64.173
by Ian Clatworthy
add -r option to fast-export |
115 |
# If a starting point was given, we need to later check that we don't
|
116 |
# start emitting revisions from before that point. Collect the
|
|
117 |
# revisions to exclude now ...
|
|
118 |
if start_rev_id is not None: |
|
|
0.64.176
by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export |
119 |
self.note("Calculating the revisions to exclude ...") |
|
0.100.1
by Ian Clatworthy
Stop fast-export from exceeding the maximum recursion depth |
120 |
self.excluded_revisions = set([rev_id for rev_id, _, _, _ in |
121 |
self.branch.iter_merge_sorted_revisions(start_rev_id)]) |
|
|
0.64.230
by Ian Clatworthy
Fix ghost handling and improve progress tracking in fast-export |
122 |
return list(view_revisions) |
|
0.64.173
by Ian Clatworthy
add -r option to fast-export |
123 |
|
|
0.79.1
by Ian Clatworthy
turn bzr-fast-export into a fast-export command |
124 |
def run(self): |
125 |
# Open the source
|
|
126 |
self.branch = bzrlib.branch.Branch.open_containing(self.source)[0] |
|
127 |
||
128 |
# Export the data
|
|
|
0.68.1
by Pieter de Bie
Classify bzr-fast-export |
129 |
self.branch.repository.lock_read() |
130 |
try: |
|
|
0.100.1
by Ian Clatworthy
Stop fast-export from exceeding the maximum recursion depth |
131 |
interesting = self.interesting_history() |
|
0.102.15
by Ian Clatworthy
add revision count to 'Starting export ...' message |
132 |
self._commit_total = len(interesting) |
133 |
self.note("Starting export of %d revisions ..." % |
|
134 |
self._commit_total) |
|
|
0.102.3
by Ian Clatworthy
First cut at exporting additional metadata via 'features' |
135 |
if not self.plain_format: |
136 |
self.emit_features() |
|
|
0.100.1
by Ian Clatworthy
Stop fast-export from exceeding the maximum recursion depth |
137 |
for revid in interesting: |
|
0.79.1
by Ian Clatworthy
turn bzr-fast-export into a fast-export command |
138 |
self.emit_commit(revid, self.git_branch) |
139 |
if self.branch.supports_tags(): |
|
140 |
self.emit_tags() |
|
|
0.68.1
by Pieter de Bie
Classify bzr-fast-export |
141 |
finally: |
142 |
self.branch.repository.unlock() |
|
143 |
||
|
0.79.1
by Ian Clatworthy
turn bzr-fast-export into a fast-export command |
144 |
# Save the marks if requested
|
|
0.79.2
by Ian Clatworthy
extend & use marks_file API |
145 |
self._save_marks() |
|
0.64.176
by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export |
146 |
self.dump_stats() |
147 |
||
148 |
def note(self, msg, *args): |
|
149 |
"""Output a note but timestamp it.""" |
|
150 |
msg = "%s %s" % (self._time_of_day(), msg) |
|
151 |
trace.note(msg, *args) |
|
152 |
||
153 |
def warning(self, msg, *args): |
|
154 |
"""Output a warning but timestamp it.""" |
|
155 |
msg = "%s WARNING: %s" % (self._time_of_day(), msg) |
|
156 |
trace.warning(msg, *args) |
|
157 |
||
158 |
def _time_of_day(self): |
|
159 |
"""Time of day as a string.""" |
|
160 |
# Note: this is a separate method so tests can patch in a fixed value
|
|
161 |
return time.strftime("%H:%M:%S") |
|
162 |
||
163 |
def report_progress(self, commit_count, details=''): |
|
164 |
if commit_count and commit_count % self.progress_every == 0: |
|
|
0.64.230
by Ian Clatworthy
Fix ghost handling and improve progress tracking in fast-export |
165 |
if self._commit_total: |
166 |
counts = "%d/%d" % (commit_count, self._commit_total) |
|
167 |
else: |
|
168 |
counts = "%d" % (commit_count,) |
|
|
0.64.176
by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export |
169 |
minutes = (time.time() - self._start_time) / 60 |
170 |
rate = commit_count * 1.0 / minutes |
|
171 |
if rate > 10: |
|
172 |
rate_str = "at %.0f/minute " % rate |
|
173 |
else: |
|
174 |
rate_str = "at %.1f/minute " % rate |
|
175 |
self.note("%s commits exported %s%s" % (counts, rate_str, details)) |
|
176 |
||
177 |
def dump_stats(self): |
|
178 |
time_required = progress.str_tdelta(time.time() - self._start_time) |
|
179 |
rc = len(self.revid_to_mark) |
|
180 |
self.note("Exported %d %s in %s", |
|
181 |
rc, helpers.single_plural(rc, "revision", "revisions"), |
|
182 |
time_required) |
|
|
0.79.2
by Ian Clatworthy
extend & use marks_file API |
183 |
|
|
0.79.6
by Ian Clatworthy
refactor bzr_exporter to use Command objects |
184 |
def print_cmd(self, cmd): |
185 |
self.outf.write("%r\n" % cmd) |
|
186 |
||
|
0.79.2
by Ian Clatworthy
extend & use marks_file API |
187 |
def _save_marks(self): |
188 |
if self.export_marks_file: |
|
|
0.64.134
by Ian Clatworthy
fix marks importing in fast-export |
189 |
revision_ids = dict((m, r) for r, m in self.revid_to_mark.items()) |
|
0.79.2
by Ian Clatworthy
extend & use marks_file API |
190 |
marks_file.export_marks(self.export_marks_file, revision_ids, |
191 |
self.branch_names) |
|
|
0.79.6
by Ian Clatworthy
refactor bzr_exporter to use Command objects |
192 |
|
|
0.68.10
by Pieter de Bie
bzr-fast-export: Don't rename empty directories |
193 |
def is_empty_dir(self, tree, path): |
194 |
path_id = tree.path2id(path) |
|
|
0.100.1
by Ian Clatworthy
Stop fast-export from exceeding the maximum recursion depth |
195 |
if path_id is None: |
|
0.64.176
by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export |
196 |
self.warning("Skipping empty_dir detection - no file_id for %s" % |
197 |
(path,)) |
|
|
0.68.10
by Pieter de Bie
bzr-fast-export: Don't rename empty directories |
198 |
return False |
199 |
||
200 |
# Continue if path is not a directory
|
|
201 |
if tree.kind(path_id) != 'directory': |
|
202 |
return False |
|
203 |
||
204 |
# Use treewalk to find the contents of our directory
|
|
205 |
contents = list(tree.walkdirs(prefix=path))[0] |
|
206 |
if len(contents[1]) == 0: |
|
207 |
return True |
|
208 |
else: |
|
209 |
return False |
|
210 |
||
|
0.102.3
by Ian Clatworthy
First cut at exporting additional metadata via 'features' |
211 |
def emit_features(self): |
|
0.102.5
by Ian Clatworthy
Define feature names in one place |
212 |
for feature in sorted(commands.FEATURE_NAMES): |
213 |
self.print_cmd(commands.FeatureCommand(feature)) |
|
|
0.102.3
by Ian Clatworthy
First cut at exporting additional metadata via 'features' |
214 |
|
|
0.68.1
by Pieter de Bie
Classify bzr-fast-export |
215 |
def emit_commit(self, revid, git_branch): |
|
0.64.173
by Ian Clatworthy
add -r option to fast-export |
216 |
if revid in self.revid_to_mark or revid in self.excluded_revisions: |
|
0.68.4
by Pieter de Bie
bzr-fast-export.py: Add support for ghost commits |
217 |
return
|
218 |
||
|
0.79.6
by Ian Clatworthy
refactor bzr_exporter to use Command objects |
219 |
# Get the Revision object
|
|
0.68.4
by Pieter de Bie
bzr-fast-export.py: Add support for ghost commits |
220 |
try: |
221 |
revobj = self.branch.repository.get_revision(revid) |
|
222 |
except bazErrors.NoSuchRevision: |
|
223 |
# This is a ghost revision. Mark it as not found and next!
|
|
224 |
self.revid_to_mark[revid] = -1 |
|
225 |
return
|
|
|
0.64.82
by Ian Clatworthy
Merge Pieter de Bie's export-fixes branch |
226 |
|
|
0.79.6
by Ian Clatworthy
refactor bzr_exporter to use Command objects |
227 |
# Get the primary parent
|
|
0.100.1
by Ian Clatworthy
Stop fast-export from exceeding the maximum recursion depth |
228 |
# TODO: Consider the excluded revisions when deciding the parents.
|
229 |
# Currently, a commit with parents that are excluded ought to be
|
|
230 |
# triggering the git_branch calculation below (and it is not).
|
|
231 |
# IGC 20090824
|
|
|
0.64.176
by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export |
232 |
ncommits = len(self.revid_to_mark) |
|
0.100.1
by Ian Clatworthy
Stop fast-export from exceeding the maximum recursion depth |
233 |
nparents = len(revobj.parent_ids) |
|
0.68.4
by Pieter de Bie
bzr-fast-export.py: Add support for ghost commits |
234 |
if nparents == 0: |
|
0.79.9
by Ian Clatworthy
fix branch of first commit to not be refs/heads/tmp |
235 |
if ncommits: |
236 |
# This is a parentless commit but it's not the first one
|
|
237 |
# output. We need to create a new temporary branch for it
|
|
238 |
# otherwise git-fast-import will assume the previous commit
|
|
239 |
# was this one's parent
|
|
240 |
git_branch = self._next_tmp_branch_name() |
|
|
0.68.4
by Pieter de Bie
bzr-fast-export.py: Add support for ghost commits |
241 |
parent = bzrlib.revision.NULL_REVISION |
242 |
else: |
|
243 |
parent = revobj.parent_ids[0] |
|
244 |
||
|
0.79.6
by Ian Clatworthy
refactor bzr_exporter to use Command objects |
245 |
# Print the commit
|
246 |
git_ref = 'refs/heads/%s' % (git_branch,) |
|
|
0.98.1
by Gonéri Le Bouder
add the missing ":" since revid_to_mark are "committish" |
247 |
mark = ncommits + 1 |
|
0.64.221
by Ian Clatworthy
backout git-bzr fix as it was breaking fast-export |
248 |
self.revid_to_mark[revid] = mark |
|
0.79.6
by Ian Clatworthy
refactor bzr_exporter to use Command objects |
249 |
file_cmds = self._get_filecommands(parent, revid) |
250 |
self.print_cmd(self._get_commit_command(git_ref, mark, revobj, |
|
251 |
file_cmds)) |
|
252 |
||
|
0.64.176
by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export |
253 |
# Report progress and checkpoint if it's time for that
|
254 |
self.report_progress(ncommits) |
|
255 |
if (self.checkpoint > 0 and ncommits |
|
256 |
and ncommits % self.checkpoint == 0): |
|
257 |
self.note("Exported %i commits - adding checkpoint to output" |
|
258 |
% ncommits) |
|
259 |
self._save_marks() |
|
260 |
self.print_cmd(commands.CheckpointCommand()) |
|
261 |
||
|
0.102.16
by Ian Clatworthy
tweak author formatting to use same smart rule as used for committer |
262 |
def _get_name_email(self, user): |
263 |
if user.find('<') == -1: |
|
|
0.64.177
by Ian Clatworthy
fix round-tripping of committer & author when name is an email |
264 |
# If the email isn't inside <>, we need to use it as the name
|
265 |
# in order for things to round-trip correctly.
|
|
266 |
# (note: parseaddr('a@b.com') => name:'', email: 'a@b.com')
|
|
|
0.102.16
by Ian Clatworthy
tweak author formatting to use same smart rule as used for committer |
267 |
name = user |
|
0.64.177
by Ian Clatworthy
fix round-tripping of committer & author when name is an email |
268 |
email = '' |
269 |
else: |
|
|
0.102.16
by Ian Clatworthy
tweak author formatting to use same smart rule as used for committer |
270 |
name, email = parseaddr(user) |
271 |
return name, email |
|
272 |
||
273 |
def _get_commit_command(self, git_ref, mark, revobj, file_cmds): |
|
274 |
# Get the committer and author info
|
|
275 |
committer = revobj.committer |
|
276 |
name, email = self._get_name_email(committer) |
|
|
0.79.6
by Ian Clatworthy
refactor bzr_exporter to use Command objects |
277 |
committer_info = (name, email, revobj.timestamp, revobj.timezone) |
|
0.64.176
by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export |
278 |
if self._multi_author_api_available: |
|
0.102.3
by Ian Clatworthy
First cut at exporting additional metadata via 'features' |
279 |
more_authors = revobj.get_apparent_authors() |
280 |
author = more_authors.pop(0) |
|
|
0.64.176
by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export |
281 |
else: |
|
0.102.3
by Ian Clatworthy
First cut at exporting additional metadata via 'features' |
282 |
more_authors = [] |
|
0.64.176
by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export |
283 |
author = revobj.get_apparent_author() |
|
0.102.3
by Ian Clatworthy
First cut at exporting additional metadata via 'features' |
284 |
if more_authors: |
|
0.102.16
by Ian Clatworthy
tweak author formatting to use same smart rule as used for committer |
285 |
name, email = self._get_name_email(author) |
|
0.102.3
by Ian Clatworthy
First cut at exporting additional metadata via 'features' |
286 |
author_info = (name, email, revobj.timestamp, revobj.timezone) |
287 |
more_author_info = [] |
|
288 |
for a in more_authors: |
|
|
0.102.16
by Ian Clatworthy
tweak author formatting to use same smart rule as used for committer |
289 |
name, email = self._get_name_email(a) |
|
0.102.3
by Ian Clatworthy
First cut at exporting additional metadata via 'features' |
290 |
more_author_info.append( |
291 |
(name, email, revobj.timestamp, revobj.timezone)) |
|
292 |
elif author != committer: |
|
|
0.102.16
by Ian Clatworthy
tweak author formatting to use same smart rule as used for committer |
293 |
name, email = self._get_name_email(author) |
|
0.102.3
by Ian Clatworthy
First cut at exporting additional metadata via 'features' |
294 |
author_info = (name, email, revobj.timestamp, revobj.timezone) |
295 |
more_author_info = None |
|
|
0.79.6
by Ian Clatworthy
refactor bzr_exporter to use Command objects |
296 |
else: |
297 |
author_info = None |
|
|
0.102.3
by Ian Clatworthy
First cut at exporting additional metadata via 'features' |
298 |
more_author_info = None |
|
0.79.6
by Ian Clatworthy
refactor bzr_exporter to use Command objects |
299 |
|
300 |
# Get the parents in terms of marks
|
|
301 |
non_ghost_parents = [] |
|
|
0.68.4
by Pieter de Bie
bzr-fast-export.py: Add support for ghost commits |
302 |
for p in revobj.parent_ids: |
|
0.64.173
by Ian Clatworthy
add -r option to fast-export |
303 |
if p in self.excluded_revisions: |
304 |
continue
|
|
|
0.64.230
by Ian Clatworthy
Fix ghost handling and improve progress tracking in fast-export |
305 |
try: |
306 |
parent_mark = self.revid_to_mark[p] |
|
|
0.79.6
by Ian Clatworthy
refactor bzr_exporter to use Command objects |
307 |
non_ghost_parents.append(":%s" % parent_mark) |
|
0.64.230
by Ian Clatworthy
Fix ghost handling and improve progress tracking in fast-export |
308 |
except KeyError: |
309 |
# ghost - ignore
|
|
310 |
continue
|
|
|
0.79.6
by Ian Clatworthy
refactor bzr_exporter to use Command objects |
311 |
if non_ghost_parents: |
312 |
from_ = non_ghost_parents[0] |
|
313 |
merges = non_ghost_parents[1:] |
|
314 |
else: |
|
315 |
from_ = None |
|
316 |
merges = None |
|
317 |
||
|
0.102.3
by Ian Clatworthy
First cut at exporting additional metadata via 'features' |
318 |
# Filter the revision properties. Some metadata (like the
|
319 |
# author information) is already exposed in other ways so
|
|
320 |
# don't repeat it here.
|
|
321 |
if self.plain_format: |
|
322 |
properties = None |
|
323 |
else: |
|
324 |
properties = revobj.properties |
|
325 |
for prop in self.properties_to_exclude: |
|
326 |
try: |
|
327 |
del properties[prop] |
|
328 |
except KeyError: |
|
329 |
pass
|
|
330 |
||
|
0.79.6
by Ian Clatworthy
refactor bzr_exporter to use Command objects |
331 |
# Build and return the result
|
332 |
return commands.CommitCommand(git_ref, mark, author_info, |
|
|
0.102.3
by Ian Clatworthy
First cut at exporting additional metadata via 'features' |
333 |
committer_info, revobj.message, from_, merges, iter(file_cmds), |
334 |
more_authors=more_author_info, properties=properties) |
|
|
0.79.6
by Ian Clatworthy
refactor bzr_exporter to use Command objects |
335 |
|
336 |
def _get_revision_trees(self, parent, revision_id): |
|
|
0.68.6
by Pieter de Bie
bzr-fast-export.py: Skip over broken commits. |
337 |
try: |
338 |
tree_old = self.branch.repository.revision_tree(parent) |
|
339 |
except bazErrors.UnexpectedInventoryFormat: |
|
|
0.79.6
by Ian Clatworthy
refactor bzr_exporter to use Command objects |
340 |
self.warning("Parent is malformed - diffing against previous parent") |
|
0.68.6
by Pieter de Bie
bzr-fast-export.py: Skip over broken commits. |
341 |
# We can't find the old parent. Let's diff against his parent
|
342 |
pp = self.branch.repository.get_revision(parent) |
|
343 |
tree_old = self.branch.repository.revision_tree(pp.parent_ids[0]) |
|
344 |
tree_new = None |
|
345 |
try: |
|
|
0.79.6
by Ian Clatworthy
refactor bzr_exporter to use Command objects |
346 |
tree_new = self.branch.repository.revision_tree(revision_id) |
|
0.68.6
by Pieter de Bie
bzr-fast-export.py: Skip over broken commits. |
347 |
except bazErrors.UnexpectedInventoryFormat: |
348 |
# We can't really do anything anymore
|
|
|
0.87.1
by David Reitter
fix bug #348038 (call to warning() with two arguments) and handle malformed revisions gracefully by not generating any output |
349 |
self.warning("Revision %s is malformed - skipping" % revision_id) |
|
0.79.6
by Ian Clatworthy
refactor bzr_exporter to use Command objects |
350 |
return tree_old, tree_new |
|
0.68.1
by Pieter de Bie
Classify bzr-fast-export |
351 |
|
|
0.79.6
by Ian Clatworthy
refactor bzr_exporter to use Command objects |
352 |
def _get_filecommands(self, parent, revision_id): |
353 |
"""Get the list of FileCommands for the changes between two revisions.""" |
|
354 |
tree_old, tree_new = self._get_revision_trees(parent, revision_id) |
|
|
0.64.166
by Ian Clatworthy
graceful handling of faulty revisions (David Reitter) |
355 |
if not(tree_old and tree_new): |
356 |
# Something is wrong with this revision - ignore the filecommands
|
|
|
0.87.1
by David Reitter
fix bug #348038 (call to warning() with two arguments) and handle malformed revisions gracefully by not generating any output |
357 |
return [] |
|
0.68.1
by Pieter de Bie
Classify bzr-fast-export |
358 |
|
|
0.64.166
by Ian Clatworthy
graceful handling of faulty revisions (David Reitter) |
359 |
changes = tree_new.changes_from(tree_old) |
360 |
||
361 |
# Make "modified" have 3-tuples, as added does
|
|
362 |
my_modified = [ x[0:3] for x in changes.modified ] |
|
363 |
||
|
0.64.178
by Ian Clatworthy
improve fast-export's handling of rename+delete combinations |
364 |
# The potential interaction between renames and deletes is messy.
|
365 |
# Handle it here ...
|
|
366 |
file_cmds, rd_modifies, renamed = self._process_renames_and_deletes( |
|
367 |
changes.renamed, changes.removed, revision_id, tree_old) |
|
|
0.64.166
by Ian Clatworthy
graceful handling of faulty revisions (David Reitter) |
368 |
|
369 |
# Map kind changes to a delete followed by an add
|
|
370 |
for path, id_, kind1, kind2 in changes.kind_changed: |
|
|
0.64.176
by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export |
371 |
path = self._adjust_path_for_renames(path, renamed, revision_id) |
|
0.64.174
by Ian Clatworthy
fix rename adjustment & kind change logic in fast-export |
372 |
# IGC: I don't understand why a delete is needed here.
|
373 |
# In fact, it seems harmful? If you uncomment this line,
|
|
374 |
# please file a bug explaining why you needed to.
|
|
375 |
#file_cmds.append(commands.FileDeleteCommand(path))
|
|
|
0.64.166
by Ian Clatworthy
graceful handling of faulty revisions (David Reitter) |
376 |
my_modified.append((path, id_, kind2)) |
377 |
||
378 |
# Record modifications
|
|
|
0.64.178
by Ian Clatworthy
improve fast-export's handling of rename+delete combinations |
379 |
for path, id_, kind in changes.added + my_modified + rd_modifies: |
|
0.64.166
by Ian Clatworthy
graceful handling of faulty revisions (David Reitter) |
380 |
if kind == 'file': |
381 |
text = tree_new.get_file_text(id_) |
|
|
0.123.8
by Jelmer Vernooij
Use modes for FileModifyCommand. |
382 |
file_cmds.append(commands.FileModifyCommand(path, |
383 |
helpers.kind_to_mode('file', tree_new.is_executable(id_)), |
|
384 |
None, text)) |
|
|
0.64.166
by Ian Clatworthy
graceful handling of faulty revisions (David Reitter) |
385 |
elif kind == 'symlink': |
|
0.123.8
by Jelmer Vernooij
Use modes for FileModifyCommand. |
386 |
file_cmds.append(commands.FileModifyCommand(path, |
387 |
helpers.kind_to_mode('symlink', False), |
|
388 |
None, tree_new.get_symlink_target(id_))) |
|
|
0.102.14
by Ian Clatworthy
export and import empty directories |
389 |
elif kind == 'directory': |
|
0.105.1
by John Whitley
Don't emit directory info when plain format is specified. |
390 |
if not self.plain_format: |
|
0.123.8
by Jelmer Vernooij
Use modes for FileModifyCommand. |
391 |
file_cmds.append(commands.FileModifyCommand(path, |
392 |
helpers.kind_to_mode('directory', False), |
|
393 |
None, None)) |
|
|
0.64.166
by Ian Clatworthy
graceful handling of faulty revisions (David Reitter) |
394 |
else: |
|
0.102.14
by Ian Clatworthy
export and import empty directories |
395 |
self.warning("cannot export '%s' of kind %s yet - ignoring" % |
396 |
(path, kind)) |
|
|
0.64.166
by Ian Clatworthy
graceful handling of faulty revisions (David Reitter) |
397 |
return file_cmds |
398 |
||
|
0.64.178
by Ian Clatworthy
improve fast-export's handling of rename+delete combinations |
399 |
def _process_renames_and_deletes(self, renames, deletes, |
400 |
revision_id, tree_old): |
|
401 |
file_cmds = [] |
|
402 |
modifies = [] |
|
403 |
renamed = [] |
|
404 |
||
405 |
# See https://bugs.edge.launchpad.net/bzr-fastimport/+bug/268933.
|
|
406 |
# In a nutshell, there are several nasty cases:
|
|
407 |
#
|
|
408 |
# 1) bzr rm a; bzr mv b a; bzr commit
|
|
409 |
# 2) bzr mv x/y z; bzr rm x; commmit
|
|
410 |
#
|
|
411 |
# The first must come out with the delete first like this:
|
|
412 |
#
|
|
413 |
# D a
|
|
414 |
# R b a
|
|
415 |
#
|
|
416 |
# The second case must come out with the rename first like this:
|
|
417 |
#
|
|
418 |
# R x/y z
|
|
419 |
# D x
|
|
420 |
#
|
|
421 |
# So outputting all deletes first or all renames first won't work.
|
|
422 |
# Instead, we need to make multiple passes over the various lists to
|
|
423 |
# get the ordering right.
|
|
424 |
||
|
0.64.237
by Ian Clatworthy
implicitly rename children on export when directory renamed |
425 |
must_be_renamed = {} |
426 |
old_to_new = {} |
|
|
0.64.178
by Ian Clatworthy
improve fast-export's handling of rename+delete combinations |
427 |
deleted_paths = set([p for p, _, _ in deletes]) |
428 |
for (oldpath, newpath, id_, kind, |
|
429 |
text_modified, meta_modified) in renames: |
|
|
0.106.2
by Harry Hirsch
Don't emit directory info for renames operations when using plain format |
430 |
emit = kind != 'directory' or not self.plain_format |
|
0.64.178
by Ian Clatworthy
improve fast-export's handling of rename+delete combinations |
431 |
if newpath in deleted_paths: |
|
0.106.2
by Harry Hirsch
Don't emit directory info for renames operations when using plain format |
432 |
if emit: |
433 |
file_cmds.append(commands.FileDeleteCommand(newpath)) |
|
|
0.64.178
by Ian Clatworthy
improve fast-export's handling of rename+delete combinations |
434 |
deleted_paths.remove(newpath) |
435 |
if (self.is_empty_dir(tree_old, oldpath)): |
|
436 |
self.note("Skipping empty dir %s in rev %s" % (oldpath, |
|
437 |
revision_id)) |
|
438 |
continue
|
|
439 |
#oldpath = self._adjust_path_for_renames(oldpath, renamed,
|
|
440 |
# revision_id)
|
|
441 |
renamed.append([oldpath, newpath]) |
|
|
0.64.237
by Ian Clatworthy
implicitly rename children on export when directory renamed |
442 |
old_to_new[oldpath] = newpath |
|
0.106.2
by Harry Hirsch
Don't emit directory info for renames operations when using plain format |
443 |
if emit: |
444 |
file_cmds.append(commands.FileRenameCommand(oldpath, newpath)) |
|
|
0.64.178
by Ian Clatworthy
improve fast-export's handling of rename+delete combinations |
445 |
if text_modified or meta_modified: |
446 |
modifies.append((newpath, id_, kind)) |
|
447 |
||
|
0.64.237
by Ian Clatworthy
implicitly rename children on export when directory renamed |
448 |
# Renaming a directory implies all children must be renamed.
|
449 |
# Note: changes_from() doesn't handle this
|
|
450 |
if kind == 'directory': |
|
451 |
for p, e in tree_old.inventory.iter_entries_by_dir(from_dir=id_): |
|
|
0.106.2
by Harry Hirsch
Don't emit directory info for renames operations when using plain format |
452 |
if e.kind == 'directory' and self.plain_format: |
453 |
continue
|
|
|
0.64.237
by Ian Clatworthy
implicitly rename children on export when directory renamed |
454 |
old_child_path = osutils.pathjoin(oldpath, p) |
455 |
new_child_path = osutils.pathjoin(newpath, p) |
|
456 |
must_be_renamed[old_child_path] = new_child_path |
|
457 |
||
458 |
# Add children not already renamed
|
|
459 |
if must_be_renamed: |
|
460 |
renamed_already = set(old_to_new.keys()) |
|
461 |
still_to_be_renamed = set(must_be_renamed.keys()) - renamed_already |
|
462 |
for old_child_path in sorted(still_to_be_renamed): |
|
463 |
new_child_path = must_be_renamed[old_child_path] |
|
464 |
if self.verbose: |
|
465 |
self.note("implicitly renaming %s => %s" % (old_child_path, |
|
466 |
new_child_path)) |
|
467 |
file_cmds.append(commands.FileRenameCommand(old_child_path, |
|
468 |
new_child_path)) |
|
469 |
||
|
0.64.178
by Ian Clatworthy
improve fast-export's handling of rename+delete combinations |
470 |
# Record remaining deletes
|
471 |
for path, id_, kind in deletes: |
|
472 |
if path not in deleted_paths: |
|
473 |
continue
|
|
|
0.106.2
by Harry Hirsch
Don't emit directory info for renames operations when using plain format |
474 |
if kind == 'directory' and self.plain_format: |
475 |
continue
|
|
|
0.64.178
by Ian Clatworthy
improve fast-export's handling of rename+delete combinations |
476 |
#path = self._adjust_path_for_renames(path, renamed, revision_id)
|
477 |
file_cmds.append(commands.FileDeleteCommand(path)) |
|
478 |
return file_cmds, modifies, renamed |
|
479 |
||
|
0.64.176
by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export |
480 |
def _adjust_path_for_renames(self, path, renamed, revision_id): |
|
0.64.174
by Ian Clatworthy
fix rename adjustment & kind change logic in fast-export |
481 |
# If a previous rename is found, we should adjust the path
|
482 |
for old, new in renamed: |
|
483 |
if path == old: |
|
|
0.64.176
by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export |
484 |
self.note("Changing path %s given rename to %s in revision %s" |
485 |
% (path, new, revision_id)) |
|
|
0.64.174
by Ian Clatworthy
fix rename adjustment & kind change logic in fast-export |
486 |
path = new |
487 |
elif path.startswith(old + '/'): |
|
|
0.64.176
by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export |
488 |
self.note( |
489 |
"Adjusting path %s given rename of %s to %s in revision %s" |
|
490 |
% (path, old, new, revision_id)) |
|
|
0.64.174
by Ian Clatworthy
fix rename adjustment & kind change logic in fast-export |
491 |
path = path.replace(old + "/", new + "/") |
492 |
return path |
|
493 |
||
|
0.68.1
by Pieter de Bie
Classify bzr-fast-export |
494 |
def emit_tags(self): |
495 |
for tag, revid in self.branch.tags.get_tag_dict().items(): |
|
496 |
try: |
|
497 |
mark = self.revid_to_mark[revid] |
|
498 |
except KeyError: |
|
|
0.79.4
by Ian Clatworthy
use note and warning APIs |
499 |
self.warning('not creating tag %r pointing to non-existent ' |
500 |
'revision %s' % (tag, revid)) |
|
|
0.68.1
by Pieter de Bie
Classify bzr-fast-export |
501 |
else: |
|
0.79.6
by Ian Clatworthy
refactor bzr_exporter to use Command objects |
502 |
git_ref = 'refs/tags/%s' % tag |
|
0.64.133
by Ian Clatworthy
Fix str + int concat in bzr-fast-export (Stéphane Raimbault) |
503 |
self.print_cmd(commands.ResetCommand(git_ref, ":" + str(mark))) |
|
0.68.1
by Pieter de Bie
Classify bzr-fast-export |
504 |
|
|
0.79.9
by Ian Clatworthy
fix branch of first commit to not be refs/heads/tmp |
505 |
def _next_tmp_branch_name(self): |
|
0.79.6
by Ian Clatworthy
refactor bzr_exporter to use Command objects |
506 |
"""Return a unique branch name. The name will start with "tmp".""" |
|
0.64.57
by Ian Clatworthy
integrate dato's bzr-fast-export |
507 |
prefix = 'tmp' |
|
0.68.1
by Pieter de Bie
Classify bzr-fast-export |
508 |
if prefix not in self.branch_names: |
509 |
self.branch_names[prefix] = 0 |
|
510 |
else: |
|
511 |
self.branch_names[prefix] += 1 |
|
512 |
prefix = '%s.%d' % (prefix, self.branch_names[prefix]) |
|
513 |
return prefix |