/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.205.33 by Jelmer Vernooij
Import simplifications for upgrade.
1
# Copyright (C) 2006-2009 by Jelmer Vernooij
0.205.12 by Jelmer Vernooij
Import upgrade code for upgrading mappings.
2
# 
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 3 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
"""Upgrading revisions made with older versions of the mapping."""
17
18
from bzrlib import ui
0.205.33 by Jelmer Vernooij
Import simplifications for upgrade.
19
from bzrlib.errors import (
20
    DependencyNotPresent,
21
    BzrError,
22
    InvalidRevisionId,
23
    NoSuchRevision,
24
    )
0.205.12 by Jelmer Vernooij
Import upgrade code for upgrading mappings.
25
from bzrlib.trace import info
26
27
import itertools
28
29
class RebaseNotPresent(DependencyNotPresent):
30
    _fmt = "Unable to import bzr-rebase (required for upgrade support): %(error)s"
31
32
    def __init__(self, error):
33
        DependencyNotPresent.__init__(self, 'bzr-rebase', error)
34
35
36
def check_rebase_version(min_version):
37
    """Check what version of bzr-rebase is installed.
38
39
    Raises an exception when the version installed is older than 
40
    min_version.
41
42
    :raises RebaseNotPresent: Raised if bzr-rebase is not installed or too old.
43
    """
44
    try:
45
        from bzrlib.plugins.rebase import version_info as rebase_version_info
0.205.33 by Jelmer Vernooij
Import simplifications for upgrade.
46
        if rebase_version_info[:len(min_version)] < min_version:
0.205.12 by Jelmer Vernooij
Import upgrade code for upgrading mappings.
47
            raise RebaseNotPresent("Version %r present, at least %r required" 
48
                                   % (rebase_version_info, min_version))
49
    except ImportError, e:
50
        raise RebaseNotPresent(e)
51
52
53
54
class UpgradeChangesContent(BzrError):
55
    """Inconsistency was found upgrading the mapping of a revision."""
56
    _fmt = """Upgrade will change contents in revision %(revid)s. Use --allow-changes to override."""
57
58
    def __init__(self, revid):
59
        self.revid = revid
60
61
62
63
def create_upgraded_revid(revid, mapping_suffix, upgrade_suffix="-upgrade"):
64
    """Create a new revision id for an upgraded version of a revision.
65
    
66
    Prevents suffix to be appended needlessly.
67
68
    :param revid: Original revision id.
69
    :return: New revision id
70
    """
71
    if revid.endswith(upgrade_suffix):
72
        return revid[0:revid.rfind("-svn")] + mapping_suffix + upgrade_suffix
73
    else:
74
        return revid + mapping_suffix + upgrade_suffix
75
76
0.205.33 by Jelmer Vernooij
Import simplifications for upgrade.
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)
0.205.36 by Jelmer Vernooij
Just replace all file ids, rather than worrying about unchanged children of changed directories.
94
        ret[new_inv.id2path(new_file_id)] = (old_file_id, new_file_id)
0.205.33 by Jelmer Vernooij
Import simplifications for upgrade.
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
0.205.36 by Jelmer Vernooij
Just replace all file ids, rather than worrying about unchanged children of changed directories.
110
    for path in sorted(fileid_renames.keys()):
0.205.33 by Jelmer Vernooij
Import simplifications for upgrade.
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)
0.205.12 by Jelmer Vernooij
Import upgrade code for upgrading mappings.
122
123
0.227.1 by Jelmer Vernooij
Import foreign-mapping-upgrade.
124
def upgrade_workingtree(wt, foreign_repository, new_mapping, 
0.205.12 by Jelmer Vernooij
Import upgrade code for upgrading mappings.
125
                        allow_changes=False, verbose=False):
126
    """Upgrade a working tree.
127
128
    :param foreign_repository: Foreign repository object
129
    """
130
    wt.lock_write()
131
    try:
132
        old_revid = wt.last_revision()
0.205.16 by Jelmer Vernooij
Import fixes from bzr-svn.
133
        revid_renames = upgrade_branch(wt.branch, foreign_repository, new_mapping=new_mapping,
0.205.12 by Jelmer Vernooij
Import upgrade code for upgrading mappings.
134
                                 allow_changes=allow_changes, verbose=verbose)
135
        last_revid = wt.branch.last_revision()
