/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.
1551.2.5 by Aaron Bentley
Removed more selftest spam [recommit]
116
        # FIXME: control files reuse
1534.4.28 by Robert Collins
first cut at merge from integration.
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')
1534.4.51 by Robert Collins
Test the disk layout of format3 working trees.
131
            if isinstance(self.transport, LocalTransport):
132
                self.bzrdir.get_workingtree_transport(None).delete('stat-cache')
1429 by Robert Collins
merge in niemeyers prefixed-store patch
133
            self._convert_to_weaves()
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
134
        if isinstance(self.old_format, BzrDirFormat5):
1429 by Robert Collins
merge in niemeyers prefixed-store patch
135
            note('starting upgrade from format 5 to 6')
136
            self._convert_to_prefixed()
137
        note("finished")
138
139
    def _convert_to_prefixed(self):
140
        from bzrlib.store import hash_prefix
1534.4.16 by Robert Collins
Last vestiges of local file requirements for upgrade nuked
141
        bzr_transport = self.transport.clone('.bzr')
142
        bzr_transport.delete('branch-format')
1429 by Robert Collins
merge in niemeyers prefixed-store patch
143
        for store_name in ["weaves", "revision-store"]:
144
            note("adding prefixes to %s" % store_name) 
1534.4.16 by Robert Collins
Last vestiges of local file requirements for upgrade nuked
145
            store_transport = bzr_transport.clone(store_name)
146
            for filename in store_transport.list_dir('.'):
1534.4.30 by Robert Collins
Test signature preservation on clone and upgrade.
147
                if (filename.endswith(".weave") or
148
                    filename.endswith(".gz") or
149
                    filename.endswith(".sig")):
1429 by Robert Collins
merge in niemeyers prefixed-store patch
150
                    file_id = os.path.splitext(filename)[0]
151
                else:
152
                    file_id = filename
1534.4.16 by Robert Collins
Last vestiges of local file requirements for upgrade nuked
153
                prefix_dir = hash_prefix(file_id)
154
                # FIXME keep track of the dirs made RBC 20060121
155
                try:
156
                    store_transport.move(filename, prefix_dir + '/' + filename)
157
                except NoSuchFile: # catches missing dirs strangely enough
158
                    store_transport.mkdir(prefix_dir)
159
                    store_transport.move(filename, prefix_dir + '/' + filename)
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
160
        self.old_format = BzrDirFormat6()
161
        self._set_new_format(self.old_format.get_format_string())
162
        self.bzrdir = self.old_format.open(self.transport)
163
        self.branch = self.bzrdir.open_branch()
1429 by Robert Collins
merge in niemeyers prefixed-store patch
164
165
    def _convert_to_weaves(self):
1381 by Martin Pool
- remove tab characters (only)
166
        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
167
        bzr_transport = self.transport.clone('.bzr')
168
        try:
169
            # TODO permissions
170
            stat = bzr_transport.stat('weaves')
171
            if not S_ISDIR(stat.st_mode):
172
                bzr_transport.delete('weaves')
173
                bzr_transport.mkdir('weaves')
174
        except NoSuchFile:
175
            bzr_transport.mkdir('weaves')
1382 by Martin Pool
- upgrade checks if branch is uptodate before anything else
176
        self.inv_weave = Weave('inventory')
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
177
        # holds in-memory weaves for all files
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
178
        self.text_weaves = {}
1534.4.16 by Robert Collins
Last vestiges of local file requirements for upgrade nuked
179
        bzr_transport.delete('branch-format')
1381 by Martin Pool
- remove tab characters (only)
180
        self._convert_working_inv()
1358 by Martin Pool
- actually upgrade all of history
181
        rev_history = self.branch.revision_history()
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
182
        # to_read is a stack holding the revisions we still need to process;
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
183
        # appending to it adds new highest-priority revisions
1319 by Martin Pool
- calculate and use file parents for importing texts
184
        self.known_revisions = set(rev_history)
1185.20.1 by Andres Salomon
Handle the case where revision_history() returns an empty list during
185
        self.to_read = rev_history[-1:]
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
186
        while self.to_read:
187
            rev_id = self.to_read.pop()
188
            if (rev_id not in self.revisions
189
                and rev_id not in self.absent_revisions):
190
                self._load_one_rev(rev_id)
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
191
        self.pb.clear()
1332 by Martin Pool
- clean up code that writes out weave results
192
        to_import = self._make_order()
1315 by Martin Pool
- import file inventories in correct order
193
        for i, rev_id in enumerate(to_import):
194
            self.pb.update('converting revision', i, len(to_import))
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
195
            self._convert_one_rev(rev_id)
1331 by Martin Pool
- write out new revisions after conversion
196
        self.pb.clear()
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
197
        self._write_all_weaves()
