/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to upgrade.py

  • Committer: Jelmer Vernooij
  • Date: 2008-11-10 16:16:50 UTC
  • mfrom: (0.207.2 trunk)
  • mto: (0.219.2 trunk)
  • mto: This revision was merged to the branch mainline in revision 6960.
  • Revision ID: jelmer@samba.org-20081110161650-147q2c84jb754ukg
Merge trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2009 by Jelmer Vernooij
 
1
# Copyright (C) 2006,2008 by Jelmer Vernooij
2
2
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
16
16
"""Upgrading revisions made with older versions of the mapping."""
17
17
 
18
18
from bzrlib import ui
19
 
from bzrlib.errors import (
20
 
    DependencyNotPresent,
21
 
    BzrError,
22
 
    InvalidRevisionId,
23
 
    NoSuchRevision,
24
 
    )
 
19
from bzrlib.errors import BzrError, InvalidRevisionId, DependencyNotPresent
 
20
from bzrlib.revision import Revision
25
21
from bzrlib.trace import info
26
22
 
27
23
import itertools
43
39
    """
44
40
    try:
45
41
        from bzrlib.plugins.rebase import version_info as rebase_version_info
46
 
        if rebase_version_info[:len(min_version)] < min_version:
 
42
        if rebase_version_info[:2] < min_version:
47
43
            raise RebaseNotPresent("Version %r present, at least %r required" 
48
44
                                   % (rebase_version_info, min_version))
49
45
    except ImportError, e:
74
70
        return revid + mapping_suffix + upgrade_suffix
75
71
 
76
72
 
77
 
def determine_fileid_renames(old_inv, new_inv):
78
 
    """Determine the file ids based on a old and a new inventory that 
79
 
    are equal in content.
80
 
 
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 
84
 
        inventories.
85
 
    """
86
 
    ret = {}
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:
92
 
            raise AssertionError(
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)
95
 
    return ret
96
 
 
97
 
 
98
 
def update_workinginv_fileids(wt, old_inv, new_inv):
99
 
    """Update all file ids in wt according to old_tree/new_tree. 
100
 
 
101
 
    old_tree and new_tree should be two RevisionTree's that differ only
102
 
    in file ids.
103
 
    """
104
 
    fileid_renames = determine_fileid_renames(old_inv, new_inv)
105
 
    old_fileids = []
106
 
    new_fileids = []
107
 
    new_root_id = None
108
 
    # Adjust file ids in working tree
109
 
    # Sorted, so we process parents before children
110
 
    for path in sorted(fileid_renames.keys()):
111
 
        if path != "":
112
 
            old_fileids.append(fileid_renames[path][0])
113
 
            new_fileids.append((path, fileid_renames[path][1]))
114
 
        else:
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)
122
 
 
123
 
 
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:
 
77
            continue
 
78
        if new_file_id is not None:
 
79
            yield new_tree.id2path(new_file_id), old_file_id, new_file_id
 
80
 
 
81
 
 
82
def upgrade_workingtree(wt, foreign_repository, new_mapping, mapping_registry, 
125
83
                        allow_changes=False, verbose=False):
126
84
    """Upgrade a working tree.
127
85
 
131
89
    try:
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)
 
97
 
 
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))])
 
99
        old_fileids = []
 
100
        new_fileids = []
 
101
        new_root_id = None
 
102
        # Adjust file ids in working tree
 
103
        for path in sorted(fileid_renames.keys(), reverse=True):
 
104
            if path != "":
 
105
                old_fileids.append(fileid_renames[path][0])
 
106
                new_fileids.append((path, fileid_renames[path][1]))
 
107
            else:
 
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)
141
115
    finally:
142
116
        wt.unlock()
143
117
 
144
118
    return revid_renames
145
119
 
146
120
 
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."""
150
 
    renames = {}
151
 
    if branch_renames is not None:
152
 
        renames.update(branch_renames)
153
124
    pb = ui.ui_factory.nested_progress_bar()
154
125
    try:
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
 
131
            else:
 
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])
164
138
    finally:
166
140
 
167
141
 
168
142
def upgrade_branch(branch, foreign_repository, new_mapping, 
169
 
                   allow_changes=False, verbose=False):
 
143
                   mapping_registry, allow_changes=False, verbose=False):
170
144
    """Upgrade a branch to the current mapping version.
171
145
    
172
146
    :param branch: Branch to upgrade.
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)
184
 
    if revid in renames:
 
157
           new_mapping=new_mapping, mapping_registry=mapping_registry, 
 
158
           allow_changes=allow_changes, verbose=verbose)
 
159
    if len(renames) > 0:
185
160
        branch.generate_revision_history(renames[revid])
186
161
    return renames
187
162
 
198
173
        raise UpgradeChangesContent(oldrev.revision_id)
199
174
 
200
175
 
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.
203
178
 
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 
208
182
             dictionary.
212
186
    for revid in revs:
213
187
        assert isinstance(revid, str)
214
188
        try:
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
218
192
            continue
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:
221
195
            continue
222
196
        rename_map[revid] = newrevid
 
197
 
223
198
    return rename_map
224
199
 
225
 
MIN_REBASE_VERSION = (0, 4, 3)
 
200
MIN_REBASE_VERSION = (0, 4)
226
201
 
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.
230
205
 
231
206
    :param repository: Repository to do upgrade in
246
221
    else:
247
222
        potential = itertools.imap(lambda (rev, parents): rev, 
248
223
                graph.iter_ancestry([revision_id]))
249
 
 
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:
254
 
            return None
255
 
        # Make sure the revision is there
256
 
        if not repository.has_revision(new_revid):
257
 
            try:
258
 
                repository.fetch(foreign_repository, new_revid)
259
 
            except NoSuchRevision:
260
 
                return None
261
 
            if not repository.has_revision(new_revid):
262
 
                return None
263
 
        return new_revid
264
 
 
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)
267
225
   
 
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)
 
230
 
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)
276
239
    else:
277
240
        heads = [revision_id]
278
241
 
279
 
    def determine_new_revid(old_revid):
280
 
        # If this revision id already exists round-tripped upstream, 
281
 
        # leave it alone.
282
 
        if foreign_repository.has_revision(old_revid):
283
 
            return old_revid
284
 
        # if not, return old_revid'
285
 
        return create_upgraded_revid(old_revid, new_mapping.upgrade_suffix)
286
 
 
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())))
292
247
 
293
248
    return (plan, upgrade_map)
294
249
 
295
250
 
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, 
298
253
                       verbose=False):
299
254
    """Upgrade the revisions in repository until the specified stop revision.
300
255
 
317
272
        repository.lock_write()
318
273
        foreign_repository.lock_read()
319
274
        (plan, revid_renames) = create_upgrade_plan(repository, foreign_repository, 
320
 
                                                    new_mapping, 
 
275
                                                    new_mapping, mapping_registry,
321
276
                                                    revision_id=revision_id,
322
277
                                                    allow_changes=allow_changes)
323
278
        if verbose:
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):
 
282
            try:
 
283
                (foreign_revid, mapping) = mapping_registry.parse_revision_id(revid)
 
284
            except InvalidRevisionId:
 
285
                return revid
 
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
328
292
    finally:
329
293
        repository.unlock()