/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
1080 by Martin Pool
- test tool for converting history to weave files
1
# Copyright (C) 2005 Canonical Ltd
1267 by Martin Pool
- notes on conversion of existing history to weaves
2
#
1080 by Martin Pool
- test tool for converting history to weave files
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 2 of the License, or
6
# (at your option) any later version.
1267 by Martin Pool
- notes on conversion of existing history to weaves
7
#
1080 by Martin Pool
- test tool for converting history to weave files
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.
1267 by Martin Pool
- notes on conversion of existing history to weaves
12
#
1080 by Martin Pool
- test tool for converting history to weave files
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
17
"""Experiment in converting existing bzr branches to weaves."""
18
1267 by Martin Pool
- notes on conversion of existing history to weaves
19
# To make this properly useful
20
#
21
# 1. assign text version ids, and put those text versions into
22
#    the inventory as they're converted.
23
#
24
# 2. keep track of the previous version of each file, rather than
25
#    just using the last one imported
26
#
27
# 3. assign entry versions when files are added, renamed or moved.
28
#
29
# 4. when merged-in versions are observed, walk down through them
30
#    to discover everything, then commit bottom-up
31
#
32
# 5. track ancestry as things are merged in, and commit that in each
33
#    revision
34
#
35
# Perhaps it's best to first walk the whole graph and make a plan for
36
# what should be imported in what order?  Need a kind of topological
37
# sort of all revisions.  (Or do we, can we just before doing a revision
38
# see that all its parents have either been converted or abandoned?)
39
1315 by Martin Pool
- import file inventories in correct order
40
41
# Cannot import a revision until all its parents have been
42
# imported.  in other words, we can only import revisions whose
43
# parents have all been imported.  the first step must be to
44
# import a revision with no parents, of which there must be at
45
# least one.  (So perhaps it's useful to store forward pointers
46
# from a list of parents to their children?)
47
#
48
# Another (equivalent?) approach is to build up the ordered
49
# ancestry list for the last revision, and walk through that.  We
50
# are going to need that.
51
#
52
# We don't want to have to recurse all the way back down the list.
53
#
54
# Suppose we keep a queue of the revisions able to be processed at
55
# any point.  This starts out with all the revisions having no
56
# parents.
57
#
58
# This seems like a generally useful algorithm...
59
#
60
# The current algorithm is dumb (O(n**2)?) but will do the job, and
61
# takes less than a second on the bzr.dev branch.
62
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
63
# This currently does a kind of lazy conversion of file texts, where a
64
# new text is written in every version.  That's unnecessary but for
65
# the moment saves us having to worry about when files need new
66
# versions.
67
68
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
69
import os
1267 by Martin Pool
- notes on conversion of existing history to weaves
70
import tempfile
71
import sys
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
72
import shutil
1132 by Martin Pool
- fix up logging for history2weaves tool
73
1185.65.29 by Robert Collins
Implement final review suggestions.
74
from bzrlib.branch import Branch
1429 by Robert Collins
merge in niemeyers prefixed-store patch
75
from bzrlib.branch import BZR_BRANCH_FORMAT_5, BZR_BRANCH_FORMAT_6
1185.17.1 by Martin Pool
[pick] clear hashcache in format upgrade to avoid worrisome warning
76
import bzrlib.hashcache as hashcache
1080 by Martin Pool
- test tool for converting history to weave files
77
from bzrlib.weave import Weave
78
from bzrlib.weavefile import read_weave, write_weave
1393.1.43 by Martin Pool
- upgrade should use ui_factory, not make a progress bar directly
79
from bzrlib.ui import ui_factory
1080 by Martin Pool
- test tool for converting history to weave files
80
from bzrlib.atomicfile import AtomicFile
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
81
from bzrlib.xml4 import serializer_v4
82
from bzrlib.xml5 import serializer_v5
1185.33.12 by Martin Pool
Remove some direct calls to logging, and some dead code
83
from bzrlib.trace import mutter, note, warning
1185.31.37 by John Arbash Meinel
Switched os.path.abspath and os.path.realpath to osutils.* (still passes on cygwin)
84
from bzrlib.osutils import sha_strings, sha_string, pathjoin, abspath
1267 by Martin Pool
- notes on conversion of existing history to weaves
85
1080 by Martin Pool
- test tool for converting history to weave files
86
1185.62.12 by John Arbash Meinel
Adding TODO to upgrade.py to remove ancestry.weave
87
# TODO: jam 20060108 Create a new branch format, and as part of upgrade
88
#       make sure that ancestry.weave is deleted (it is never used, but
89
#       used to be created)
90
91
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
92
class Convert(object):
1377 by Martin Pool
- run conversion to weaves from the 'bzr upgrade' command
93
    def __init__(self, base_dir):
