/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
1534.4.34 by Robert Collins
Fix remaining uses of deprecated apis within bzrlib.
17
"""bzr upgrade logic."""
18
19
# change upgrade from .bzr to create a '.bzr-new', then do a bait and switch.
20
1080 by Martin Pool
- test tool for converting history to weave files
21
1267 by Martin Pool
- notes on conversion of existing history to weaves
22
# To make this properly useful
23
#
24
# 1. assign text version ids, and put those text versions into
25
#    the inventory as they're converted.
26
#
27
# 2. keep track of the previous version of each file, rather than
28
#    just using the last one imported
29
#
30
# 3. assign entry versions when files are added, renamed or moved.
31
#
32
# 4. when merged-in versions are observed, walk down through them
33
#    to discover everything, then commit bottom-up
34
#
35
# 5. track ancestry as things are merged in, and commit that in each
36
#    revision
37
#
38
# Perhaps it's best to first walk the whole graph and make a plan for
39
# what should be imported in what order?  Need a kind of topological
40
# sort of all revisions.  (Or do we, can we just before doing a revision
41
# see that all its parents have either been converted or abandoned?)
42
1315 by Martin Pool
- import file inventories in correct order
43
44
# Cannot import a revision until all its parents have been
45
# imported.  in other words, we can only import revisions whose
46
# parents have all been imported.  the first step must be to
47
# import a revision with no parents, of which there must be at
48
# least one.  (So perhaps it's useful to store forward pointers
49
# from a list of parents to their children?)
50
#
51
# Another (equivalent?) approach is to build up the ordered
52
# ancestry list for the last revision, and walk through that.  We
53
# are going to need that.
54
#
55
# We don't want to have to recurse all the way back down the list.
56
#
57
# Suppose we keep a queue of the revisions able to be processed at
58
# any point.  This starts out with all the revisions having no
59
# parents.
60
#
61
# This seems like a generally useful algorithm...
62
#
63
# The current algorithm is dumb (O(n**2)?) but will do the job, and
64
# takes less than a second on the bzr.dev branch.
65
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
66
# This currently does a kind of lazy conversion of file texts, where a
67
# new text is written in every version.  That's unnecessary but for
68
# the moment saves us having to worry about when files need new
69
# versions.
70
1534.4.16 by Robert Collins
Last vestiges of local file requirements for upgrade nuked
71
from cStringIO import StringIO
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
72
import os
1267 by Martin Pool
- notes on conversion of existing history to weaves
73
import tempfile
74
import sys
1534.4.14 by Robert Collins
Replace copy_tree with transport logic in upgreade.
75
from stat import *
1132 by Martin Pool
- fix up logging for history2weaves tool
76
1534.4.28 by Robert Collins
first cut at merge from integration.
77
import bzrlib
1185.65.29 by Robert Collins
Implement final review suggestions.
78
from bzrlib.branch import Branch
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
79
import bzrlib.bzrdir as bzrdir
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
80
from bzrlib.bzrdir import BzrDirFormat, BzrDirFormat4, BzrDirFormat5, BzrDirFormat6
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
81
import bzrlib.errors as errors
1534.4.16 by Robert Collins
Last vestiges of local file requirements for upgrade nuked
82
from bzrlib.errors import NoSuchFile, UpgradeReadonly
1185.17.1 by Martin Pool
[pick] clear hashcache in format upgrade to avoid worrisome warning
83
import bzrlib.hashcache as hashcache
1534.4.28 by Robert Collins
first cut at merge from integration.
84
from bzrlib.lockable_files import LockableFiles
1534.4.13 by Robert Collins
Give a reasonable warning on attempts to upgrade a readonly url.
85
from bzrlib.osutils import sha_strings, sha_string, pathjoin, abspath
86
from bzrlib.ui import ui_factory
1534.4.16 by Robert Collins
Last vestiges of local file requirements for upgrade nuked
87
from bzrlib.store.text import TextStore
88
from bzrlib.store.weave import WeaveStore
1534.4.13 by Robert Collins
Give a reasonable warning on attempts to upgrade a readonly url.
89
from bzrlib.trace import mutter, note, warning
1534.4.16 by Robert Collins
Last vestiges of local file requirements for upgrade nuked
90
from bzrlib.transactions import PassThroughTransaction
1534.4.13 by Robert Collins
Give a reasonable warning on attempts to upgrade a readonly url.
91
from bzrlib.transport import get_transport
1534.4.16 by Robert Collins
Last vestiges of local file requirements for upgrade nuked
92
from bzrlib.transport.local import LocalTransport
1080 by Martin Pool
- test tool for converting history to weave files
93
from bzrlib.weave import Weave
94
from bzrlib.weavefile import read_weave, write_weave
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
95
from bzrlib.xml4 import serializer_v4
96
from bzrlib.xml5 import serializer_v5
1185.62.12 by John Arbash Meinel
Adding TODO to upgrade.py to remove ancestry.weave
97
98
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
99
class Convert(object):
1534.4.13 by Robert Collins
Give a reasonable warning on attempts to upgrade a readonly url.
100
101
    def __init__(self, transport):