0.205.16 by Jelmer Vernooij
Import fixes from bzr-svn.
136
        if old_revid == last_revid:
137
            return revid_renames
0.205.33 by Jelmer Vernooij
Import simplifications for upgrade.
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)
0.205.12 by Jelmer Vernooij
Import upgrade code for upgrading mappings.
141
    finally:
142
        wt.unlock()
143
0.205.16 by Jelmer Vernooij
Import fixes from bzr-svn.
144
    return revid_renames
145
146
0.227.1 by Jelmer Vernooij
Import foreign-mapping-upgrade.
147
def upgrade_tags(tags, repository, foreign_repository, new_mapping, 
0.205.41 by Jelmer Vernooij
Fix typo.
148
                 allow_changes=False, verbose=False, branch_renames=None,
0.205.40 by Jelmer Vernooij
Don't upgrade tags to revisions in branch ancestry.
149
                 branch_ancestry=None):
0.205.16 by Jelmer Vernooij
Import fixes from bzr-svn.
150
    """Upgrade a tags dictionary."""
0.205.33 by Jelmer Vernooij
Import simplifications for upgrade.
151
    renames = {}
152
    if branch_renames is not None:
153
        renames.update(branch_renames)
0.205.16 by Jelmer Vernooij
Import fixes from bzr-svn.
154
    pb = ui.ui_factory.nested_progress_bar()
155
    try:
156
        tags_dict = tags.get_tag_dict()
157
        for i, (name, revid) in enumerate(tags_dict.items()):
158
            pb.update("upgrading tags", i, len(tags_dict))
0.205.33 by Jelmer Vernooij
Import simplifications for upgrade.
159
            if not revid in renames:
160
                renames.update(upgrade_repository(repository, foreign_repository, 
0.205.16 by Jelmer Vernooij
Import fixes from bzr-svn.
161
                      revision_id=revid, new_mapping=new_mapping,
0.205.33 by Jelmer Vernooij
Import simplifications for upgrade.
162
                      allow_changes=allow_changes, verbose=verbose))
0.205.40 by Jelmer Vernooij
Don't upgrade tags to revisions in branch ancestry.
163
            if revid in renames and (branch_ancestry is None or not revid in branch_ancestry):
0.205.16 by Jelmer Vernooij
Import fixes from bzr-svn.
164
                tags.set_tag(name, renames[revid])
165
    finally:
166
        pb.finished()
0.205.12 by Jelmer Vernooij
Import upgrade code for upgrading mappings.
167
168
0.205.14 by Jelmer Vernooij
Fix upgrade_branch.
169
def upgrade_branch(branch, foreign_repository, new_mapping, 
0.227.1 by Jelmer Vernooij
Import foreign-mapping-upgrade.
170
                   allow_changes=False, verbose=False):
0.205.12 by Jelmer Vernooij
Import upgrade code for upgrading mappings.
171
    """Upgrade a branch to the current mapping version.
172
    
173
    :param branch: Branch to upgrade.
174
    :param foreign_repository: Repository to fetch new revisions from
175
    :param allow_changes: Allow changes in mappings.
176
    :param verbose: Whether to print verbose list of rewrites
177
    """
178
    revid = branch.last_revision()
179
    renames = upgrade_repository(branch.repository, foreign_repository, 
180
              revision_id=revid, new_mapping=new_mapping,
181
              allow_changes=allow_changes, verbose=verbose)
0.205.40 by Jelmer Vernooij
Don't upgrade tags to revisions in branch ancestry.
182
    if revid in renames:
183
        branch.generate_revision_history(renames[revid])
184
    ancestry = branch.repository.get_ancestry(branch.last_revision(), topo_sorted=False)
0.205.16 by Jelmer Vernooij
Import fixes from bzr-svn.
185
    upgrade_tags(branch.tags, branch.repository, foreign_repository, 
0.227.1 by Jelmer Vernooij
Import foreign-mapping-upgrade.
186
           new_mapping=new_mapping, 
0.205.40 by Jelmer Vernooij
Don't upgrade tags to revisions in branch ancestry.
187
           allow_changes=allow_changes, verbose=verbose, branch_renames=renames,
188
           branch_ancestry=ancestry)
0.205.12 by Jelmer Vernooij
Import upgrade code for upgrading mappings.
189
    return renames
190
191
192
def check_revision_changed(oldrev, newrev):
193
    """Check if two revisions are different. This is exactly the same 
194
    as Revision.equals() except that it does not check the revision_id."""