94
        self.base = base_dir
1307 by Martin Pool
- start walking through ancestors in conversion to weaves
95
        self.converted_revs = set()
96
        self.absent_revisions = set()
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
97
        self.text_count = 0
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
98
        self.revisions = {}
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
99
        self.convert()
100
101
102
    def convert(self):
1382 by Martin Pool
- upgrade checks if branch is uptodate before anything else
103
        if not self._open_branch():
104
            return
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
105
        note('starting upgrade of %s', os.path.abspath(self.base))
1381 by Martin Pool
- remove tab characters (only)
106
        self._backup_control_dir()
1429 by Robert Collins
merge in niemeyers prefixed-store patch
107
        self.pb = ui_factory.progress_bar()
108
        if self.old_format == 4:
109
            note('starting upgrade from format 4 to 5')
1185.67.5 by Aaron Bentley
Added write locks as appropriate
110
            self.branch.lock_write()
111
            try:
112
                self._convert_to_weaves()
113
            finally:
114
                self.branch.unlock()
1429 by Robert Collins
merge in niemeyers prefixed-store patch
115
            self._open_branch()
116
        if self.old_format == 5:
117
            note('starting upgrade from format 5 to 6')
1185.67.5 by Aaron Bentley
Added write locks as appropriate
118
            self.branch.lock_write()
119
            try:
120
                self._convert_to_prefixed()
121
            finally:
122
                self.branch.unlock()
1429 by Robert Collins
merge in niemeyers prefixed-store patch
123
            self._open_branch()
1185.31.37 by John Arbash Meinel
Switched os.path.abspath and os.path.realpath to osutils.* (still passes on cygwin)
124
        cache = hashcache.HashCache(abspath(self.base))
1185.17.1 by Martin Pool
[pick] clear hashcache in format upgrade to avoid worrisome warning
125
        cache.clear()
126
        cache.write()
1429 by Robert Collins
merge in niemeyers prefixed-store patch
127
        note("finished")
128
129
130
    def _convert_to_prefixed(self):
131
        from bzrlib.store import hash_prefix
132
        for store_name in ["weaves", "revision-store"]:
133
            note("adding prefixes to %s" % store_name) 
1185.31.32 by John Arbash Meinel
Updated the bzr sourcecode to use bzrlib.osutils.pathjoin rather than os.path.join to enforce internal use of / instead of \
134
            store_dir = pathjoin(self.base, ".bzr", store_name)
1429 by Robert Collins
merge in niemeyers prefixed-store patch
135
            for filename in os.listdir(store_dir):
136
                if filename.endswith(".weave") or filename.endswith(".gz"):
137
                    file_id = os.path.splitext(filename)[0]
138
                else:
139
                    file_id = filename
1185.31.32 by John Arbash Meinel
Updated the bzr sourcecode to use bzrlib.osutils.pathjoin rather than os.path.join to enforce internal use of / instead of \
140
                prefix_dir = pathjoin(store_dir, hash_prefix(file_id))
1429 by Robert Collins
merge in niemeyers prefixed-store patch
141
                if not os.path.isdir(prefix_dir):
142
                    os.mkdir(prefix_dir)
1185.31.32 by John Arbash Meinel
Updated the bzr sourcecode to use bzrlib.osutils.pathjoin rather than os.path.join to enforce internal use of / instead of \
143
                os.rename(pathjoin(store_dir, filename),
144
                          pathjoin(prefix_dir, filename))
1429 by Robert Collins
merge in niemeyers prefixed-store patch
145
        self._set_new_format(BZR_BRANCH_FORMAT_6)
146
147
148
    def _convert_to_weaves(self):
1381 by Martin Pool
- remove tab characters (only)
149
        note('note: upgrade may be faster if all store files are ungzipped first')
150
        if not os.path.isdir(self.base + '/.bzr/weaves'):
151
            os.mkdir(self.base + '/.bzr/weaves')