102
        self.base = transport.base
1307 by Martin Pool
- start walking through ancestors in conversion to weaves
103
        self.converted_revs = set()
104
        self.absent_revisions = set()
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
105
        self.text_count = 0
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
106
        self.revisions = {}
1534.4.13 by Robert Collins
Give a reasonable warning on attempts to upgrade a readonly url.
107
        self.transport = transport
108
        if self.transport.is_readonly():
109
            raise UpgradeReadonly
1534.4.28 by Robert Collins
first cut at merge from integration.
110
        self.control_files = LockableFiles(transport.clone(bzrlib.BZRDIR), 'branch-lock')
111
        # Lock the branch (soon to be meta dir) to prevent anyone racing with us
112
        # This is currently windows incompatible, it will deadlock. When the upgrade
113
        # logic becomes format specific, then we can have the format know how to pass this
114
        # on. Also note that we probably have an 'upgrade meta' which upgrades the constituent
115
        # parts.
116
        print "FIXME: control files reuse" 
117
        self.control_files.lock_write()
118
        try:
119
            self.convert()
120
        finally:
121
            self.control_files.unlock()
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
122
123
    def convert(self):
1382 by Martin Pool
- upgrade checks if branch is uptodate before anything else
124
        if not self._open_branch():
125
            return
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
126
        note('starting upgrade of %s', self.base)
1381 by Martin Pool
- remove tab characters (only)
127
        self._backup_control_dir()
1429 by Robert Collins
merge in niemeyers prefixed-store patch
128
        self.pb = ui_factory.progress_bar()
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
129
        if isinstance(self.old_format, BzrDirFormat4):
1429 by Robert Collins
merge in niemeyers prefixed-store patch
130
            note('starting upgrade from format 4 to 5')
131
            self._convert_to_weaves()
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
132
        if isinstance(self.old_format, BzrDirFormat5):
1429 by Robert Collins
merge in niemeyers prefixed-store patch
133
            note('starting upgrade from format 5 to 6')
134
            self._convert_to_prefixed()
1534.4.16 by Robert Collins
Last vestiges of local file requirements for upgrade nuked
135
        if isinstance(self.transport, LocalTransport):
136
            cache = hashcache.HashCache(abspath(self.base))
137
            cache.clear()
138
            cache.write()
1429 by Robert Collins
merge in niemeyers prefixed-store patch
139
        note("finished")
140
141
    def _convert_to_prefixed(self):
142
        from bzrlib.store import hash_prefix
1534.4.16 by Robert Collins
Last vestiges of local file requirements for upgrade nuked
143
        bzr_transport = self.transport.clone('.bzr')
144
        bzr_transport.delete('branch-format')
1429 by Robert Collins
merge in niemeyers prefixed-store patch
145
        for store_name in ["weaves", "revision-store"]:
146
            note("adding prefixes to %s" % store_name) 
1534.4.16 by Robert Collins
Last vestiges of local file requirements for upgrade nuked
147
            store_transport = bzr_transport.clone(store_name)
148
            for filename in store_transport.list_dir('.'):
1534.4.30 by Robert Collins
Test signature preservation on clone and upgrade.
149
                if (filename.endswith(".weave") or
150
                    filename.endswith(".gz") or
151
                    filename.endswith(".sig")):
1429 by Robert Collins
merge in niemeyers prefixed-store patch
152
                    file_id = os.path.splitext(filename)[0]
153
                else:
154
                    file_id = filename
1534.4.16 by Robert Collins
Last vestiges of local file requirements for upgrade nuked
155
                prefix_dir = hash_prefix(file_id)
156
                # FIXME keep track of the dirs made RBC 20060121
157
                try:
158
                    store_transport.move(filename, prefix_dir + '/' + filename)