198
        self._write_all_revs()
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
199
        note('upgraded to weaves:')
200
        note('  %6d revisions and inventories' % len(self.revisions))
1393.1.44 by Martin Pool
- upgrade carries across ghost references
201
        note('  %6d revisions not present' % len(self.absent_revisions))
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
202
        note('  %6d texts' % self.text_count)
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
203
        self._cleanup_spare_files_after_format4()
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
204
        self.old_format = BzrDirFormat5()
205
        self._set_new_format(self.old_format.get_format_string())
206
        self.bzrdir = self.old_format.open(self.transport)
207
        self.branch = self.bzrdir.open_branch()
1357 by Martin Pool
- require marker file to do upgrade so as not to clobber something important
208
1382 by Martin Pool
- upgrade checks if branch is uptodate before anything else
209
    def _open_branch(self):
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
210
        self.old_format = BzrDirFormat.find_format(self.transport)
211
        self.bzrdir = self.old_format.open(self.transport)
212
        self.branch = self.bzrdir.open_branch()
213
        if isinstance(self.old_format, BzrDirFormat6):
1534.4.8 by Robert Collins
Unfuck upgrade.
214
            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
215
            return False
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
216
        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.
217
            not isinstance(self.old_format, BzrDirFormat5) and
218
            not isinstance(self.old_format, bzrdir.BzrDirMetaFormat1)):
219
            raise errors.BzrError("cannot upgrade from branch format %s" %
1382 by Martin Pool
- upgrade checks if branch is uptodate before anything else
220
                           self.branch._branch_format)
221
        return True
222
1429 by Robert Collins
merge in niemeyers prefixed-store patch
223
    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.
224
        self.branch.control_files.put_utf8('branch-format', format)
1355 by Martin Pool
- write working inventory into final location
225
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
226
    def _cleanup_spare_files_after_format4(self):
227
        transport = self.transport.clone('.bzr')
1551.2.5 by Aaron Bentley
Removed more selftest spam [recommit]
228
        # FIXME working tree upgrade foo.
1381 by Martin Pool
- remove tab characters (only)
229
        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.
230
            try:
231
                ## assert os.path.getsize(p) == 0
232
                transport.delete(n)
233
            except NoSuchFile:
234
                pass
235
        transport.delete_tree('inventory-store')
236
        transport.delete_tree('text-store')
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
237
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
238
    def _backup_control_dir(self):
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
239
        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.
240
        self.transport.copy_tree('.bzr', '.bzr.backup')
241
        note('%s.bzr has been backed up to %s.bzr.backup',
242
             self.transport.base,
243
             self.transport.base)
1381 by Martin Pool
- remove tab characters (only)
244
        note('if conversion fails, you can move this directory back to .bzr')
245
        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
246
247
    def _convert_working_inv(self):
1381 by Martin Pool
- remove tab characters (only)
248
        branch = self.branch
1185.65.29 by Robert Collins
Implement final review suggestions.
249
        inv = serializer_v4.read_inventory(branch.control_files.get('inventory'))
1393.1.18 by Martin Pool
- fix upgrade for transport changes
250
        new_inv_xml = serializer_v5.write_inventory_to_string(inv)
1551.2.5 by Aaron Bentley
Removed more selftest spam [recommit]
251
        # FIXME inventory is a working tree change.
1185.65.29 by Robert Collins
Implement final review suggestions.
252
        branch.control_files.put('inventory', new_inv_xml)
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
253
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
254
    def _write_all_weaves(self):
1534.4.16 by Robert Collins
Last vestiges of local file requirements for upgrade nuked
255
        bzr_transport = self.transport.clone('.bzr')
256
        controlweaves = WeaveStore(bzr_transport, prefixed=False)
257
        weave_transport = bzr_transport.clone('weaves')
258
        weaves = WeaveStore(weave_transport, prefixed=False)
259
        transaction = PassThroughTransaction()
260
261
        controlweaves.put_weave('inventory', self.inv_weave, transaction)
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
262
        i = 0
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
263
        try:
264
            for file_id, file_weave in self.text_weaves.items():
265
                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
266
                weaves.put_weave(file_id, file_weave, transaction)
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
267
                i += 1
268
        finally:
269
            self.pb.clear()
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
270
1331 by Martin Pool
- write out new revisions after conversion
271
    def _write_all_revs(self):