1382 by Martin Pool
- upgrade checks if branch is uptodate before anything else
152
        self.inv_weave = Weave('inventory')
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
153
        # holds in-memory weaves for all files
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
154
        self.text_weaves = {}
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
155
        os.remove(self.branch.control_files.controlfilename('branch-format'))
1381 by Martin Pool
- remove tab characters (only)
156
        self._convert_working_inv()
1358 by Martin Pool
- actually upgrade all of history
157
        rev_history = self.branch.revision_history()
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
158
        # to_read is a stack holding the revisions we still need to process;
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
159
        # appending to it adds new highest-priority revisions
1319 by Martin Pool
- calculate and use file parents for importing texts
160
        self.known_revisions = set(rev_history)
1185.20.1 by Andres Salomon
Handle the case where revision_history() returns an empty list during
161
        self.to_read = rev_history[-1:]
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
162
        while self.to_read:
163
            rev_id = self.to_read.pop()
164
            if (rev_id not in self.revisions
165
                and rev_id not in self.absent_revisions):
166
                self._load_one_rev(rev_id)
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
167
        self.pb.clear()
1332 by Martin Pool
- clean up code that writes out weave results
168
        to_import = self._make_order()
1315 by Martin Pool
- import file inventories in correct order
169
        for i, rev_id in enumerate(to_import):
170
            self.pb.update('converting revision', i, len(to_import))
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
171
            self._convert_one_rev(rev_id)
1331 by Martin Pool
- write out new revisions after conversion
172
        self.pb.clear()
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
173
        note('upgraded to weaves:')
174
        note('  %6d revisions and inventories' % len(self.revisions))
1393.1.44 by Martin Pool
- upgrade carries across ghost references
175
        note('  %6d revisions not present' % len(self.absent_revisions))
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
176
        note('  %6d texts' % self.text_count)
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
177
        self._write_all_weaves()
1331 by Martin Pool
- write out new revisions after conversion
178
        self._write_all_revs()
1381 by Martin Pool
- remove tab characters (only)
179
        self._cleanup_spare_files()
1429 by Robert Collins
merge in niemeyers prefixed-store patch
180
        self._set_new_format(BZR_BRANCH_FORMAT_5)
1357 by Martin Pool
- require marker file to do upgrade so as not to clobber something important
181
182
1382 by Martin Pool
- upgrade checks if branch is uptodate before anything else
183
    def _open_branch(self):
1393.1.2 by Martin Pool
- better representation in Branch factories of opening old formats
184
        self.branch = Branch.open_downlevel(self.base)
1429 by Robert Collins
merge in niemeyers prefixed-store patch
185
        self.old_format = self.branch._branch_format
186
        if self.old_format == 6:
187
            note('this branch is in the most current format')
1382 by Martin Pool
- upgrade checks if branch is uptodate before anything else
188
            return False
1429 by Robert Collins
merge in niemeyers prefixed-store patch
189
        if self.old_format not in (4, 5):
1382 by Martin Pool
- upgrade checks if branch is uptodate before anything else
190
            raise BzrError("cannot upgrade from branch format %r" %
191
                           self.branch._branch_format)
192
        return True
193
1429 by Robert Collins
merge in niemeyers prefixed-store patch
194
    def _set_new_format(self, format):
1185.65.12 by Robert Collins
Remove the only-used-once put_controlfiles, and change put_controlfile to put and put_utf8.
195
        self.branch.control_files.put_utf8('branch-format', format)
1355 by Martin Pool
- write working inventory into final location
196
197
    def _cleanup_spare_files(self):
1381 by Martin Pool
- remove tab characters (only)
198
        for n in 'merged-patches', 'pending-merged-patches':
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
199
            p = self.branch.control_files.controlfilename(n)
1381 by Martin Pool
- remove tab characters (only)
200
            if not os.path.exists(p):
201
                continue
202
            ## assert os.path.getsize(p) == 0
203
            os.remove(p)
204
        shutil.rmtree(self.base + '/.bzr/inventory-store')
205
        shutil.rmtree(self.base + '/.bzr/text-store')
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
206
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
207
    def _backup_control_dir(self):
1377 by Martin Pool
- run conversion to weaves from the 'bzr upgrade' command
208
        orig = self.base + '/.bzr'
209
        backup = orig + '.backup'
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
210
        note('making backup of tree history')
1381 by Martin Pool
- remove tab characters (only)
211
        shutil.copytree(orig, backup)