159
                except NoSuchFile: # catches missing dirs strangely enough
160
                    store_transport.mkdir(prefix_dir)
161
                    store_transport.move(filename, prefix_dir + '/' + filename)
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
162
        self.old_format = BzrDirFormat6()
163
        self._set_new_format(self.old_format.get_format_string())
164
        self.bzrdir = self.old_format.open(self.transport)
165
        self.branch = self.bzrdir.open_branch()
1429 by Robert Collins
merge in niemeyers prefixed-store patch
166
167
    def _convert_to_weaves(self):
1381 by Martin Pool
- remove tab characters (only)
168
        note('note: upgrade may be faster if all store files are ungzipped first')
1534.4.16 by Robert Collins
Last vestiges of local file requirements for upgrade nuked
169
        bzr_transport = self.transport.clone('.bzr')
170
        try:
171
            # TODO permissions
172
            stat = bzr_transport.stat('weaves')
173
            if not S_ISDIR(stat.st_mode):
174
                bzr_transport.delete('weaves')
175
                bzr_transport.mkdir('weaves')
176
        except NoSuchFile:
177
            bzr_transport.mkdir('weaves')
1382 by Martin Pool
- upgrade checks if branch is uptodate before anything else
178
        self.inv_weave = Weave('inventory')
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
179
        # holds in-memory weaves for all files
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
180
        self.text_weaves = {}
1534.4.16 by Robert Collins
Last vestiges of local file requirements for upgrade nuked
181
        bzr_transport.delete('branch-format')
1381 by Martin Pool
- remove tab characters (only)
182
        self._convert_working_inv()
1358 by Martin Pool
- actually upgrade all of history
183
        rev_history = self.branch.revision_history()
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
184
        # to_read is a stack holding the revisions we still need to process;
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
185
        # appending to it adds new highest-priority revisions
1319 by Martin Pool
- calculate and use file parents for importing texts
186
        self.known_revisions = set(rev_history)
1185.20.1 by Andres Salomon
Handle the case where revision_history() returns an empty list during
187
        self.to_read = rev_history[-1:]
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
188
        while self.to_read:
189
            rev_id = self.to_read.pop()
190
            if (rev_id not in self.revisions
191
                and rev_id not in self.absent_revisions):
192
                self._load_one_rev(rev_id)
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
193
        self.pb.clear()
1332 by Martin Pool
- clean up code that writes out weave results
194
        to_import = self._make_order()
1315 by Martin Pool
- import file inventories in correct order
195
        for i, rev_id in enumerate(to_import):
196
            self.pb.update('converting revision', i, len(to_import))
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
197
            self._convert_one_rev(rev_id)
1331 by Martin Pool
- write out new revisions after conversion
198
        self.pb.clear()
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
199
        self._write_all_weaves()
200
        self._write_all_revs()
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
201
        note('upgraded to weaves:')
202
        note('  %6d revisions and inventories' % len(self.revisions))
1393.1.44 by Martin Pool
- upgrade carries across ghost references
203
        note('  %6d revisions not present' % len(self.absent_revisions))
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
204
        note('  %6d texts' % self.text_count)
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
205
        self._cleanup_spare_files_after_format4()
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
206
        self.old_format = BzrDirFormat5()
207
        self._set_new_format(self.old_format.get_format_string())
208
        self.bzrdir = self.old_format.open(self.transport)
209
        self.branch = self.bzrdir.open_branch()
1357 by Martin Pool
- require marker file to do upgrade so as not to clobber something important
210
1382 by Martin Pool
- upgrade checks if branch is uptodate before anything else
211
    def _open_branch(self):
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
212
        self.old_format = BzrDirFormat.find_format(self.transport)
213
        self.bzrdir = self.old_format.open(self.transport)
214
        self.branch = self.bzrdir.open_branch()
215
        if isinstance(self.old_format, BzrDirFormat6):
1534.4.8 by Robert Collins
Unfuck upgrade.
216
            note('this branch is in the most current format (%s)', self.old_format)
1382 by Martin Pool
- upgrade checks if branch is uptodate before anything else
217
            return False
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
218
        if (not isinstance(self.old_format, BzrDirFormat4) and
1534.4.44 by Robert Collins
Make a new BzrDir format that uses a versioned branch format in a branch/ subdirectory.
219
            not isinstance(self.old_format, BzrDirFormat5) and
220
            not isinstance(self.old_format, bzrdir.BzrDirMetaFormat1)):