272
        """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.
273
        transport = self.transport.clone('.bzr')
274
        transport.delete_tree('revision-store')
275
        transport.mkdir('revision-store')
1534.4.16 by Robert Collins
Last vestiges of local file requirements for upgrade nuked
276
        revision_transport = transport.clone('revision-store')
277
        # TODO permissions
278
        revision_store = TextStore(revision_transport,
279
                                   prefixed=False,
280
                                   compressed=True)
1331 by Martin Pool
- write out new revisions after conversion
281
        try:
282
            for i, rev_id in enumerate(self.converted_revs):
283
                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
284
                rev_tmp = StringIO()
285
                serializer_v5.write_revision(self.revisions[rev_id], rev_tmp)
286
                rev_tmp.seek(0)
287
                revision_store.add(rev_tmp, rev_id)
1331 by Martin Pool
- write out new revisions after conversion
288
        finally:
289
            self.pb.clear()
1332 by Martin Pool
- clean up code that writes out weave results
290
1331 by Martin Pool
- write out new revisions after conversion
291
            
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
292
    def _load_one_rev(self, rev_id):
293
        """Load a revision object into memory.
294
295
        Any parents not either loaded or abandoned get queued to be
296
        loaded."""
297
        self.pb.update('loading revision',
1315 by Martin Pool
- import file inventories in correct order
298
                       len(self.revisions),
1319 by Martin Pool
- calculate and use file parents for importing texts
299
                       len(self.known_revisions))
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
300
        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
301
            self.pb.clear()
302
            note('revision {%s} not present in branch; '
1393.1.44 by Martin Pool
- upgrade carries across ghost references
303
                 'will be converted as a ghost',
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
304
                 rev_id)
305
            self.absent_revisions.add(rev_id)
306
        else:
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
307
            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
308
            rev = serializer_v4.read_revision_from_string(rev_xml)
1313 by Martin Pool
- rename to Revision.parent_ids to avoid confusion with old usage
309
            for parent_id in rev.parent_ids:
1319 by Martin Pool
- calculate and use file parents for importing texts
310
                self.known_revisions.add(parent_id)
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
311
                self.to_read.append(parent_id)
312
            self.revisions[rev_id] = rev
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
313
314
315
    def _load_old_inventory(self, rev_id):
316
        assert rev_id not in self.converted_revs
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
317
        old_inv_xml = self.branch.repository.inventory_store.get(rev_id).read()
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
318
        inv = serializer_v4.read_inventory_from_string(old_inv_xml)
319
        rev = self.revisions[rev_id]
320
        if rev.inventory_sha1:
321
            assert rev.inventory_sha1 == sha_string(old_inv_xml), \
322
                'inventory sha mismatch for {%s}' % rev_id
323
        return inv
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
324
        
325
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
326
    def _load_updated_inventory(self, rev_id):
327
        assert rev_id in self.converted_revs
328
        inv_xml = self.inv_weave.get_text(rev_id)
329
        inv = serializer_v5.read_inventory_from_string(inv_xml)
330
        return inv
331
332
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
333
    def _convert_one_rev(self, rev_id):
334
        """Convert revision and all referenced objects to new format."""
335
        rev = self.revisions[rev_id]
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
336
        inv = self._load_old_inventory(rev_id)
1393.1.44 by Martin Pool
- upgrade carries across ghost references
337
        present_parents = [p for p in rev.parent_ids
338
                           if p not in self.absent_revisions]
339
        self._convert_revision_contents(rev, inv, present_parents)
340
        self._store_new_weave(rev, inv, present_parents)
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
341
        self.converted_revs.add(rev_id)
342
343
1393.1.44 by Martin Pool
- upgrade carries across ghost references
344
    def _store_new_weave(self, rev, inv, present_parents):
1320 by Martin Pool
- write updated inventory into weave
345
        # the XML is now updated with text versions
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
346
        if __debug__:
347
            for file_id in inv:
348
                ie = inv[file_id]
349
                if ie.kind == 'root_directory':
350
                    continue
1092.2.21 by Robert Collins
convert name_version to revision in inventory entries
351
                assert hasattr(ie, 'revision'), \
352
                    'no revision on {%s} in {%s}' % \
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
353
                    (file_id, rev.revision_id)
1316 by Martin Pool
- upgrade format of inventories as they're converted
354
        new_inv_xml = serializer_v5.write_inventory_to_string(inv)
1325 by Martin Pool
- conversion to weave tries to avoid repeated SHA calculation
355
        new_inv_sha1 = sha_string(new_inv_xml)
1393.1.44 by Martin Pool
- upgrade carries across ghost references
356
        self.inv_weave.add(rev.revision_id, 
357
                           present_parents,
1325 by Martin Pool
- conversion to weave tries to avoid repeated SHA calculation
358
                           new_inv_xml.splitlines(True),
359
                           new_inv_sha1)
360
        rev.inventory_sha1 = new_inv_sha1
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
361
1393.1.44 by Martin Pool
- upgrade carries across ghost references
362
    def _convert_revision_contents(self, rev, inv, present_parents):
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
363
        """Convert all the files within a revision.