212
        note('%s has been backed up to %s', orig, backup)
213
        note('if conversion fails, you can move this directory back to .bzr')
214
        note('if it succeeds, you can remove this directory if you wish')
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
215
216
    def _convert_working_inv(self):
1381 by Martin Pool
- remove tab characters (only)
217
        branch = self.branch
1185.65.29 by Robert Collins
Implement final review suggestions.
218
        inv = serializer_v4.read_inventory(branch.control_files.get('inventory'))
1393.1.18 by Martin Pool
- fix upgrade for transport changes
219
        new_inv_xml = serializer_v5.write_inventory_to_string(inv)
1185.65.29 by Robert Collins
Implement final review suggestions.
220
        branch.control_files.put('inventory', new_inv_xml)
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
221
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
222
    def _write_all_weaves(self):
1377 by Martin Pool
- run conversion to weaves from the 'bzr upgrade' command
223
        write_a_weave(self.inv_weave, self.base + '/.bzr/inventory.weave')
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
224
        i = 0
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
225
        try:
226
            for file_id, file_weave in self.text_weaves.items():
227
                self.pb.update('writing weave', i, len(self.text_weaves))
1377 by Martin Pool
- run conversion to weaves from the 'bzr upgrade' command
228
                write_a_weave(file_weave, self.base + '/.bzr/weaves/%s.weave' % file_id)
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
229
                i += 1
230
        finally:
231
            self.pb.clear()
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
232
1331 by Martin Pool
- write out new revisions after conversion
233
234
    def _write_all_revs(self):
235
        """Write all revisions out in new form."""
1381 by Martin Pool
- remove tab characters (only)
236
        shutil.rmtree(self.base + '/.bzr/revision-store')
237
        os.mkdir(self.base + '/.bzr/revision-store')
1331 by Martin Pool
- write out new revisions after conversion
238
        try:
239
            for i, rev_id in enumerate(self.converted_revs):
240
                self.pb.update('write revision', i, len(self.converted_revs))
1377 by Martin Pool
- run conversion to weaves from the 'bzr upgrade' command
241
                f = file(self.base + '/.bzr/revision-store/%s' % rev_id, 'wb')
1331 by Martin Pool
- write out new revisions after conversion
242
                try:
243
                    serializer_v5.write_revision(self.revisions[rev_id], f)
244
                finally:
245
                    f.close()
246
        finally:
247
            self.pb.clear()
1332 by Martin Pool
- clean up code that writes out weave results
248
1331 by Martin Pool
- write out new revisions after conversion
249
            
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
250
    def _load_one_rev(self, rev_id):
251
        """Load a revision object into memory.
252
253
        Any parents not either loaded or abandoned get queued to be
254
        loaded."""
255
        self.pb.update('loading revision',
1315 by Martin Pool
- import file inventories in correct order
256
                       len(self.revisions),
1319 by Martin Pool
- calculate and use file parents for importing texts
257
                       len(self.known_revisions))
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
258
        if not self.branch.repository.revision_store.has_id(rev_id):
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
259
            self.pb.clear()
260
            note('revision {%s} not present in branch; '
1393.1.44 by Martin Pool
- upgrade carries across ghost references
261
                 'will be converted as a ghost',
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
262
                 rev_id)
263
            self.absent_revisions.add(rev_id)
264
        else:
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
265
            rev_xml = self.branch.repository.revision_store.get(rev_id).read()
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
266
            rev = serializer_v4.read_revision_from_string(rev_xml)
1313 by Martin Pool
- rename to Revision.parent_ids to avoid confusion with old usage
267
            for parent_id in rev.parent_ids:
1319 by Martin Pool
- calculate and use file parents for importing texts
268
                self.known_revisions.add(parent_id)
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
269
                self.to_read.append(parent_id)
270
            self.revisions[rev_id] = rev
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
271
272
273
    def _load_old_inventory(self, rev_id):
274
        assert rev_id not in self.converted_revs
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
275
        old_inv_xml = self.branch.repository.inventory_store.get(rev_id).read()
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
276
        inv = serializer_v4.read_inventory_from_string(old_inv_xml)
277
        rev = self.revisions[rev_id]
278
        if rev.inventory_sha1:
279
            assert rev.inventory_sha1 == sha_string(old_inv_xml), \
