/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: 2009-03-14 18:17:35 UTC
  • mto: (0.436.139 foreign)
  • mto: This revision was merged to the branch mainline in revision 6960.
  • Revision ID: jelmer@samba.org-20090314181735-i2u2gb2lv6iyy2no
Add keys to virtual VersionedFiles.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006,2008 by Jelmer Vernooij
 
1
# Copyright (C) 2006-2009 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 BzrError, InvalidRevisionId, DependencyNotPresent
 
19
from bzrlib.errors import (
 
20
    DependencyNotPresent,
 
21
    BzrError,
 
22
    InvalidRevisionId,
 
23
    NoSuchRevision,
 
24
    )
20
25
from bzrlib.trace import info
21
26
 
22
27
import itertools
38
43
    """
39
44
    try:
40
45
        from bzrlib.plugins.rebase import version_info as rebase_version_info
41
 
        if rebase_version_info[:2] < min_version:
 
46
        if rebase_version_info[:len(min_version)] < min_version:
42
47
            raise RebaseNotPresent("Version %r present, at least %r required" 
43
48
                                   % (rebase_version_info, min_version))
44
49
    except ImportError, e:
69
74
        return revid + mapping_suffix + upgrade_suffix
70
75
 
71
76
 
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:
76
 
            continue
77
 
        if new_file_id is not None:
78
 
            yield new_tree.id2path(new_file_id), old_file_id, new_file_id
79
 
 
80
 
 
81
 
def upgrade_workingtree(wt, foreign_repository, new_mapping, mapping_registry, 
 
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, 
82
125
                        allow_changes=False, verbose=False):
83
126
    """Upgrade a working tree.
84
127
 
88
131
    try:
89
132
        old_revid = wt.last_revision()
90
133
        revid_renames = upgrade_branch(wt.branch, foreign_repository, new_mapping=new_mapping,
91
 
                                 mapping_registry=mapping_registry,
92
134
                                 allow_changes=allow_changes, verbose=verbose)
93
135
        last_revid = wt.branch.last_revision()
94
136
        if old_revid == last_revid:
95
137
            return revid_renames
96
 
 
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))])
98
 
        old_fileids = []
99
 
        new_fileids = []
100
 
        new_root_id = None
101
 
        # Adjust file ids in working tree
102
 
        for path in sorted(fileid_renames.keys(), reverse=True):
103
 
            if path != "":
104
 
                old_fileids.append(fileid_renames[path][0])
105
 
                new_fileids.append((path, fileid_renames[path][1]))
106
 
            else:
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)
 
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)
114
141
    finally:
115
142
        wt.unlock()
116
143
 
117
144
    return revid_renames
118
145
 
119
146
 
120
 
def upgrade_tags(tags, repository, foreign_repository, new_mapping, mapping_registry, 
121
 
                 allow_changes=False, verbose=False, branch_renames=None):
 
147
def upgrade_tags(tags, repository, foreign_repository, new_mapping, 
 
148
                 allow_changes=False, verbose=False, branch_renames=None,
 
149
                 branch_ancestry=None):
122
150
    """Upgrade a tags dictionary."""
 
151
    renames = {}
 
152
    if branch_renames is not None:
 
153
        renames.update(branch_renames)
123
154
    pb = ui.ui_factory.nested_progress_bar()
124
155
    try:
125
156
        tags_dict = tags.get_tag_dict()
126
157
        for i, (name, revid) in enumerate(tags_dict.items()):
127
158
            pb.update("upgrading tags", i, len(tags_dict))
128
 
            if branch_renames is not None and revid in branch_renames:
129
 
                renames = branch_renames
130
 
            else:
131
 
                renames = upgrade_repository(repository, foreign_repository, 
 
159
            if not revid in renames:
 
160
                renames.update(upgrade_repository(repository, foreign_repository, 
132
161
                      revision_id=revid, new_mapping=new_mapping,
133
 
                      mapping_registry=mapping_registry,
134
 
                      allow_changes=allow_changes, verbose=verbose)
135
 
            if revid in renames:
 
162
                      allow_changes=allow_changes, verbose=verbose))
 
163
            if revid in renames and (branch_ancestry is None or not revid in branch_ancestry):
136
164
                tags.set_tag(name, renames[revid])
137
165
    finally:
138
166
        pb.finished()
139
167
 
140
168
 
141
169
def upgrade_branch(branch, foreign_repository, new_mapping, 
142
 
                   mapping_registry, allow_changes=False, verbose=False):
 
170
                   allow_changes=False, verbose=False):
143
171
    """Upgrade a branch to the current mapping version.
144
172
    
145
173
    :param branch: Branch to upgrade.
150
178
    revid = branch.last_revision()
151
179
    renames = upgrade_repository(branch.repository, foreign_repository, 
152
180
              revision_id=revid, new_mapping=new_mapping,
153
 
              mapping_registry=mapping_registry,
154
181
              allow_changes=allow_changes, verbose=verbose)
 
182
    if revid in renames:
 
183
        branch.generate_revision_history(renames[revid])
 
184
    ancestry = branch.repository.get_ancestry(branch.last_revision(), topo_sorted=False)
155
185
    upgrade_tags(branch.tags, branch.repository, foreign_repository, 
156
 
           new_mapping=new_mapping, mapping_registry=mapping_registry, 
157
 
           allow_changes=allow_changes, verbose=verbose)
158
 
    if len(renames) > 0:
159
 
        branch.generate_revision_history(renames[revid])
 
186
           new_mapping=new_mapping, 
 
187
           allow_changes=allow_changes, verbose=verbose, branch_renames=renames,
 
188
           branch_ancestry=ancestry)
160
189
    return renames
161
190
 
162
191
 
172
201
        raise UpgradeChangesContent(oldrev.revision_id)
173
202
 
174
203
 
175
 
def generate_upgrade_map(new_mapping, revs, mapping_registry):
 
204
def generate_upgrade_map(revs, vcs, determine_upgraded_revid):
176
205
    """Generate an upgrade map for use by bzr-rebase.
