/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-19 16:43:56 UTC
  • mto: (0.436.139 foreign)
  • mto: This revision was merged to the branch mainline in revision 6960.
  • Revision ID: jelmer@samba.org-20090319164356-iwxw3x3ntre7fjxc
Fix formatting.

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
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
"""Upgrading revisions made with older versions of the mapping."""
17
17
 
18
 
from bzrlib import ui
19
 
from bzrlib.errors import BzrError, InvalidRevisionId, DependencyNotPresent
20
 
from bzrlib.trace import info
 
18
from bzrlib import (
 
19
    trace,
 
20
    ui,
 
21
    )
 
22
from bzrlib.errors import (
 
23
    DependencyNotPresent,
 
24
    BzrError,
 
25
    InvalidRevisionId,
 
26
    NoSuchRevision,
 
27
    )
21
28
 
22
29
import itertools
23
30
 
38
45
    """
39
46
    try:
40
47
        from bzrlib.plugins.rebase import version_info as rebase_version_info
41
 
        if rebase_version_info[:2] < min_version:
 
48
        if rebase_version_info[:len(min_version)] < min_version:
42
49
            raise RebaseNotPresent("Version %r present, at least %r required" 
43
50
                                   % (rebase_version_info, min_version))
44
51
    except ImportError, e:
69
76
        return revid + mapping_suffix + upgrade_suffix
70
77
 
71
78
 
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, 
 
79
def determine_fileid_renames(old_inv, new_inv):
 
80
    """Determine the file ids based on a old and a new inventory that 
 
81
    are equal in content.
 
82
 
 
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 
 
86
        inventories.
 
87
    """
 
88
    ret = {}
 
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:
 
94
            raise AssertionError(
 
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)
 
97
    return ret
 
98
 
 
99
 
 
100
def update_workinginv_fileids(wt, old_inv, new_inv):
 
101
    """Update all file ids in wt according to old_tree/new_tree. 
 
102
 
 
103
    old_tree and new_tree should be two RevisionTree's that differ only
 
104
    in file ids.
 
105
    """
 
106
    fileid_renames = determine_fileid_renames(old_inv, new_inv)
 
107
    old_fileids = []
 
108
    new_fileids = []
 
109
    new_root_id = None
 
110
    # Adjust file ids in working tree
 
111
    # Sorted, so we process parents before children
 
112
    for path in sorted(fileid_renames.keys()):
 
113
        if path != "":
 
114
            old_fileids.append(fileid_renames[path][0])
 
115
            new_fileids.append((path, fileid_renames[path][1]))
 
116
        else:
 
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)
 
124
 
 
125
 
 
126
def upgrade_workingtree(wt, foreign_repository, new_mapping, 
82
127
                        allow_changes=False, verbose=False):
83
128
    """Upgrade a working tree.
84
129
 
88
133
    try:
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
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)
 
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)
114
143
    finally:
115
144
        wt.unlock()
116
145
 
117
146
    return revid_renames
118
147
 
119
148
 
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."""
 
153
    renames = {}
 
154
    if branch_renames is not None:
 
155
        renames.update(branch_renames)
123
156
    pb = ui.ui_factory.nested_progress_bar()
124
157
    try:
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
130
 
            else:
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)
135
 
            if revid in renames:
 
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])
137
167
    finally:
138
168
        pb.finished()
139
169
 
140
170
 
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.
144
174
    
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)
 
184
    if revid in renames:
 
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)
158
 
    if len(renames) > 0:
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)
160
191
    return renames
161
192
 
162
193
 
172
203
        raise UpgradeChangesContent(oldrev.revision_id)
173
204
 
174
205
 
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.
177
208
 
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 
181
213
             dictionary.
185
217
    for revid in revs:
186
218
        assert isinstance(revid, str)
187
219
        try:
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
191
223
            continue
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):
194
226
            continue
195
227
        rename_map[revid] = newrevid
196
 
 
197
228
    return rename_map
198
229
 
199
 
MIN_REBASE_VERSION = (0, 4)
 
230
MIN_REBASE_VERSION = (0, 4, 3)
200
231
 
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.
204
235
 
205
236
    :param repository: Repository to do upgrade in
220
251
    else:
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)
 
254
 
 
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:
 
259
            return None
 
260
        # Make sure the revision is there
 
261
        if not repository.has_revision(new_revid):
 
262
            try:
 
263
                repository.fetch(foreign_repository, new_revid)
 
264
            except NoSuchRevision:
 
265
                return None
 
266
            if not repository.has_revision(new_revid):
 
267
                return None
 
268
        return new_revid
 
269
 
 
270
    upgrade_map = generate_upgrade_map(potential, foreign_repository.vcs, 
 
271
                                       determine_upgraded_revid)
224
272
   
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
273
    if not allow_changes:
231
274
        for oldrevid, newrevid in upgrade_map.iteritems():
232
275
            oldrev = repository.get_revision(oldrevid)
238
281
    else:
239
282
        heads = [revision_id]
240
283
 
 
284
    def determine_new_revid(old_revid):
 
285
        # If this revision id already exists round-tripped upstream, 
 
286
        # leave it alone.
 
287
        if foreign_repository.has_revision(old_revid):
 
288
            return old_revid
 
289
        # if not, return old_revid'
 
290
        return create_upgraded_revid(old_revid, new_mapping.upgrade_suffix)
 
291
 
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())))
248
299
 
249
300
 
250
301
def upgrade_repository(repository, foreign_repository, new_mapping, 
251
 
                       mapping_registry, revision_id=None, allow_changes=False, 
 
302
                       revision_id=None, allow_changes=False, 
252
303
                       verbose=False):
253
304
    """Upgrade the revisions in repository until the specified stop revision.
254
305
 
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,
 
325
                                                    new_mapping, 
275
326
                                                    revision_id=revision_id,
276
327
                                                    allow_changes=allow_changes)
277
328
        if verbose:
278
329
            for revid in rebase_todo(repository, plan):
279
 
                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)
 
330
                trace.info("%s -> %s" % (revid, plan[revid][0]))
 
331
        rebase(repository, plan, replay_snapshot)
290
332
        return revid_renames
291
333
    finally:
292
334
        repository.unlock()