74
70
return revid + mapping_suffix + upgrade_suffix
77
def determine_fileid_renames(old_inv, new_inv):
78
"""Determine the file ids based on a old and a new inventory that
81
:param old_inv: Old inventory
82
:param new_inv: New inventory
83
:return: Dictionary a (old_id, new_id) tuple for each path in the
87
if len(old_inv) != len(new_inv):
88
raise AssertionError("Inventories are not of the same size")
89
for old_file_id in old_inv:
90
new_file_id = new_inv.path2id(old_inv.id2path(old_file_id))
91
if new_file_id is None:
93
"Unable to find %s in new inventory" % old_file_id)
94
ret[new_inv.id2path(new_file_id)] = (old_file_id, new_file_id)
98
def update_workinginv_fileids(wt, old_inv, new_inv):
99
"""Update all file ids in wt according to old_tree/new_tree.
101
old_tree and new_tree should be two RevisionTree's that differ only
104
fileid_renames = determine_fileid_renames(old_inv, new_inv)
108
# Adjust file ids in working tree
109
# Sorted, so we process parents before children
110
for path in sorted(fileid_renames.keys()):
112
old_fileids.append(fileid_renames[path][0])
113
new_fileids.append((path, fileid_renames[path][1]))
115
new_root_id = fileid_renames[path][1]
116
new_fileids.reverse()
117
wt.unversion(old_fileids)
118
if new_root_id is not None:
119
wt.set_root_id(new_root_id)
120
wt.add([x[0] for x in new_fileids], [x[1] for x in new_fileids])
121
wt.set_last_revision(new_inv.revision_id)
124
def upgrade_workingtree(wt, foreign_repository, new_mapping,
73
def determine_fileid_renames(old_tree, new_tree):
74
for old_file_id in old_tree:
75
new_file_id = new_tree.path2id(old_tree.id2path(old_file_id))
76
if old_file_id == new_file_id:
78
if new_file_id is not None:
79
yield new_tree.id2path(new_file_id), old_file_id, new_file_id
82
def upgrade_workingtree(wt, foreign_repository, new_mapping, mapping_registry,
125
83
allow_changes=False, verbose=False):
126
84
"""Upgrade a working tree.
132
90
old_revid = wt.last_revision()
133
91
revid_renames = upgrade_branch(wt.branch, foreign_repository, new_mapping=new_mapping,
92
mapping_registry=mapping_registry,
134
93
allow_changes=allow_changes, verbose=verbose)
135
94
last_revid = wt.branch.last_revision()
136
95
if old_revid == last_revid:
137
96
return revid_renames
138
old_inv = wt.branch.repository.get_inventory(old_revid)
139
new_inv = wt.branch.repository.get_inventory(last_revid)
140
update_workinginv_fileids(wt, old_inv, new_inv)
98
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))])
102
# Adjust file ids in working tree
103
for path in sorted(fileid_renames.keys(), reverse=True):
105
old_fileids.append(fileid_renames[path][0])
106
new_fileids.append((path, fileid_renames[path][1]))
108
new_root_id = fileid_renames[path][1]
109
new_fileids.reverse()
110
wt.unversion(old_fileids)
111
if new_root_id is not None:
112
wt.set_root_id(new_root_id)
113
wt.add([x[0] for x in new_fileids], [x[1] for x in new_fileids])
114
wt.set_last_revision(last_revid)
144
118
return revid_renames
147
def upgrade_tags(tags, repository, foreign_repository, new_mapping,
121
def upgrade_tags(tags, repository, foreign_repository, new_mapping, mapping_registry,
148
122
allow_changes=False, verbose=False, branch_renames=None):
149
123
"""Upgrade a tags dictionary."""
151
if branch_renames is not None:
152
renames.update(branch_renames)
153
124
pb = ui.ui_factory.nested_progress_bar()
155
126
tags_dict = tags.get_tag_dict()
156
127
for i, (name, revid) in enumerate(tags_dict.items()):
157
128
pb.update("upgrading tags", i, len(tags_dict))
158
if not revid in renames:
159
renames.update(upgrade_repository(repository, foreign_repository,
129
if branch_renames is not None and revid in branch_renames:
130
renames = branch_renames
132
renames = upgrade_repository(repository, foreign_repository,
160
133
revision_id=revid, new_mapping=new_mapping,
161
allow_changes=allow_changes, verbose=verbose))
134
mapping_registry=mapping_registry,
135
allow_changes=allow_changes, verbose=verbose)
162
136
if revid in renames:
163
137
tags.set_tag(name, renames[revid])
177
151
revid = branch.last_revision()
178
152
renames = upgrade_repository(branch.repository, foreign_repository,
179
153
revision_id=revid, new_mapping=new_mapping,
154
mapping_registry=mapping_registry,
180
155
allow_changes=allow_changes, verbose=verbose)
181
156
upgrade_tags(branch.tags, branch.repository, foreign_repository,
182
new_mapping=new_mapping,
183
allow_changes=allow_changes, verbose=verbose, branch_renames=renames)
157
new_mapping=new_mapping, mapping_registry=mapping_registry,
158
allow_changes=allow_changes, verbose=verbose)
185
160
branch.generate_revision_history(renames[revid])
198
173
raise UpgradeChangesContent(oldrev.revision_id)
201
def generate_upgrade_map(revs, vcs, determine_upgraded_revid):
176
def generate_upgrade_map(new_mapping, revs, mapping_registry):
202
177
"""Generate an upgrade map for use by bzr-rebase.
204
179
:param new_mapping: Mapping to upgrade revisions to.
205
:param vcs: The foreign vcs
206
180
:param revs: Iterator over revisions to upgrade.
207
181
:return: Map from old revids as keys, new revids as values stored in a
212
186
for revid in revs:
213
187
assert isinstance(revid, str)
215
(foreign_revid, old_mapping) = vcs.mapping_registry.parse_revision_id(revid)
189
(foreign_revid, _) = mapping_registry.parse_revision_id(revid)
216
190
except InvalidRevisionId:
217
191
# Not a foreign revision, nothing to do
219
newrevid = determine_upgraded_revid(foreign_revid)
220
if newrevid in (revid, None):
193
newrevid = new_mapping.revision_id_foreign_to_bzr(foreign_revid)
194
if revid == newrevid:
222
196
rename_map[revid] = newrevid
223
198
return rename_map
225
MIN_REBASE_VERSION = (0, 4, 3)
200
MIN_REBASE_VERSION = (0, 4)
227
202
def create_upgrade_plan(repository, foreign_repository, new_mapping,
228
revision_id=None, allow_changes=False):
203
mapping_registry, revision_id=None, allow_changes=False):
229
204
"""Generate a rebase plan for upgrading revisions.
231
206
:param repository: Repository to do upgrade in
247
222
potential = itertools.imap(lambda (rev, parents): rev,
248
223
graph.iter_ancestry([revision_id]))
250
def determine_upgraded_revid(foreign_revid):
251
# FIXME: Try all mappings until new_mapping rather than just new_mapping
252
new_revid = foreign_repository.upgrade_foreign_revision_id(foreign_revid, new_mapping)
253
if new_revid is None:
255
# Make sure the revision is there
256
if not repository.has_revision(new_revid):
258
repository.fetch(foreign_repository, new_revid)
259
except NoSuchRevision:
261
if not repository.has_revision(new_revid):
265
upgrade_map = generate_upgrade_map(potential, foreign_repository.vcs,
266
determine_upgraded_revid)
224
upgrade_map = generate_upgrade_map(new_mapping, potential, mapping_registry)
226
# Make sure all the required current version revisions are present
227
for revid in upgrade_map.values():
228
if not repository.has_revision(revid):
229
repository.fetch(foreign_repository, revid)
268
231
if not allow_changes:
269
for oldrevid, newrevid in upgrade_map.iteritems():
232
for oldrevid, newrevid in upgrade_map.items():
270
233
oldrev = repository.get_revision(oldrevid)
271
234
newrev = repository.get_revision(newrevid)
272
235
check_revision_changed(oldrev, newrev)
277
240
heads = [revision_id]
279
def determine_new_revid(old_revid):
280
# If this revision id already exists round-tripped upstream,
282
if foreign_repository.has_revision(old_revid):
284
# if not, return old_revid'
285
return create_upgraded_revid(old_revid, new_mapping.upgrade_suffix)
287
242
plan = generate_transpose_plan(graph.iter_ancestry(heads), upgrade_map,
288
graph, determine_new_revid)
243
graph, lambda revid: create_upgraded_revid(revid, new_mapping.upgrade_suffix))
289
244
def remove_parents((oldrevid, (newrevid, parents))):
290
245
return (oldrevid, newrevid)
291
upgrade_map.update(dict(map(remove_parents, plan.iteritems())))
246
upgrade_map.update(dict(map(remove_parents, plan.items())))
293
248
return (plan, upgrade_map)
296
251
def upgrade_repository(repository, foreign_repository, new_mapping,
297
revision_id=None, allow_changes=False,
252
mapping_registry, revision_id=None, allow_changes=False,
299
254
"""Upgrade the revisions in repository until the specified stop revision.
317
272
repository.lock_write()
318
273
foreign_repository.lock_read()
319
274
(plan, revid_renames) = create_upgrade_plan(repository, foreign_repository,
275
new_mapping, mapping_registry,
321
276
revision_id=revision_id,
322
277
allow_changes=allow_changes)
324
279
for revid in rebase_todo(repository, plan):
325
280
info("%s -> %s" % (revid, plan[revid][0]))
326
rebase(repository, plan, replay_snapshot)
281
def fix_revid(revid):
283
(foreign_revid, mapping) = mapping_registry.parse_revision_id(revid)
284
except InvalidRevisionId:
286
return new_mapping.revision_id_foreign_to_bzr(foreign_revid)
287
def replay(repository, oldrevid, newrevid, new_parents):
288
return replay_snapshot(repository, oldrevid, newrevid, new_parents,
289
revid_renames, fix_revid)
290
rebase(repository, plan, replay)
327
291
return revid_renames
329
293
repository.unlock()