177
206
 
178
207
    :param new_mapping: Mapping to upgrade revisions to.
 
208
    :param vcs: The foreign vcs
179
209
    :param revs: Iterator over revisions to upgrade.
180
210
    :return: Map from old revids as keys, new revids as values stored in a 
181
211
             dictionary.
185
215
    for revid in revs:
186
216
        assert isinstance(revid, str)
187
217
        try:
188
 
            (foreign_revid, _) = mapping_registry.parse_revision_id(revid)
 
218
            (foreign_revid, old_mapping) = vcs.mapping_registry.parse_revision_id(revid)
189
219
        except InvalidRevisionId:
190
220
            # Not a foreign revision, nothing to do
191
221
            continue
192
 
        newrevid = new_mapping.revision_id_foreign_to_bzr(foreign_revid)
193
 
        if revid == newrevid:
 
222
        newrevid = determine_upgraded_revid(foreign_revid)
 
223
        if newrevid in (revid, None):
194
224
            continue
195
225
        rename_map[revid] = newrevid
196
 
 
197
226
    return rename_map
198
227
 
199
 
MIN_REBASE_VERSION = (0, 4)
 
228
MIN_REBASE_VERSION = (0, 4, 3)
200
229
 
201
230
def create_upgrade_plan(repository, foreign_repository, new_mapping,
202
 
                        mapping_registry, revision_id=None, allow_changes=False):
 
231
                        revision_id=None, allow_changes=False):
203
232
    """Generate a rebase plan for upgrading revisions.
204
233
 
205
234
    :param repository: Repository to do upgrade in
220
249
    else:
221
250
        potential = itertools.imap(lambda (rev, parents): rev, 
222
251
                graph.iter_ancestry([revision_id]))
223
 
    upgrade_map = generate_upgrade_map(new_mapping, potential, mapping_registry)
 
252
 
 
253
    def determine_upgraded_revid(foreign_revid):
 
254
        # FIXME: Try all mappings until new_mapping rather than just new_mapping
 
255
        new_revid = foreign_repository.upgrade_foreign_revision_id(foreign_revid, new_mapping)
 
256
        if new_revid is None:
 
257
            return None
 
258
        # Make sure the revision is there
 
259
        if not repository.has_revision(new_revid):
 
260
            try:
 
261
                repository.fetch(foreign_repository, new_revid)
 
262
            except NoSuchRevision:
 
263
                return None
 
264
            if not repository.has_revision(new_revid):
 
265
                return None
 
266
        return new_revid
 
267
 
 
268
    upgrade_map = generate_upgrade_map(potential, foreign_repository.vcs, 
 
269
                                       determine_upgraded_revid)
224
270
   
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)
229
 
 
230
271
    if not allow_changes:
231
272
        for oldrevid, newrevid in upgrade_map.iteritems():
232
273
            oldrev = repository.get_revision(oldrevid)
238
279
    else:
239
280
        heads = [revision_id]
240
281
 
 
282
    def determine_new_revid(old_revid):
 
283
        # If this revision id already exists round-tripped upstream, 
 
284
        # leave it alone.
 
285
        if foreign_repository.has_revision(old_revid):
 
286
            return old_revid
 
287
        # if not, return old_revid'
 
288
        return create_upgraded_revid(old_revid, new_mapping.upgrade_suffix)
 
289
 
241
290
    plan = generate_transpose_plan(graph.iter_ancestry(heads), upgrade_map, 
242
 
      graph, lambda revid: create_upgraded_revid(revid, new_mapping.upgrade_suffix))
 
291
      graph, determine_new_revid)
243
292
    def remove_parents((oldrevid, (newrevid, parents))):
244
293
        return (oldrevid, newrevid)
245
294
    upgrade_map.update(dict(map(remove_parents, plan.iteritems())))
248
297
 
249
298
 
250
299
def upgrade_repository(repository, foreign_repository, new_mapping, 
251
 
                       mapping_registry, revision_id=None, allow_changes=False, 
 
300
                       revision_id=None, allow_changes=False, 
252
301
                       verbose=False):
253
302
    """Upgrade the revisions in repository until the specified stop revision.
254
303
 
271
320
        repository.lock_write()
272
321
        foreign_repository.lock_read()
273
322
        (plan, revid_renames) = create_upgrade_plan(repository, foreign_repository, 
274
 
                                                    new_mapping, mapping_registry,
 
323
                                                    new_mapping, 
275
324
                                                    revision_id=revision_id,
276
325
                                                    allow_changes=allow_changes)
277
326
        if verbose:
278
327
            for revid in rebase_todo(repository, plan):
279
328
                info("%s -> %s" % (revid, plan[revid][0]))
280
 
        def fix_revid(revid):
281
 
            try:
282
 
                (foreign_revid, mapping) = mapping_registry.parse_revision_id(revid)
283
 
            except InvalidRevisionId:
284
 
                return revid
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)
 
329
        rebase(repository, plan, replay_snapshot)
290
330
        return revid_renames
291
331
    finally:
292
332
        repository.unlock()