364
365
        Also upgrade the inventory to refer to the text revision ids."""
366
        rev_id = rev.revision_id
1319 by Martin Pool
- calculate and use file parents for importing texts
367
        mutter('converting texts of revision {%s}',
368
               rev_id)
1393.1.44 by Martin Pool
- upgrade carries across ghost references
369
        parent_invs = map(self._load_updated_inventory, present_parents)
1332 by Martin Pool
- clean up code that writes out weave results
370
        for file_id in inv:
371
            ie = inv[file_id]
1386 by Martin Pool
- avoiding loading all inventories upfront for conversion
372
            self._convert_file_version(rev, ie, parent_invs)
373
374
    def _convert_file_version(self, rev, ie, parent_invs):
1319 by Martin Pool
- calculate and use file parents for importing texts
375
        """Convert one version of one file.
376
377
        The file needs to be added into the weave if it is a merge
378
        of >=2 parents or if it's changed from its parent.
379
        """
1405 by Robert Collins
remove some of the upgrade code that was duplicated with inventory_entry, and give all inventory entries a weave
380
        if ie.kind == 'root_directory':
381
            return
1319 by Martin Pool
- calculate and use file parents for importing texts
382
        file_id = ie.file_id
383
        rev_id = rev.revision_id
384
        w = self.text_weaves.get(file_id)
385
        if w is None:
386
            w = Weave(file_id)
387
            self.text_weaves[file_id] = w
388
        text_changed = False
1411 by Robert Collins
use weave ancestry to determine inventory entry previous heads, prevent propogating 'I did a merge' merges.
389
        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
390
        for old_revision in previous_entries:
1092.2.22 by Robert Collins
text_version and name_version unification looking reasonable
391
                # if this fails, its a ghost ?
392
                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
393
        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
394
        del ie.text_id
395
        assert getattr(ie, 'revision', None) is not None
396
397
    def snapshot_ie(self, previous_revisions, ie, w, rev_id):
398
        # TODO: convert this logic, which is ~= snapshot to
399
        # 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
400
        # a v4 revision_tree can be given, or something that looks enough like
401
        # 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
402
        # and we need something that looks like a weave store for snapshot to 
403
        # save against.
404
        #ie.snapshot(rev, PATH, previous_revisions, REVISION_TREE, InMemoryWeaveStore(self.text_weaves))
405
        if len(previous_revisions) == 1:
406
            previous_ie = previous_revisions.values()[0]
407
            if ie._unchanged(previous_ie):
408
                ie.revision = previous_ie.revision
409
                return
410
        parent_indexes = map(w.lookup, previous_revisions)
411
        if ie.has_text():
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
412
            text = self.branch.repository.text_store.get(ie.text_id)
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
413
            file_lines = text.readlines()
1378 by Martin Pool
- in upgrade, avoiding loading file texts unless necessary
414
            assert sha_strings(file_lines) == ie.text_sha1
415
            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
416
            w.add(rev_id, parent_indexes, file_lines, ie.text_sha1)
1332 by Martin Pool
- clean up code that writes out weave results
417
            self.text_count += 1
1319 by Martin Pool
- calculate and use file parents for importing texts
418
        else:
1405 by Robert Collins
remove some of the upgrade code that was duplicated with inventory_entry, and give all inventory entries a weave
419
            w.add(rev_id, parent_indexes, [], None)
420
        ie.revision = rev_id
421
        ##mutter('import text {%s} of {%s}',
422
        ##       ie.text_id, file_id)
1310 by Martin Pool
- compute order to import revisions
423
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
424
    def _make_order(self):
1310 by Martin Pool
- compute order to import revisions
425
        """Return a suitable order for importing revisions.
426
427
        The order must be such that an revision is imported after all
428
        its (present) parents.
429
        """
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
430
        todo = set(self.revisions.keys())
431
        done = self.absent_revisions.copy()
1310 by Martin Pool
- compute order to import revisions
432
        o = []
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
433
        while todo:
434
            # scan through looking for a revision whose parents
435
            # are all done
1310 by Martin Pool
- compute order to import revisions
436
            for rev_id in sorted(list(todo)):
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
437
                rev = self.revisions[rev_id]
1313 by Martin Pool
- rename to Revision.parent_ids to avoid confusion with old usage
438
                parent_ids = set(rev.parent_ids)
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
439
                if parent_ids.issubset(done):
440
                    # can take this one now
1310 by Martin Pool
- compute order to import revisions
441
                    o.append(rev_id)
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
442
                    todo.remove(rev_id)
443
                    done.add(rev_id)
1315 by Martin Pool
- import file inventories in correct order
444
        return o
1377 by Martin Pool
- run conversion to weaves from the 'bzr upgrade' command
445
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
446
1534.4.13 by Robert Collins
Give a reasonable warning on attempts to upgrade a readonly url.
447
def upgrade(url):
448
    t = get_transport(url)
449
    Convert(t)