69
76
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,
79
def determine_fileid_renames(old_inv, new_inv):
80
"""Determine the file ids based on a old and a new inventory that
83
:param old_inv: Old inventory
84
:param new_inv: New inventory
85
:return: Dictionary a (old_id, new_id) tuple for each path in the
89
if len(old_inv) != len(new_inv):
90
raise AssertionError("Inventories are not of the same size")
91
for old_file_id in old_inv:
92
new_file_id = new_inv.path2id(old_inv.id2path(old_file_id))
93
if new_file_id is None:
95
"Unable to find %s in new inventory" % old_file_id)
96
ret[new_inv.id2path(new_file_id)] = (old_file_id, new_file_id)
100
def update_workinginv_fileids(wt, old_inv, new_inv):
101
"""Update all file ids in wt according to old_tree/new_tree.
103
old_tree and new_tree should be two RevisionTree's that differ only
106
fileid_renames = determine_fileid_renames(old_inv, new_inv)
110
# Adjust file ids in working tree
111
# Sorted, so we process parents before children
112
for path in sorted(fileid_renames.keys()):
114
old_fileids.append(fileid_renames[path][0])
115
new_fileids.append((path, fileid_renames[path][1]))
117
new_root_id = fileid_renames[path][1]
118
new_fileids.reverse()
119
wt.unversion(old_fileids)
120
if new_root_id is not None:
121
wt.set_root_id(new_root_id)
122
wt.add([x[0] for x in new_fileids], [x[1] for x in new_fileids])
123
wt.set_last_revision(new_inv.revision_id)
126
def upgrade_workingtree(wt, foreign_repository, new_mapping,
82
127
allow_changes=False, verbose=False):
83
128
"""Upgrade a working tree.
89
134
old_revid = wt.last_revision()
90
135
revid_renames = upgrade_branch(wt.branch, foreign_repository, new_mapping=new_mapping,
91
mapping_registry=mapping_registry,
92
136
allow_changes=allow_changes, verbose=verbose)
93
137
last_revid = wt.branch.last_revision()
94
138
if old_revid == last_revid:
95
139
return revid_renames
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)
140
old_inv = wt.branch.repository.get_inventory(old_revid)
141
new_inv = wt.branch.repository.get_inventory(last_revid)
142
update_workinginv_fileids(wt, old_inv, new_inv)
117
146
return revid_renames
120
def upgrade_tags(tags, repository, foreign_repository, new_mapping, mapping_registry,
121
allow_changes=False, verbose=False, branch_renames=None):
149
def upgrade_tags(tags, repository, foreign_repository, new_mapping,
150
allow_changes=False, verbose=False, branch_renames=None,
151
branch_ancestry=None):
122
152
"""Upgrade a tags dictionary."""
154
if branch_renames is not None:
155
renames.update(branch_renames)
123
156
pb = ui.ui_factory.nested_progress_bar()
125
158
tags_dict = tags.get_tag_dict()
126
159
for i, (name, revid) in enumerate(tags_dict.items()):
127
160
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,
161
if not revid in renames:
162
renames.update(upgrade_repository(repository, foreign_repository,
132
163
revision_id=revid, new_mapping=new_mapping,
133
mapping_registry=mapping_registry,
134
allow_changes=allow_changes, verbose=verbose)
164
allow_changes=allow_changes, verbose=verbose))
165
if revid in renames and (branch_ancestry is None or not revid in branch_ancestry):
136
166
tags.set_tag(name, renames[revid])
141
171
def upgrade_branch(branch, foreign_repository, new_mapping,
142
mapping_registry, allow_changes=False, verbose=False):
172
allow_changes=False, verbose=False):
143
173
"""Upgrade a branch to the current mapping version.
145
175
:param branch: Branch to upgrade.
150
180
revid = branch.last_revision()
151
181
renames = upgrade_repository(branch.repository, foreign_repository,
152
182
revision_id=revid, new_mapping=new_mapping,
153
mapping_registry=mapping_registry,
154
183
allow_changes=allow_changes, verbose=verbose)
185
branch.generate_revision_history(renames[revid])
186
ancestry = branch.repository.get_ancestry(branch.last_revision(), topo_sorted=False)
155
187
upgrade_tags(branch.tags, branch.repository, foreign_repository,
156
new_mapping=new_mapping, mapping_registry=mapping_registry,
157
allow_changes=allow_changes, verbose=verbose)
159
branch.generate_revision_history(renames[revid])
188
new_mapping=new_mapping,
189
allow_changes=allow_changes, verbose=verbose, branch_renames=renames,
190
branch_ancestry=ancestry)
172
203
raise UpgradeChangesContent(oldrev.revision_id)
175
def generate_upgrade_map(new_mapping, revs, mapping_registry):
206
def generate_upgrade_map(revs, vcs, determine_upgraded_revid):
176
207
"""Generate an upgrade map for use by bzr-rebase.
178
209
:param new_mapping: Mapping to upgrade revisions to.
210
:param vcs: The foreign vcs
179
211
:param revs: Iterator over revisions to upgrade.
180
212
:return: Map from old revids as keys, new revids as values stored in a
185
217
for revid in revs:
186
218
assert isinstance(revid, str)
188
(foreign_revid, _) = mapping_registry.parse_revision_id(revid)
220
(foreign_revid, old_mapping) = vcs.mapping_registry.parse_revision_id(revid)
189
221
except InvalidRevisionId:
190
222
# Not a foreign revision, nothing to do
192
newrevid = new_mapping.revision_id_foreign_to_bzr(foreign_revid)
193
if revid == newrevid:
224
newrevid = determine_upgraded_revid(foreign_revid)
225
if newrevid in (revid, None):
195
227
rename_map[revid] = newrevid
197
228
return rename_map
199
MIN_REBASE_VERSION = (0, 4)
230
MIN_REBASE_VERSION = (0, 4, 3)
201
232
def create_upgrade_plan(repository, foreign_repository, new_mapping,
202
mapping_registry, revision_id=None, allow_changes=False):
233
revision_id=None, allow_changes=False):
203
234
"""Generate a rebase plan for upgrading revisions.
205
236
:param repository: Repository to do upgrade in
221
252
potential = itertools.imap(lambda (rev, parents): rev,
222
253
graph.iter_ancestry([revision_id]))
223
upgrade_map = generate_upgrade_map(new_mapping, potential, mapping_registry)
255
def determine_upgraded_revid(foreign_revid):
256
# FIXME: Try all mappings until new_mapping rather than just new_mapping
257
new_revid = foreign_repository.upgrade_foreign_revision_id(foreign_revid, new_mapping)
258
if new_revid is None:
260
# Make sure the revision is there
261
if not repository.has_revision(new_revid):
263
repository.fetch(foreign_repository, new_revid)
264
except NoSuchRevision:
266
if not repository.has_revision(new_revid):
270
upgrade_map = generate_upgrade_map(potential, foreign_repository.vcs,
271
determine_upgraded_revid)
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)
230
273
if not allow_changes:
231
274
for oldrevid, newrevid in upgrade_map.iteritems():
232
275
oldrev = repository.get_revision(oldrevid)
239
282
heads = [revision_id]
284
def determine_new_revid(old_revid):
285
# If this revision id already exists round-tripped upstream,
287
if foreign_repository.has_revision(old_revid):
289
# if not, return old_revid'
290
return create_upgraded_revid(old_revid, new_mapping.upgrade_suffix)
241
292
plan = generate_transpose_plan(graph.iter_ancestry(heads), upgrade_map,
242
graph, lambda revid: create_upgraded_revid(revid, new_mapping.upgrade_suffix))
293
graph, determine_new_revid)
243
294
def remove_parents((oldrevid, (newrevid, parents))):
244
295
return (oldrevid, newrevid)
245
296
upgrade_map.update(dict(map(remove_parents, plan.iteritems())))
271
322
repository.lock_write()
272
323
foreign_repository.lock_read()
273
324
(plan, revid_renames) = create_upgrade_plan(repository, foreign_repository,
274
new_mapping, mapping_registry,
275
326
revision_id=revision_id,
276
327
allow_changes=allow_changes)
278
329
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)
330
trace.info("%s -> %s" % (revid, plan[revid][0]))
331
rebase(repository, plan, replay_snapshot)
290
332
return revid_renames
292
334
repository.unlock()