221
            raise errors.BzrError("cannot upgrade from branch format %s" %
1382 by Martin Pool
- upgrade checks if branch is uptodate before anything else
222
                           self.branch._branch_format)
223
        return True
224
1429 by Robert Collins
merge in niemeyers prefixed-store patch
225
    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.
226
        self.branch.control_files.put_utf8('branch-format', format)
1355 by Martin Pool
- write working inventory into final location
227
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
228
    def _cleanup_spare_files_after_format4(self):
229
        transport = self.transport.clone('.bzr')
1534.4.28 by Robert Collins
first cut at merge from integration.
230
        print "FIXME working tree upgrade foo."
1381 by Martin Pool
- remove tab characters (only)
231
        for n in 'merged-patches', 'pending-merged-patches':
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
232
            try:
233
                ## assert os.path.getsize(p) == 0
234
                transport.delete(n)
235
            except NoSuchFile:
236
                pass
237
        transport.delete_tree('inventory-store')
238
        transport.delete_tree('text-store')
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
239
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
240
    def _backup_control_dir(self):
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
241
        note('making backup of tree history')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
242
        self.transport.copy_tree('.bzr', '.bzr.backup')
243
        note('%s.bzr has been backed up to %s.bzr.backup',
244
             self.transport.base,
245
             self.transport.base)
1381 by Martin Pool
- remove tab characters (only)
246
        note('if conversion fails, you can move this directory back to .bzr')
247
        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
248
249
    def _convert_working_inv(self):
1381 by Martin Pool
- remove tab characters (only)
250
        branch = self.branch
1185.65.29 by Robert Collins
Implement final review suggestions.
251
        inv = serializer_v4.read_inventory(branch.control_files.get('inventory'))
1393.1.18 by Martin Pool
- fix upgrade for transport changes
252
        new_inv_xml = serializer_v5.write_inventory_to_string(inv)
1534.4.28 by Robert Collins
first cut at merge from integration.
253
        print "fixme inventory is a working tree change."
1185.65.29 by Robert Collins
Implement final review suggestions.
254
        branch.control_files.put('inventory', new_inv_xml)
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
255
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
256
    def _write_all_weaves(self):
1534.4.16 by Robert Collins
Last vestiges of local file requirements for upgrade nuked
257
        bzr_transport = self.transport.clone('.bzr')
258
        controlweaves = WeaveStore(bzr_transport, prefixed=False)
259
        weave_transport = bzr_transport.clone('weaves')
260
        weaves = WeaveStore(weave_transport, prefixed=False)
261
        transaction = PassThroughTransaction()
262
263
        controlweaves.put_weave('inventory', self.inv_weave, transaction)
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
264
        i = 0
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
265
        try:
266
            for file_id, file_weave in self.text_weaves.items():
267
                self.pb.update('writing weave', i, len(self.text_weaves))
1534.4.16 by Robert Collins
Last vestiges of local file requirements for upgrade nuked
268
                weaves.put_weave(file_id, file_weave, transaction)
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
269
                i += 1
270
        finally:
271
            self.pb.clear()
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
272
1331 by Martin Pool
- write out new revisions after conversion
273
    def _write_all_revs(self):
274
        """Write all revisions out in new form."""
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
275
        transport = self.transport.clone('.bzr')
276
        transport.delete_tree('revision-store')
277
        transport.mkdir('revision-store')
1534.4.16 by Robert Collins
Last vestiges of local file requirements for upgrade nuked
278
        revision_transport = transport.clone('revision-store')
279
        # TODO permissions
280
        revision_store = TextStore(revision_transport,
281
                                   prefixed=False,
282
                                   compressed=True)
1331 by Martin Pool
- write out new revisions after conversion
283
        try:
284
            for i, rev_id in enumerate(self.converted_revs):
285
                self.pb.update('write revision', i, len(self.converted_revs))
1534.4.16 by Robert Collins
Last vestiges of local file requirements for upgrade nuked
286
                rev_tmp = StringIO()
287
                serializer_v5.write_revision(self.revisions[rev_id], rev_tmp)
288
                rev_tmp.seek(0)
289
                revision_store.add(rev_tmp, rev_id)
1331 by Martin Pool
- write out new revisions after conversion
290
        finally:
291
            self.pb.clear()
1332 by Martin Pool
- clean up code that writes out weave results
292
1331 by Martin Pool
- write out new revisions after conversion
293
            
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
294
    def _load_one_rev(self, rev_id):