195
    if (newrev.inventory_sha1 != oldrev.inventory_sha1 or
196
        newrev.timestamp != oldrev.timestamp or
197
        newrev.message != oldrev.message or
198
        newrev.timezone != oldrev.timezone or
199
        newrev.committer != oldrev.committer or
200
        newrev.properties != oldrev.properties):
201
        raise UpgradeChangesContent(oldrev.revision_id)
202
203
0.227.1 by Jelmer Vernooij
Import foreign-mapping-upgrade.
204
def generate_upgrade_map(revs, vcs, determine_upgraded_revid):
0.205.12 by Jelmer Vernooij
Import upgrade code for upgrading mappings.
205
    """Generate an upgrade map for use by bzr-rebase.
206
207
    :param new_mapping: Mapping to upgrade revisions to.
0.227.1 by Jelmer Vernooij
Import foreign-mapping-upgrade.
208
    :param vcs: The foreign vcs
0.205.12 by Jelmer Vernooij
Import upgrade code for upgrading mappings.
209
    :param revs: Iterator over revisions to upgrade.
210
    :return: Map from old revids as keys, new revids as values stored in a 
211
             dictionary.
212
    """
213
    rename_map = {}
0.205.16 by Jelmer Vernooij
Import fixes from bzr-svn.
214
    # Create a list of revisions that can be renamed during the upgrade
0.205.12 by Jelmer Vernooij
Import upgrade code for upgrading mappings.
215
    for revid in revs:
216
        assert isinstance(revid, str)
217
        try:
0.227.1 by Jelmer Vernooij
Import foreign-mapping-upgrade.
218
            (foreign_revid, old_mapping) = vcs.mapping_registry.parse_revision_id(revid)
0.205.12 by Jelmer Vernooij
Import upgrade code for upgrading mappings.
219
        except InvalidRevisionId:
220
            # Not a foreign revision, nothing to do
221
            continue
0.205.33 by Jelmer Vernooij
Import simplifications for upgrade.
222
        newrevid = determine_upgraded_revid(foreign_revid)
223
        if newrevid in (revid, None):
0.205.12 by Jelmer Vernooij
Import upgrade code for upgrading mappings.
224
            continue
225
        rename_map[revid] = newrevid
226
    return rename_map
227
0.205.33 by Jelmer Vernooij
Import simplifications for upgrade.
228
MIN_REBASE_VERSION = (0, 4, 3)
0.205.12 by Jelmer Vernooij
Import upgrade code for upgrading mappings.
229
230
def create_upgrade_plan(repository, foreign_repository, new_mapping,
0.227.1 by Jelmer Vernooij
Import foreign-mapping-upgrade.
231
                        revision_id=None, allow_changes=False):
0.205.12 by Jelmer Vernooij
Import upgrade code for upgrading mappings.
232
    """Generate a rebase plan for upgrading revisions.
233
234
    :param repository: Repository to do upgrade in
235
    :param foreign_repository: Subversion repository to fetch new revisions from.
236
    :param new_mapping: New mapping to use.
237
    :param revision_id: Revision to upgrade (None for all revisions in 
238
        repository.)
239
    :param allow_changes: Whether an upgrade is allowed to change the contents
240
        of revisions.
241
    :return: Tuple with a rebase plan and map of renamed revisions.
242
    """
243
    from bzrlib.plugins.rebase.rebase import generate_transpose_plan
244
    check_rebase_version(MIN_REBASE_VERSION)
245
246
    graph = repository.get_graph()
247
    if revision_id is None:
248
        potential = repository.all_revision_ids()
249
    else:
250
        potential = itertools.imap(lambda (rev, parents): rev, 
251
                graph.iter_ancestry([revision_id]))
0.205.33 by Jelmer Vernooij
Import simplifications for upgrade.
252
253
    def determine_upgraded_revid(foreign_revid):
254
        # FIXME: Try all mappings until new_mapping rather than just new_mapping
0.227.1 by Jelmer Vernooij
Import foreign-mapping-upgrade.
255
        new_revid = foreign_repository.upgrade_foreign_revision_id(foreign_revid, new_mapping)
256
        if new_revid is None:
257
            return None
0.205.33 by Jelmer Vernooij
Import simplifications for upgrade.
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
0.227.1 by Jelmer Vernooij
Import foreign-mapping-upgrade.
264
            if not repository.has_revision(new_revid):
