46
def create_deterministic_revid(revid, new_parents):
47
"""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
49
Prevents suffix to be appended needlessly.
63
51
:param revid: Original revision id.
64
52
: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):
54
if "-rebase-" in revid:
55
revid = revid[0:revid.rfind("-rebase-")]
56
return revid + "-rebase-" + osutils.sha_string(":".join(new_parents))[:8]
59
def upgrade_tags(tags, repository, generate_rebase_map, determine_new_revid,
60
allow_changes=False, verbose=False, branch_renames=None,
61
branch_ancestry=None):
122
62
"""Upgrade a tags dictionary."""
64
if branch_renames is not None:
65
renames.update(branch_renames)
123
66
pb = ui.ui_factory.nested_progress_bar()
125
68
tags_dict = tags.get_tag_dict()
126
for i, (name, revid) in enumerate(tags_dict.items()):
69
for i, (name, revid) in enumerate(tags_dict.iteritems()):
127
70
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)
71
if revid not in renames:
73
repository.lock_read()
74
revid_exists = repository.has_revision(revid)
78
renames.update(upgrade_repository(
80
generate_rebase_map, determine_new_revid,
81
revision_id=revid, allow_changes=allow_changes,
83
if (revid in renames and
84
(branch_ancestry is None or revid not in branch_ancestry)):
136
85
tags.set_tag(name, renames[revid])
141
def upgrade_branch(branch, foreign_repository, new_mapping,
142
mapping_registry, allow_changes=False, verbose=False):
90
def upgrade_branch(branch, generate_rebase_map, determine_new_revid,
91
allow_changes=False, verbose=False):
143
92
"""Upgrade a branch to the current mapping version.
145
94
:param branch: Branch to upgrade.
146
95
:param foreign_repository: Repository to fetch new revisions from
147
96
:param allow_changes: Allow changes in mappings.
148
97
:param verbose: Whether to print verbose list of rewrites
150
99
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)
100
renames = upgrade_repository(
101
branch.repository, generate_rebase_map,
102
determine_new_revid, revision_id=revid,
103
allow_changes=allow_changes, verbose=verbose)
159
105
branch.generate_revision_history(renames[revid])
106
ancestry = branch.repository.get_ancestry(
107
branch.last_revision(), topo_sorted=False)
109
branch.tags, branch.repository, generate_rebase_map,
110
determine_new_revid, allow_changes=allow_changes, verbose=verbose,
111
branch_renames=renames, branch_ancestry=ancestry)
163
115
def check_revision_changed(oldrev, newrev):
164
"""Check if two revisions are different. This is exactly the same
116
"""Check if two revisions are different. This is exactly the same
165
117
as Revision.equals() except that it does not check the revision_id."""
166
118
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):
119
newrev.timestamp != oldrev.timestamp or
120
newrev.message != oldrev.message or
121
newrev.timezone != oldrev.timezone or
122
newrev.committer != oldrev.committer or
123
newrev.properties != oldrev.properties):
172
124
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):
127
def create_upgrade_plan(repository, generate_rebase_map, determine_new_revid,
128
revision_id=None, allow_changes=False):
203
129
"""Generate a rebase plan for upgrading revisions.
205
131
:param repository: Repository to do upgrade in
206
:param foreign_repository: Subversion repository to fetch new revisions from.
132
:param foreign_repository: Subversion repository to fetch new revisions
207
134
:param new_mapping: New mapping to use.
208
:param revision_id: Revision to upgrade (None for all revisions in
135
:param revision_id: Revision to upgrade (None for all revisions in
210
137
:param allow_changes: Whether an upgrade is allowed to change the contents
212
139
: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
142
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)
143
upgrade_map = generate_rebase_map(revision_id)
230
145
if not allow_changes:
231
146
for oldrevid, newrevid in upgrade_map.iteritems():
234
149
check_revision_changed(oldrev, newrev)
236
151
if revision_id is None:
237
heads = repository.all_revision_ids()
152
heads = repository.all_revision_ids()
239
154
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))):
156
plan = generate_transpose_plan(
157
graph.iter_ancestry(heads), upgrade_map, graph, determine_new_revid)
158
def remove_parents(entry):
159
(oldrevid, (newrevid, parents)) = entry
244
160
return (oldrevid, newrevid)
245
161
upgrade_map.update(dict(map(remove_parents, plan.iteritems())))
247
163
return (plan, upgrade_map)
250
def upgrade_repository(repository, foreign_repository, new_mapping,
251
mapping_registry, revision_id=None, allow_changes=False,
166
def upgrade_repository(repository, generate_rebase_map,
167
determine_new_revid, revision_id=None,
168
allow_changes=False, verbose=False):
253
169
"""Upgrade the revisions in repository until the specified stop revision.
255
171
:param repository: Repository in which to upgrade.
256
172
:param foreign_repository: Repository to fetch new revisions from.
257
173
:param new_mapping: New mapping.
258
:param revision_id: Revision id up until which to upgrade, or None for
174
:param revision_id: Revision id up until which to upgrade, or None for
260
176
:param allow_changes: Allow changes to mappings.
261
177
:param verbose: Whether to print list of rewrites
262
178
: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
180
# Find revisions that need to be upgraded, create
269
181
# 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)
182
with repository.lock_write():
183
(plan, revid_renames) = create_upgrade_plan(
184
repository, generate_rebase_map, determine_new_revid,
185
revision_id=revision_id, allow_changes=allow_changes)
278
187
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)
188
trace.note("%s -> %s" % (revid, plan[revid][0]))
189
rebase(repository, plan, CommitBuilderRevisionRewriter(repository))
290
190
return revid_renames
293
foreign_repository.unlock()