295
        """Load a revision object into memory.
296
297
        Any parents not either loaded or abandoned get queued to be
298
        loaded."""
299
        self.pb.update('loading revision',
1315 by Martin Pool
- import file inventories in correct order
300
                       len(self.revisions),
1319 by Martin Pool
- calculate and use file parents for importing texts
301
                       len(self.known_revisions))
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
302
        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
303
            self.pb.clear()
304
            note('revision {%s} not present in branch; '
1393.1.44 by Martin Pool
- upgrade carries across ghost references
305
                 'will be converted as a ghost',
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
306
                 rev_id)
307
            self.absent_revisions.add(rev_id)
308
        else:
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
309
            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
310
            rev = serializer_v4.read_revision_from_string(rev_xml)
1313 by Martin Pool
- rename to Revision.parent_ids to avoid confusion with old usage
311
            for parent_id in rev.parent_ids:
1319 by Martin Pool
- calculate and use file parents for importing texts
312
                self.known_revisions.add(parent_id)
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
313
                self.to_read.append(parent_id)
314
            self.revisions[rev_id] = rev
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
315
316
317
    def _load_old_inventory(self, rev_id):
318
        assert rev_id not in self.converted_revs
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
319
        old_inv_xml = self.branch.repository.inventory_store.get(rev_id).read()
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
320
        inv = serializer_v4.read_inventory_from_string(old_inv_xml)
321
        rev = self.revisions[rev_id]
322
        if rev.inventory_sha1:
323
            assert rev.inventory_sha1 == sha_string(old_inv_xml), \
324
                'inventory sha mismatch for {%s}' % rev_id
325
        return inv
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
326
        
327
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
328
    def _load_updated_inventory(self, rev_id):
329
        assert rev_id in self.converted_revs
330
        inv_xml = self.inv_weave.get_text(rev_id)
331
        inv = serializer_v5.read_inventory_from_string(inv_xml)
332
        return inv
333
334
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
335
    def _convert_one_rev(self, rev_id):
336
        """Convert revision and all referenced objects to new format."""
337
        rev = self.revisions[rev_id]
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
338
        inv = self._load_old_inventory(rev_id)
1393.1.44 by Martin Pool
- upgrade carries across ghost references
339
        present_parents = [p for p in rev.parent_ids
340
                           if p not in self.absent_revisions]
341
        self._convert_revision_contents(rev, inv, present_parents)
342
        self._store_new_weave(rev, inv, present_parents)
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
343
        self.converted_revs.add(rev_id)
344
345
1393.1.44 by Martin Pool
- upgrade carries across ghost references
346
    def _store_new_weave(self, rev, inv, present_parents):
1320 by Martin Pool
- write updated inventory into weave
347
        # the XML is now updated with text versions
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
348
        if __debug__:
349
            for file_id in inv:
350
                ie = inv[file_id]
351
                if ie.kind == 'root_directory':
352
                    continue
1092.2.21 by Robert Collins
convert name_version to revision in inventory entries
353
                assert hasattr(ie, 'revision'), \
354
                    'no revision on {%s} in {%s}' % \
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
355
                    (file_id, rev.revision_id)
1316 by Martin Pool
- upgrade format of inventories as they're converted
356
        new_inv_xml = serializer_v5.write_inventory_to_string(inv)
1325 by Martin Pool
- conversion to weave tries to avoid repeated SHA calculation
357
        new_inv_sha1 = sha_string(new_inv_xml)
1393.1.44 by Martin Pool
- upgrade carries across ghost references
358
        self.inv_weave.add(rev.revision_id, 
359
                           present_parents,
1325 by Martin Pool
- conversion to weave tries to avoid repeated SHA calculation
360
                           new_inv_xml.splitlines(True),
361
                           new_inv_sha1)
362
        rev.inventory_sha1 = new_inv_sha1
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
363
1393.1.44 by Martin Pool
- upgrade carries across ghost references
364
    def _convert_revision_contents(self, rev, inv, present_parents):
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
365
        """Convert all the files within a revision.
366
367
        Also upgrade the inventory to refer to the text revision ids."""
368
        rev_id = rev.revision_id
1319 by Martin Pool
- calculate and use file parents for importing texts
369
        mutter('converting texts of revision {%s}',
370
               rev_id)
1393.1.44 by Martin Pool
- upgrade carries across ghost references
371
        parent_invs = map(self._load_updated_inventory, present_parents)