280
                'inventory sha mismatch for {%s}' % rev_id
281
        return inv
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
282
        
283
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
284
    def _load_updated_inventory(self, rev_id):
285
        assert rev_id in self.converted_revs
286
        inv_xml = self.inv_weave.get_text(rev_id)
287
        inv = serializer_v5.read_inventory_from_string(inv_xml)
288
        return inv
289
290
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
291
    def _convert_one_rev(self, rev_id):
292
        """Convert revision and all referenced objects to new format."""
293
        rev = self.revisions[rev_id]
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
294
        inv = self._load_old_inventory(rev_id)
1393.1.44 by Martin Pool
- upgrade carries across ghost references
295
        present_parents = [p for p in rev.parent_ids
296
                           if p not in self.absent_revisions]
297
        self._convert_revision_contents(rev, inv, present_parents)
298
        self._store_new_weave(rev, inv, present_parents)
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
299
        self.converted_revs.add(rev_id)
300
301
1393.1.44 by Martin Pool
- upgrade carries across ghost references
302
    def _store_new_weave(self, rev, inv, present_parents):
1320 by Martin Pool
- write updated inventory into weave
303
        # the XML is now updated with text versions
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
304
        if __debug__:
305
            for file_id in inv:
306
                ie = inv[file_id]
307
                if ie.kind == 'root_directory':
308
                    continue
1092.2.21 by Robert Collins
convert name_version to revision in inventory entries
309
                assert hasattr(ie, 'revision'), \
310
                    'no revision on {%s} in {%s}' % \
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
311
                    (file_id, rev.revision_id)
1316 by Martin Pool
- upgrade format of inventories as they're converted
312
        new_inv_xml = serializer_v5.write_inventory_to_string(inv)
1325 by Martin Pool
- conversion to weave tries to avoid repeated SHA calculation
313
        new_inv_sha1 = sha_string(new_inv_xml)
1393.1.44 by Martin Pool
- upgrade carries across ghost references
314
        self.inv_weave.add(rev.revision_id, 
315
                           present_parents,
1325 by Martin Pool
- conversion to weave tries to avoid repeated SHA calculation
316
                           new_inv_xml.splitlines(True),
317
                           new_inv_sha1)
318
        rev.inventory_sha1 = new_inv_sha1
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
319
1393.1.44 by Martin Pool
- upgrade carries across ghost references
320
    def _convert_revision_contents(self, rev, inv, present_parents):
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
321
        """Convert all the files within a revision.
322
323
        Also upgrade the inventory to refer to the text revision ids."""
324
        rev_id = rev.revision_id
1319 by Martin Pool
- calculate and use file parents for importing texts
325
        mutter('converting texts of revision {%s}',
326
               rev_id)
1393.1.44 by Martin Pool
- upgrade carries across ghost references
327
        parent_invs = map(self._load_updated_inventory, present_parents)
1332 by Martin Pool
- clean up code that writes out weave results
328
        for file_id in inv:
329
            ie = inv[file_id]
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
330
            self._convert_file_version(rev, ie, parent_invs)
331
332
    def _convert_file_version(self, rev, ie, parent_invs):
1319 by Martin Pool
- calculate and use file parents for importing texts
333
        """Convert one version of one file.
334
335
        The file needs to be added into the weave if it is a merge
336
        of >=2 parents or if it's changed from its parent.
337
        """
1405 by Robert Collins
remove some of the upgrade code that was duplicated with inventory_entry, and give all inventory entries a weave
338
        if ie.kind == 'root_directory':
339
            return
1319 by Martin Pool
- calculate and use file parents for importing texts
340
        file_id = ie.file_id
341
        rev_id = rev.revision_id
342
        w = self.text_weaves.get(file_id)
343
        if w is None:
344
            w = Weave(file_id)
345
            self.text_weaves[file_id] = w
346
        text_changed = False
1411 by Robert Collins
use weave ancestry to determine inventory entry previous heads, prevent propogating 'I did a merge' merges.
347
        previous_entries = ie.find_previous_heads(parent_invs, w)
1409 by Robert Collins
unify previous inventory entry parent logic in preparation for fixing the revision-thrashing bug
348
        for old_revision in previous_entries:
1092.2.22 by Robert Collins
text_version and name_version unification looking reasonable
349
                # if this fails, its a ghost ?
350
                assert old_revision in self.converted_revs 
