44
def create_deterministic_revid(revid, new_parents):
45
"""Create a new deterministic revision id with specified new parents.
58
def create_upgraded_revid(revid, mapping_suffix, upgrade_suffix="-upgrade"):
59
"""Create a new revision id for an upgraded version of a revision.
61
47
Prevents suffix to be appended needlessly.
63
49
:param revid: Original revision id.
64
50
:return: New revision id
66
if revid.endswith(upgrade_suffix):
67
return revid[0:revid.rfind("-svn")] + mapping_suffix + upgrade_suffix
69
return revid + mapping_suffix + upgrade_suffix
72
def determine_fileid_renames(old_tree, new_tree):
73
for old_file_id in old_tree:
74
new_file_id = new_tree.path2id(old_tree.id2path(old_file_id))
75
if old_file_id == new_file_id:
77
if new_file_id is not None:
78
yield new_tree.id2path(new_file_id), old_file_id, new_file_id
81
def upgrade_workingtree(wt, foreign_repository, new_mapping, mapping_registry,
82
allow_changes=False, verbose=False):
83
"""Upgrade a working tree.
85
:param foreign_repository: Foreign repository object
89
old_revid = wt.last_revision()
90
revid_renames = upgrade_branch(wt.branch, foreign_repository, new_mapping=new_mapping,
91
mapping_registry=mapping_registry,
92
allow_changes=allow_changes, verbose=verbose)
93
last_revid = wt.branch.last_revision()
94
if old_revid == last_revid:
97
fileid_renames = dict([(path, (old_fileid, new_fileid)) for (path, old_fileid, new_fileid) in determine_fileid_renames(wt.branch.repository.revision_tree(old_revid), wt.branch.repository.revision_tree(last_revid))])
101
# Adjust file ids in working tree
102
for path in sorted(fileid_renames.keys(), reverse=True):
104
old_fileids.append(fileid_renames[path][0])
105
new_fileids.append((path, fileid_renames[path][1]))
107
new_root_id = fileid_renames[path][1]
108
new_fileids.reverse()
109
wt.unversion(old_fileids)
110
if new_root_id is not None:
111
wt.set_root_id(new_root_id)
112
wt.add([x[0] for x in new_fileids], [x[1] for x in new_fileids])
113
wt.set_last_revision(last_revid)
120
def upgrade_tags(tags, repository, foreign_repository, new_mapping, mapping_registry,
121
allow_changes=False, verbose=False, branch_renames=None):
52
if "-rebase-" in revid:
53
revid = revid[0:revid.rfind("-rebase-")]
54
return revid + "-rebase-" + osutils.sha_string(":".join(new_parents))[:8]
57
def upgrade_tags(tags, repository, generate_rebase_map, determine_new_revid,
58
allow_changes=False, verbose=False, branch_renames=None,
59
branch_ancestry=None):
122
60
"""Upgrade a tags dictionary."""
62
if branch_renames is not None:
63
renames.update(branch_renames)
123
64
pb = ui.ui_factory.nested_progress_bar()
125
66
tags_dict = tags.get_tag_dict()
126
for i, (name, revid) in enumerate(tags_dict.items()):
67
for i, (name, revid) in enumerate(tags_dict.iteritems()):
127
68
pb.update("upgrading tags", i, len(tags_dict))
128
if branch_renames is not None and revid in branch_renames:
129
renames = branch_renames
131
renames = upgrade_repository(repository, foreign_repository,
132
revision_id=revid, new_mapping=new_mapping,
133
mapping_registry=mapping_registry,
134
allow_changes=allow_changes, verbose=verbose)
69
if revid not in renames:
71
repository.lock_read()
72
revid_exists = repository.has_revision(revid)
76
renames.update(upgrade_repository(
78
generate_rebase_map, determine_new_revid,
79
revision_id=revid, allow_changes=allow_changes,
81
if (revid in renames and
82
(branch_ancestry is None or revid not in branch_ancestry)):
136
83
tags.set_tag(name, renames[revid])
141
def upgrade_branch(branch, foreign_repository, new_mapping,
142
mapping_registry, allow_changes=False, verbose=False):
88
def upgrade_branch(branch, generate_rebase_map, determine_new_revid,
89
allow_changes=False, verbose=False):
143
90
"""Upgrade a branch to the current mapping version.
145
92
:param branch: Branch to upgrade.
146
93
:param foreign_repository: Repository to fetch new revisions from
147
94
:param allow_changes: Allow changes in mappings.
148
95
:param verbose: Whether to print verbose list of rewrites
150
97
revid = branch.last_revision()
151
renames = upgrade_repository(branch.repository, foreign_repository,
152
revision_id=revid, new_mapping=new_mapping,
153
mapping_registry=mapping_registry,
154
allow_changes=allow_changes, verbose=verbose)
155
upgrade_tags(branch.tags, branch.repository, foreign_repository,
156
new_mapping=new_mapping, mapping_registry=mapping_registry,
157
allow_changes=allow_changes, verbose=verbose)
98
renames = upgrade_repository(
99
branch.repository, generate_rebase_map,
100
determine_new_revid, revision_id=revid,
101
allow_changes=allow_changes, verbose=verbose)
159
103
branch.generate_revision_history(renames[revid])
104
ancestry = branch.repository.get_ancestry(
105
branch.last_revision(), topo_sorted=False)
107
branch.tags, branch.repository, generate_rebase_map,
108
determine_new_revid, allow_changes=allow_changes, verbose=verbose,
109
branch_renames=renames, branch_ancestry=ancestry)
163
113
def check_revision_changed(oldrev, newrev):
164
"""Check if two revisions are different. This is exactly the same
114
"""Check if two revisions are different. This is exactly the same
165
115
as Revision.equals() except that it does not check the revision_id."""
166
116
if (newrev.inventory_sha1 != oldrev.inventory_sha1 or
167
newrev.timestamp != oldrev.timestamp or
168
newrev.message != oldrev.message or
169
newrev.timezone != oldrev.timezone or
170
newrev.committer != oldrev.committer or
171
newrev.properties != oldrev.properties):
117
newrev.timestamp != oldrev.timestamp or
118
newrev.message != oldrev.message or
119
newrev.timezone != oldrev.timezone or
120
newrev.committer != oldrev.committer or
121
newrev.properties != oldrev.properties):
172
122
raise UpgradeChangesContent(oldrev.revision_id)
175
def generate_upgrade_map(new_mapping, revs, mapping_registry):
176
"""Generate an upgrade map for use by bzr-rebase.
178
:param new_mapping: Mapping to upgrade revisions to.
179
:param revs: Iterator over revisions to upgrade.
180
:return: Map from old revids as keys, new revids as values stored in a
184
# Create a list of revisions that can be renamed during the upgrade
186
assert isinstance(revid, str)
188
(foreign_revid, _) = mapping_registry.parse_revision_id(revid)
189
except InvalidRevisionId:
190
# Not a foreign revision, nothing to do
192
newrevid = new_mapping.revision_id_foreign_to_bzr(foreign_revid)
193
if revid == newrevid:
195
rename_map[revid] = newrevid
199
MIN_REBASE_VERSION = (0, 4)
201
def create_upgrade_plan(repository, foreign_repository, new_mapping,
202
mapping_registry, revision_id=None, allow_changes=False):
125
def create_upgrade_plan(repository, generate_rebase_map, determine_new_revid,
126
revision_id=None, allow_changes=False):
203
127
"""Generate a rebase plan for upgrading revisions.
205
129
:param repository: Repository to do upgrade in
206
:param foreign_repository: Subversion repository to fetch new revisions from.
130
:param foreign_repository: Subversion repository to fetch new revisions
207
132
:param new_mapping: New mapping to use.
208
:param revision_id: Revision to upgrade (None for all revisions in
133
:param revision_id: Revision to upgrade (None for all revisions in
210
135
:param allow_changes: Whether an upgrade is allowed to change the contents
212
137
:return: Tuple with a rebase plan and map of renamed revisions.
214
from bzrlib.plugins.rebase.rebase import generate_transpose_plan
215
check_rebase_version(MIN_REBASE_VERSION)
217
140
graph = repository.get_graph()
218
if revision_id is None:
219
potential = repository.all_revision_ids()
221
potential = itertools.imap(lambda (rev, parents): rev,
222
graph.iter_ancestry([revision_id]))
223
upgrade_map = generate_upgrade_map(new_mapping, potential, mapping_registry)
225
# Make sure all the required current version revisions are present
226
for revid in upgrade_map.values():
227
if not repository.has_revision(revid):
228
repository.fetch(foreign_repository, revid)
141
upgrade_map = generate_rebase_map(revision_id)
230
143
if not allow_changes:
231
144
for oldrevid, newrevid in upgrade_map.iteritems():
234
147
check_revision_changed(oldrev, newrev)
236
149
if revision_id is None:
237
heads = repository.all_revision_ids()
150
heads = repository.all_revision_ids()
239
152
heads = [revision_id]
241
plan = generate_transpose_plan(graph.iter_ancestry(heads), upgrade_map,
242
graph, lambda revid: create_upgraded_revid(revid, new_mapping.upgrade_suffix))
243
def remove_parents((oldrevid, (newrevid, parents))):
154
plan = generate_transpose_plan(
155
graph.iter_ancestry(heads), upgrade_map, graph, determine_new_revid)
156
def remove_parents(entry):
157
(oldrevid, (newrevid, parents)) = entry
244
158
return (oldrevid, newrevid)
245
159
upgrade_map.update(dict(map(remove_parents, plan.iteritems())))
247
161
return (plan, upgrade_map)
250
def upgrade_repository(repository, foreign_repository, new_mapping,
251
mapping_registry, revision_id=None, allow_changes=False,
164
def upgrade_repository(repository, generate_rebase_map,
165
determine_new_revid, revision_id=None,
166
allow_changes=False, verbose=False):
253
167
"""Upgrade the revisions in repository until the specified stop revision.
255
169
:param repository: Repository in which to upgrade.
256
170
:param foreign_repository: Repository to fetch new revisions from.
257
171
:param new_mapping: New mapping.
258
:param revision_id: Revision id up until which to upgrade, or None for
172
:param revision_id: Revision id up until which to upgrade, or None for
260
174
:param allow_changes: Allow changes to mappings.
261
175
:param verbose: Whether to print list of rewrites
262
176
:return: Dictionary of mapped revisions
264
check_rebase_version(MIN_REBASE_VERSION)
265
from bzrlib.plugins.rebase.rebase import (
266
replay_snapshot, rebase, rebase_todo)
268
178
# Find revisions that need to be upgraded, create
269
179
# dictionary with revision ids in key, new parents in value
271
repository.lock_write()
272
foreign_repository.lock_read()
273
(plan, revid_renames) = create_upgrade_plan(repository, foreign_repository,
274
new_mapping, mapping_registry,
275
revision_id=revision_id,
276
allow_changes=allow_changes)
180
with repository.lock_write():
181
(plan, revid_renames) = create_upgrade_plan(
182
repository, generate_rebase_map, determine_new_revid,
183
revision_id=revision_id, allow_changes=allow_changes)
278
185
for revid in rebase_todo(repository, plan):
279
info("%s -> %s" % (revid, plan[revid][0]))
280
def fix_revid(revid):
282
(foreign_revid, mapping) = mapping_registry.parse_revision_id(revid)
283
except InvalidRevisionId:
285
return new_mapping.revision_id_foreign_to_bzr(foreign_revid)
286
def replay(repository, oldrevid, newrevid, new_parents):
287
return replay_snapshot(repository, oldrevid, newrevid, new_parents,
288
revid_renames, fix_revid)
289
rebase(repository, plan, replay)
186
trace.note("%s -> %s" % (revid, plan[revid][0]))
187
rebase(repository, plan, CommitBuilderRevisionRewriter(repository))
290
188
return revid_renames
293
foreign_repository.unlock()