1332 by Martin Pool
- clean up code that writes out weave results
372
        for file_id in inv:
373
            ie = inv[file_id]
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
374
            self._convert_file_version(rev, ie, parent_invs)
375
376
    def _convert_file_version(self, rev, ie, parent_invs):
1319 by Martin Pool
- calculate and use file parents for importing texts
377
        """Convert one version of one file.
378
379
        The file needs to be added into the weave if it is a merge
380
        of >=2 parents or if it's changed from its parent.
381
        """
1405 by Robert Collins
remove some of the upgrade code that was duplicated with inventory_entry, and give all inventory entries a weave
382
        if ie.kind == 'root_directory':
383
            return
1319 by Martin Pool
- calculate and use file parents for importing texts
384
        file_id = ie.file_id
385
        rev_id = rev.revision_id
386
        w = self.text_weaves.get(file_id)
387
        if w is None:
388
            w = Weave(file_id)
389
            self.text_weaves[file_id] = w
390
        text_changed = False
1411 by Robert Collins
use weave ancestry to determine inventory entry previous heads, prevent propogating 'I did a merge' merges.
391
        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
392
        for old_revision in previous_entries:
1092.2.22 by Robert Collins
text_version and name_version unification looking reasonable
393
                # if this fails, its a ghost ?
394
                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
395
        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
396
        del ie.text_id
397
        assert getattr(ie, 'revision', None) is not None
398
399
    def snapshot_ie(self, previous_revisions, ie, w, rev_id):
400
        # TODO: convert this logic, which is ~= snapshot to
401
        # 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
402
        # a v4 revision_tree can be given, or something that looks enough like
403
        # 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
404
        # and we need something that looks like a weave store for snapshot to 
405
        # save against.
406
        #ie.snapshot(rev, PATH, previous_revisions, REVISION_TREE, InMemoryWeaveStore(self.text_weaves))
407
        if len(previous_revisions) == 1:
408
            previous_ie = previous_revisions.values()[0]
409
            if ie._unchanged(previous_ie):
410
                ie.revision = previous_ie.revision
411
                return
412
        parent_indexes = map(w.lookup, previous_revisions)
413
        if ie.has_text():
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
414
            text = self.branch.repository.text_store.get(ie.text_id)
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
415
            file_lines = text.readlines()
1378 by Martin Pool
- in upgrade, avoiding loading file texts unless necessary
416
            assert sha_strings(file_lines) == ie.text_sha1
417
            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
418
            w.add(rev_id, parent_indexes, file_lines, ie.text_sha1)
1332 by Martin Pool
- clean up code that writes out weave results
419
            self.text_count += 1
1319 by Martin Pool
- calculate and use file parents for importing texts
420
        else:
1405 by Robert Collins
remove some of the upgrade code that was duplicated with inventory_entry, and give all inventory entries a weave
421
            w.add(rev_id, parent_indexes, [], None)
422
        ie.revision = rev_id
423
        ##mutter('import text {%s} of {%s}',
424
        ##       ie.text_id, file_id)
1310 by Martin Pool
- compute order to import revisions
425
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
426
    def _make_order(self):
1310 by Martin Pool
- compute order to import revisions
427
        """Return a suitable order for importing revisions.
428
429
        The order must be such that an revision is imported after all
430
        its (present) parents.
431
        """
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
432
        todo = set(self.revisions.keys())
433
        done = self.absent_revisions.copy()
1310 by Martin Pool
- compute order to import revisions
434
        o = []
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
435
        while todo:
436
            # scan through looking for a revision whose parents
437
            # are all done
1310 by Martin Pool
- compute order to import revisions
438
            for rev_id in sorted(list(todo)):
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
439
                rev = self.revisions[rev_id]
1313 by Martin Pool
- rename to Revision.parent_ids to avoid confusion with old usage
440
                parent_ids = set(rev.parent_ids)
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
441
                if parent_ids.issubset(done):
442
                    # can take this one now
1310 by Martin Pool
- compute order to import revisions
443
                    o.append(rev_id)
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
444
                    todo.remove(rev_id)
445
                    done.add(rev_id)
1315 by Martin Pool
- import file inventories in correct order
446
        return o
1377 by Martin Pool
- run conversion to weaves from the 'bzr upgrade' command
447
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
448
1534.4.13 by Robert Collins
Give a reasonable warning on attempts to upgrade a readonly url.
449
def upgrade(url):
450
    t = get_transport(url)
451
    Convert(t)