1409 by Robert Collins
unify previous inventory entry parent logic in preparation for fixing the revision-thrashing bug
351
        self.snapshot_ie(previous_entries, ie, w, rev_id)
1405 by Robert Collins
remove some of the upgrade code that was duplicated with inventory_entry, and give all inventory entries a weave
352
        del ie.text_id
353
        assert getattr(ie, 'revision', None) is not None
354
355
    def snapshot_ie(self, previous_revisions, ie, w, rev_id):
356
        # TODO: convert this logic, which is ~= snapshot to
357
        # a call to:. This needs the path figured out. rather than a work_tree
1409 by Robert Collins
unify previous inventory entry parent logic in preparation for fixing the revision-thrashing bug
358
        # a v4 revision_tree can be given, or something that looks enough like
359
        # one to give the file content to the entry if it needs it.
1405 by Robert Collins
remove some of the upgrade code that was duplicated with inventory_entry, and give all inventory entries a weave
360
        # and we need something that looks like a weave store for snapshot to 
361
        # save against.
362
        #ie.snapshot(rev, PATH, previous_revisions, REVISION_TREE, InMemoryWeaveStore(self.text_weaves))
363
        if len(previous_revisions) == 1:
364
            previous_ie = previous_revisions.values()[0]
365
            if ie._unchanged(previous_ie):
366
                ie.revision = previous_ie.revision
367
                return
368
        parent_indexes = map(w.lookup, previous_revisions)
369
        if ie.has_text():
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
370
            text = self.branch.repository.text_store.get(ie.text_id)
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
371
            file_lines = text.readlines()
1378 by Martin Pool
- in upgrade, avoiding loading file texts unless necessary
372
            assert sha_strings(file_lines) == ie.text_sha1
373
            assert sum(map(len, file_lines)) == ie.text_size
1405 by Robert Collins
remove some of the upgrade code that was duplicated with inventory_entry, and give all inventory entries a weave
374
            w.add(rev_id, parent_indexes, file_lines, ie.text_sha1)
1332 by Martin Pool
- clean up code that writes out weave results
375
            self.text_count += 1
1319 by Martin Pool
- calculate and use file parents for importing texts
376
        else:
1405 by Robert Collins
remove some of the upgrade code that was duplicated with inventory_entry, and give all inventory entries a weave
377
            w.add(rev_id, parent_indexes, [], None)
378
        ie.revision = rev_id
379
        ##mutter('import text {%s} of {%s}',
380
        ##       ie.text_id, file_id)
1310 by Martin Pool
- compute order to import revisions
381
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
382
    def _make_order(self):
1310 by Martin Pool
- compute order to import revisions
383
        """Return a suitable order for importing revisions.
384
385
        The order must be such that an revision is imported after all
386
        its (present) parents.
387
        """
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
388
        todo = set(self.revisions.keys())
389
        done = self.absent_revisions.copy()
1310 by Martin Pool
- compute order to import revisions
390
        o = []
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
391
        while todo:
392
            # scan through looking for a revision whose parents
393
            # are all done
1310 by Martin Pool
- compute order to import revisions
394
            for rev_id in sorted(list(todo)):
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
395
                rev = self.revisions[rev_id]
1313 by Martin Pool
- rename to Revision.parent_ids to avoid confusion with old usage
396
                parent_ids = set(rev.parent_ids)
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
397
                if parent_ids.issubset(done):
398
                    # can take this one now
1310 by Martin Pool
- compute order to import revisions
399
                    o.append(rev_id)
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
400
                    todo.remove(rev_id)
401
                    done.add(rev_id)
1315 by Martin Pool
- import file inventories in correct order
402
        return o
1377 by Martin Pool
- run conversion to weaves from the 'bzr upgrade' command
403
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
404
1332 by Martin Pool
- clean up code that writes out weave results
405
def write_a_weave(weave, filename):
406
    inv_wf = file(filename, 'wb')
1080 by Martin Pool
- test tool for converting history to weave files
407
    try:
1087 by Martin Pool
- add a tool script to convert past history into weaves
408
        write_weave(weave, inv_wf)
1080 by Martin Pool
- test tool for converting history to weave files
409
    finally:
410
        inv_wf.close()
411
1377 by Martin Pool
- run conversion to weaves from the 'bzr upgrade' command
412
413
def upgrade(base_dir):
414
    Convert(base_dir)