265
                return None
0.205.33 by Jelmer Vernooij
Import simplifications for upgrade.
266
        return new_revid
267
0.227.1 by Jelmer Vernooij
Import foreign-mapping-upgrade.
268
    upgrade_map = generate_upgrade_map(potential, foreign_repository.vcs, 
269
                                       determine_upgraded_revid)
0.205.12 by Jelmer Vernooij
Import upgrade code for upgrading mappings.
270
   
271
    if not allow_changes:
0.205.22 by Jelmer Vernooij
Merge improvements from bzr-svn.
272
        for oldrevid, newrevid in upgrade_map.iteritems():
0.205.12 by Jelmer Vernooij
Import upgrade code for upgrading mappings.
273
            oldrev = repository.get_revision(oldrevid)
274
            newrev = repository.get_revision(newrevid)
275
            check_revision_changed(oldrev, newrev)
276
277
    if revision_id is None:
278
        heads = repository.all_revision_ids() 
279
    else:
280
        heads = [revision_id]
281
0.227.1 by Jelmer Vernooij
Import foreign-mapping-upgrade.
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'
0.205.37 by Jelmer Vernooij
Import foreign-mapping-upgrade command, fixes for bzr-svn.
288
        return create_upgraded_revid(old_revid, new_mapping.upgrade_suffix)
0.227.1 by Jelmer Vernooij
Import foreign-mapping-upgrade.
289
0.205.12 by Jelmer Vernooij
Import upgrade code for upgrading mappings.
290
    plan = generate_transpose_plan(graph.iter_ancestry(heads), upgrade_map, 
0.227.1 by Jelmer Vernooij
Import foreign-mapping-upgrade.
291
      graph, determine_new_revid)
0.205.12 by Jelmer Vernooij
Import upgrade code for upgrading mappings.
292
    def remove_parents((oldrevid, (newrevid, parents))):
293
        return (oldrevid, newrevid)
0.205.22 by Jelmer Vernooij
Merge improvements from bzr-svn.
294
    upgrade_map.update(dict(map(remove_parents, plan.iteritems())))
0.205.12 by Jelmer Vernooij
Import upgrade code for upgrading mappings.
295
296
    return (plan, upgrade_map)
297
298
 
299
def upgrade_repository(repository, foreign_repository, new_mapping, 
0.227.1 by Jelmer Vernooij
Import foreign-mapping-upgrade.
300
                       revision_id=None, allow_changes=False, 
0.205.12 by Jelmer Vernooij
Import upgrade code for upgrading mappings.
301
                       verbose=False):
302
    """Upgrade the revisions in repository until the specified stop revision.
303
304
    :param repository: Repository in which to upgrade.
305
    :param foreign_repository: Repository to fetch new revisions from.
306
    :param new_mapping: New mapping.
307
    :param revision_id: Revision id up until which to upgrade, or None for 
308
                        all revisions.
309
    :param allow_changes: Allow changes to mappings.
310
    :param verbose: Whether to print list of rewrites
311
    :return: Dictionary of mapped revisions
312
    """
313
    check_rebase_version(MIN_REBASE_VERSION)
314
    from bzrlib.plugins.rebase.rebase import (
315
        replay_snapshot, rebase, rebase_todo)
316
317
    # Find revisions that need to be upgraded, create
318
    # dictionary with revision ids in key, new parents in value
319
    try:
320
        repository.lock_write()
321
        foreign_repository.lock_read()
322
        (plan, revid_renames) = create_upgrade_plan(repository, foreign_repository, 
0.227.1 by Jelmer Vernooij
Import foreign-mapping-upgrade.
323
                                                    new_mapping, 
0.205.12 by Jelmer Vernooij
Import upgrade code for upgrading mappings.
324
                                                    revision_id=revision_id,
325
                                                    allow_changes=allow_changes)
326
        if verbose:
327
            for revid in rebase_todo(repository, plan):
328
                info("%s -> %s" % (revid, plan[revid][0]))
0.205.33 by Jelmer Vernooij
Import simplifications for upgrade.
329
        rebase(repository, plan, replay_snapshot)
0.205.12 by Jelmer Vernooij
Import upgrade code for upgrading mappings.
330
        return revid_renames
331
    finally:
332
        repository.unlock()
333
        foreign_repository.unlock()
334