/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
1
# Copyright (C) 2006-2010 Canonical Ltd
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
6379.6.7 by Jelmer Vernooij
Move importing from future until after doc string, otherwise the doc string will disappear.
17
"""Weave-era BzrDir formats."""
18
6379.6.3 by Jelmer Vernooij
Use absolute_import.
19
from __future__ import absolute_import
20
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
21
from bzrlib.bzrdir import (
22
    BzrDir,
23
    BzrDirFormat,
24
    BzrDirMetaFormat1,
25
    )
26
from bzrlib.controldir import (
27
    Converter,
28
    format_registry,
29
    )
30
from bzrlib.lazy_import import lazy_import
31
lazy_import(globals(), """
32
import os
33
import warnings
34
35
from bzrlib import (
36
    errors,
37
    graph,
38
    lockable_files,
39
    lockdir,
40
    osutils,
41
    revision as _mod_revision,
42
    trace,
43
    ui,
44
    urlutils,
45
    versionedfile,
46
    weave,
47
    xml5,
48
    )
6150.3.2 by Jonathan Riddell
gettext() on weave plugin
49
from bzrlib.i18n import gettext
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
50
from bzrlib.store.versioned import VersionedFileStore
51
from bzrlib.transactions import WriteTransaction
52
from bzrlib.transport import (
53
    get_transport,
54
    local,
55
    )
5582.10.90 by Jelmer Vernooij
Merge weave-bzrdir branch.
56
from bzrlib.plugins.weave_fmt import xml4
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
57
""")
58
59
60
class BzrDirFormatAllInOne(BzrDirFormat):
61
    """Common class for formats before meta-dirs."""
62
63
    fixed_components = True
64
65
    def initialize_on_transport_ex(self, transport, use_existing_dir=False,
66
        create_prefix=False, force_new_repo=False, stacked_on=None,
67
        stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
68
        shared_repo=False):
69
        """See BzrDirFormat.initialize_on_transport_ex."""
70
        require_stacking = (stacked_on is not None)
71
        # Format 5 cannot stack, but we've been asked to - actually init
72
        # a Meta1Dir
73
        if require_stacking:
74
            format = BzrDirMetaFormat1()
75
            return format.initialize_on_transport_ex(transport,
76
                use_existing_dir=use_existing_dir, create_prefix=create_prefix,
77
                force_new_repo=force_new_repo, stacked_on=stacked_on,
78
                stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
79
                make_working_trees=make_working_trees, shared_repo=shared_repo)
80
        return BzrDirFormat.initialize_on_transport_ex(self, transport,
81
            use_existing_dir=use_existing_dir, create_prefix=create_prefix,
82
            force_new_repo=force_new_repo, stacked_on=stacked_on,
83
            stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
84
            make_working_trees=make_working_trees, shared_repo=shared_repo)
85
6349.2.1 by Jelmer Vernooij
Add BzrDirMetaComponentFormat.
86
    @classmethod
87
    def from_string(cls, format_string):
88
        if format_string != cls.get_format_string():
89
            raise AssertionError("unexpected format string %r" % format_string)
90
        return cls()
91
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
92
93
class BzrDirFormat5(BzrDirFormatAllInOne):
94
    """Bzr control format 5.
95
96
    This format is a combined format for working tree, branch and repository.
97
    It has:
98
     - Format 2 working trees [always]
99
     - Format 4 branches [always]
100
     - Format 5 repositories [always]
101
       Unhashed stores in the repository.
102
    """
103
104
    _lock_class = lockable_files.TransportLock
105
5712.4.7 by Jelmer Vernooij
More fixes.
106
    def __eq__(self, other):
107
        return type(self) == type(other)
108
6349.2.1 by Jelmer Vernooij
Add BzrDirMetaComponentFormat.
109
    @classmethod
110
    def get_format_string(cls):
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
111
        """See BzrDirFormat.get_format_string()."""
112
        return "Bazaar-NG branch, format 5\n"
113
114
    def get_branch_format(self):
5582.10.90 by Jelmer Vernooij
Merge weave-bzrdir branch.
115
        from bzrlib.plugins.weave_fmt.branch import BzrBranchFormat4
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
116
        return BzrBranchFormat4()
117
118
    def get_format_description(self):
119
        """See BzrDirFormat.get_format_description()."""
120
        return "All-in-one format 5"
121
122
    def get_converter(self, format=None):
123
        """See BzrDirFormat.get_converter()."""
124
        # there is one and only one upgrade path here.
125
        return ConvertBzrDir5To6()
126
127
    def _initialize_for_clone(self, url):
128
        return self.initialize_on_transport(get_transport(url), _cloning=True)
129
130
    def initialize_on_transport(self, transport, _cloning=False):
131
        """Format 5 dirs always have working tree, branch and repository.
132
133
        Except when they are being cloned.
134
        """
5582.10.90 by Jelmer Vernooij
Merge weave-bzrdir branch.
135
        from bzrlib.plugins.weave_fmt.branch import BzrBranchFormat4
136
        from bzrlib.plugins.weave_fmt.repository import RepositoryFormat5
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
137
        result = (super(BzrDirFormat5, self).initialize_on_transport(transport))
138
        RepositoryFormat5().initialize(result, _internal=True)
139
        if not _cloning:
140
            branch = BzrBranchFormat4().initialize(result)
141
            result._init_workingtree()
142
        return result
143
144
    def network_name(self):
145
        return self.get_format_string()
146
147
    def _open(self, transport):
148
        """See BzrDirFormat._open."""
149
        return BzrDir5(transport, self)
150
151
    def __return_repository_format(self):
152
        """Circular import protection."""
5582.10.90 by Jelmer Vernooij
Merge weave-bzrdir branch.
153
        from bzrlib.plugins.weave_fmt.repository import RepositoryFormat5
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
154
        return RepositoryFormat5()
155
    repository_format = property(__return_repository_format)
156
157
158
class BzrDirFormat6(BzrDirFormatAllInOne):
159
    """Bzr control format 6.
160
161
    This format is a combined format for working tree, branch and repository.
162
    It has:
163
     - Format 2 working trees [always]
164
     - Format 4 branches [always]
165
     - Format 6 repositories [always]
166
    """
167
168
    _lock_class = lockable_files.TransportLock
169
5712.4.7 by Jelmer Vernooij
More fixes.
170
    def __eq__(self, other):
171
        return type(self) == type(other)
172
6349.2.1 by Jelmer Vernooij
Add BzrDirMetaComponentFormat.
173
    @classmethod
174
    def get_format_string(cls):
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
175
        """See BzrDirFormat.get_format_string()."""
176
        return "Bazaar-NG branch, format 6\n"
177
178
    def get_format_description(self):
179
        """See BzrDirFormat.get_format_description()."""
180
        return "All-in-one format 6"
181
182
    def get_branch_format(self):
5582.10.90 by Jelmer Vernooij
Merge weave-bzrdir branch.
183
        from bzrlib.plugins.weave_fmt.branch import BzrBranchFormat4
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
184
        return BzrBranchFormat4()
185
186
    def get_converter(self, format=None):
187
        """See BzrDirFormat.get_converter()."""
188
        # there is one and only one upgrade path here.
189
        return ConvertBzrDir6ToMeta()
190
191
    def _initialize_for_clone(self, url):
192
        return self.initialize_on_transport(get_transport(url), _cloning=True)
193
194
    def initialize_on_transport(self, transport, _cloning=False):
195
        """Format 6 dirs always have working tree, branch and repository.
196
197
        Except when they are being cloned.
198
        """
5582.10.90 by Jelmer Vernooij
Merge weave-bzrdir branch.
199
        from bzrlib.plugins.weave_fmt.branch import BzrBranchFormat4
200
        from bzrlib.plugins.weave_fmt.repository import RepositoryFormat6
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
201
        result = super(BzrDirFormat6, self).initialize_on_transport(transport)
202
        RepositoryFormat6().initialize(result, _internal=True)
203
        if not _cloning:
204
            branch = BzrBranchFormat4().initialize(result)
205
            result._init_workingtree()
206
        return result
207
208
    def network_name(self):
209
        return self.get_format_string()
210
211
    def _open(self, transport):
212
        """See BzrDirFormat._open."""
213
        return BzrDir6(transport, self)
214
215
    def __return_repository_format(self):
216
        """Circular import protection."""
5582.10.90 by Jelmer Vernooij
Merge weave-bzrdir branch.
217
        from bzrlib.plugins.weave_fmt.repository import RepositoryFormat6
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
218
        return RepositoryFormat6()
219
    repository_format = property(__return_repository_format)
220
221
222
class ConvertBzrDir4To5(Converter):
223
    """Converts format 4 bzr dirs to format 5."""
224
225
    def __init__(self):
226
        super(ConvertBzrDir4To5, self).__init__()
227
        self.converted_revs = set()
228
        self.absent_revisions = set()
229
        self.text_count = 0
230
        self.revisions = {}
231
232
    def convert(self, to_convert, pb):
233
        """See Converter.convert()."""
234
        self.bzrdir = to_convert
235
        if pb is not None:
6150.3.2 by Jonathan Riddell
gettext() on weave plugin
236
            warnings.warn(gettext("pb parameter to convert() is deprecated"))
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
237
        self.pb = ui.ui_factory.nested_progress_bar()
238
        try:
6150.3.2 by Jonathan Riddell
gettext() on weave plugin
239
            ui.ui_factory.note(gettext('starting upgrade from format 4 to 5'))
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
240
            if isinstance(self.bzrdir.transport, local.LocalTransport):
241
                self.bzrdir.get_workingtree_transport(None).delete('stat-cache')
242
            self._convert_to_weaves()
243
            return BzrDir.open(self.bzrdir.user_url)
244
        finally:
245
            self.pb.finished()
246
247
    def _convert_to_weaves(self):
6150.3.2 by Jonathan Riddell
gettext() on weave plugin
248
        ui.ui_factory.note(gettext(
249
          'note: upgrade may be faster if all store files are ungzipped first'))
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
250
        try:
251
            # TODO permissions
252
            stat = self.bzrdir.transport.stat('weaves')
253
            if not S_ISDIR(stat.st_mode):
254
                self.bzrdir.transport.delete('weaves')
255
                self.bzrdir.transport.mkdir('weaves')
256
        except errors.NoSuchFile:
257
            self.bzrdir.transport.mkdir('weaves')
258
        # deliberately not a WeaveFile as we want to build it up slowly.
259
        self.inv_weave = weave.Weave('inventory')
260
        # holds in-memory weaves for all files
261
        self.text_weaves = {}
262
        self.bzrdir.transport.delete('branch-format')
263
        self.branch = self.bzrdir.open_branch()
264
        self._convert_working_inv()
6165.4.25 by Jelmer Vernooij
Fix plugin use of revision_history.
265
        rev_history = self.branch._revision_history()
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
266
        # to_read is a stack holding the revisions we still need to process;
267
        # appending to it adds new highest-priority revisions
268
        self.known_revisions = set(rev_history)
269
        self.to_read = rev_history[-1:]
270
        while self.to_read:
271
            rev_id = self.to_read.pop()
272
            if (rev_id not in self.revisions
273
                and rev_id not in self.absent_revisions):
274
                self._load_one_rev(rev_id)
275
        self.pb.clear()
276
        to_import = self._make_order()
277
        for i, rev_id in enumerate(to_import):
6150.3.2 by Jonathan Riddell
gettext() on weave plugin
278
            self.pb.update(gettext('converting revision'), i, len(to_import))
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
279
            self._convert_one_rev(rev_id)
280
        self.pb.clear()
281
        self._write_all_weaves()
282
        self._write_all_revs()
6150.3.2 by Jonathan Riddell
gettext() on weave plugin
283
        ui.ui_factory.note(gettext('upgraded to weaves:'))
6150.3.10 by Jonathan Riddell
do not include space padding in gettext()
284
        ui.ui_factory.note('  ' + gettext('%6d revisions and inventories') %
6150.3.2 by Jonathan Riddell
gettext() on weave plugin
285
                                                        len(self.revisions))
6150.3.10 by Jonathan Riddell
do not include space padding in gettext()
286
        ui.ui_factory.note('  ' + gettext('%6d revisions not present') %
6150.3.2 by Jonathan Riddell
gettext() on weave plugin
287
                                                    len(self.absent_revisions))
6150.3.10 by Jonathan Riddell
do not include space padding in gettext()
288
        ui.ui_factory.note('  ' + gettext('%6d texts') % self.text_count)
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
289
        self._cleanup_spare_files_after_format4()
290
        self.branch._transport.put_bytes(
291
            'branch-format',
292
            BzrDirFormat5().get_format_string(),
293
            mode=self.bzrdir._get_file_mode())
294
295
    def _cleanup_spare_files_after_format4(self):
296
        # FIXME working tree upgrade foo.
297
        for n in 'merged-patches', 'pending-merged-patches':
298
            try:
299
                ## assert os.path.getsize(p) == 0
300
                self.bzrdir.transport.delete(n)
301
            except errors.NoSuchFile:
302
                pass
303
        self.bzrdir.transport.delete_tree('inventory-store')
304
        self.bzrdir.transport.delete_tree('text-store')
305
306
    def _convert_working_inv(self):
307
        inv = xml4.serializer_v4.read_inventory(
308
                self.branch._transport.get('inventory'))
309
        new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv, working=True)
310
        self.branch._transport.put_bytes('inventory', new_inv_xml,
311
            mode=self.bzrdir._get_file_mode())
312
313
    def _write_all_weaves(self):
314
        controlweaves = VersionedFileStore(self.bzrdir.transport, prefixed=False,
315
            versionedfile_class=weave.WeaveFile)
316
        weave_transport = self.bzrdir.transport.clone('weaves')
317
        weaves = VersionedFileStore(weave_transport, prefixed=False,
318
                versionedfile_class=weave.WeaveFile)
319
        transaction = WriteTransaction()
320
321
        try:
322
            i = 0
323
            for file_id, file_weave in self.text_weaves.items():
6150.3.2 by Jonathan Riddell
gettext() on weave plugin
324
                self.pb.update(gettext('writing weave'), i,
325
                                                        len(self.text_weaves))
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
326
                weaves._put_weave(file_id, file_weave, transaction)
327
                i += 1
6150.3.2 by Jonathan Riddell
gettext() on weave plugin
328
            self.pb.update(gettext('inventory'), 0, 1)
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
329
            controlweaves._put_weave('inventory', self.inv_weave, transaction)
6150.3.2 by Jonathan Riddell
gettext() on weave plugin
330
            self.pb.update(gettext('inventory'), 1, 1)
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
331
        finally:
332
            self.pb.clear()
333
334
    def _write_all_revs(self):
335
        """Write all revisions out in new form."""
336
        self.bzrdir.transport.delete_tree('revision-store')
337
        self.bzrdir.transport.mkdir('revision-store')
338
        revision_transport = self.bzrdir.transport.clone('revision-store')
339
        # TODO permissions
340
        from bzrlib.xml5 import serializer_v5
5582.10.90 by Jelmer Vernooij
Merge weave-bzrdir branch.
341
        from bzrlib.plugins.weave_fmt.repository import RevisionTextStore
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
342
        revision_store = RevisionTextStore(revision_transport,
343
            serializer_v5, False, versionedfile.PrefixMapper(),
344
            lambda:True, lambda:True)
345
        try:
346
            for i, rev_id in enumerate(self.converted_revs):
6150.3.2 by Jonathan Riddell
gettext() on weave plugin
347
                self.pb.update(gettext('write revision'), i,
348
                                                len(self.converted_revs))
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
349
                text = serializer_v5.write_revision_to_string(
350
                    self.revisions[rev_id])
351
                key = (rev_id,)
352
                revision_store.add_lines(key, None, osutils.split_lines(text))
353
        finally:
354
            self.pb.clear()
355
356
    def _load_one_rev(self, rev_id):
357
        """Load a revision object into memory.
358
359
        Any parents not either loaded or abandoned get queued to be
360
        loaded."""
6150.3.11 by Jonathan Riddell
syntax fixes
361
        self.pb.update(gettext('loading revision'),
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
362
                       len(self.revisions),
363
                       len(self.known_revisions))
364
        if not self.branch.repository.has_revision(rev_id):
365
            self.pb.clear()
6150.3.2 by Jonathan Riddell
gettext() on weave plugin
366
            ui.ui_factory.note(gettext('revision {%s} not present in branch; '
367
                         'will be converted as a ghost') %
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
368
                         rev_id)
369
            self.absent_revisions.add(rev_id)
370
        else:
371
            rev = self.branch.repository.get_revision(rev_id)
372
            for parent_id in rev.parent_ids:
373
                self.known_revisions.add(parent_id)
374
                self.to_read.append(parent_id)
375
            self.revisions[rev_id] = rev
376
377
    def _load_old_inventory(self, rev_id):
378
        f = self.branch.repository.inventory_store.get(rev_id)
379
        try:
380
            old_inv_xml = f.read()
381
        finally:
382
            f.close()
383
        inv = xml4.serializer_v4.read_inventory_from_string(old_inv_xml)
384
        inv.revision_id = rev_id
385
        rev = self.revisions[rev_id]
386
        return inv
387
388
    def _load_updated_inventory(self, rev_id):
389
        inv_xml = self.inv_weave.get_text(rev_id)
390
        inv = xml5.serializer_v5.read_inventory_from_string(inv_xml, rev_id)
391
        return inv
392
393
    def _convert_one_rev(self, rev_id):
394
        """Convert revision and all referenced objects to new format."""
395
        rev = self.revisions[rev_id]
396
        inv = self._load_old_inventory(rev_id)
397
        present_parents = [p for p in rev.parent_ids
398
                           if p not in self.absent_revisions]
399
        self._convert_revision_contents(rev, inv, present_parents)
400
        self._store_new_inv(rev, inv, present_parents)
401
        self.converted_revs.add(rev_id)
402
403
    def _store_new_inv(self, rev, inv, present_parents):
404
        new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv)
405
        new_inv_sha1 = osutils.sha_string(new_inv_xml)
406
        self.inv_weave.add_lines(rev.revision_id,
407
                                 present_parents,
408
                                 new_inv_xml.splitlines(True))
409
        rev.inventory_sha1 = new_inv_sha1
410
411
    def _convert_revision_contents(self, rev, inv, present_parents):
412
        """Convert all the files within a revision.
413
414
        Also upgrade the inventory to refer to the text revision ids."""
415
        rev_id = rev.revision_id
416
        trace.mutter('converting texts of revision {%s}', rev_id)
417
        parent_invs = map(self._load_updated_inventory, present_parents)
418
        entries = inv.iter_entries()
419
        entries.next()
420
        for path, ie in entries:
421
            self._convert_file_version(rev, ie, parent_invs)
422
423
    def _convert_file_version(self, rev, ie, parent_invs):
424
        """Convert one version of one file.
425
426
        The file needs to be added into the weave if it is a merge
427
        of >=2 parents or if it's changed from its parent.
428
        """
429
        file_id = ie.file_id
430
        rev_id = rev.revision_id
431
        w = self.text_weaves.get(file_id)
432
        if w is None:
433
            w = weave.Weave(file_id)
434
            self.text_weaves[file_id] = w
435
        text_changed = False
436
        parent_candiate_entries = ie.parent_candidates(parent_invs)
437
        heads = graph.Graph(self).heads(parent_candiate_entries.keys())
438
        # XXX: Note that this is unordered - and this is tolerable because
439
        # the previous code was also unordered.
440
        previous_entries = dict((head, parent_candiate_entries[head]) for head
441
            in heads)
442
        self.snapshot_ie(previous_entries, ie, w, rev_id)
443
444
    def get_parent_map(self, revision_ids):
445
        """See graph.StackedParentsProvider.get_parent_map"""
446
        return dict((revision_id, self.revisions[revision_id])
447
                    for revision_id in revision_ids
448
                     if revision_id in self.revisions)
449
450
    def snapshot_ie(self, previous_revisions, ie, w, rev_id):
451
        # TODO: convert this logic, which is ~= snapshot to
452
        # a call to:. This needs the path figured out. rather than a work_tree
453
        # a v4 revision_tree can be given, or something that looks enough like
454
        # one to give the file content to the entry if it needs it.
455
        # and we need something that looks like a weave store for snapshot to
456
        # save against.
457
        #ie.snapshot(rev, PATH, previous_revisions, REVISION_TREE, InMemoryWeaveStore(self.text_weaves))
458
        if len(previous_revisions) == 1:
459
            previous_ie = previous_revisions.values()[0]
460
            if ie._unchanged(previous_ie):
461
                ie.revision = previous_ie.revision
462
                return
463
        if ie.has_text():
464
            f = self.branch.repository._text_store.get(ie.text_id)
465
            try:
466
                file_lines = f.readlines()
467
            finally:
468
                f.close()
469
            w.add_lines(rev_id, previous_revisions, file_lines)
470
            self.text_count += 1
471
        else:
472
            w.add_lines(rev_id, previous_revisions, [])
473
        ie.revision = rev_id
474
475
    def _make_order(self):
476
        """Return a suitable order for importing revisions.
477
478
        The order must be such that an revision is imported after all
479
        its (present) parents.
480
        """
481
        todo = set(self.revisions.keys())
482
        done = self.absent_revisions.copy()
483
        order = []
484
        while todo:
485
            # scan through looking for a revision whose parents
486
            # are all done
487
            for rev_id in sorted(list(todo)):
488
                rev = self.revisions[rev_id]
489
                parent_ids = set(rev.parent_ids)
490
                if parent_ids.issubset(done):
491
                    # can take this one now
492
                    order.append(rev_id)
493
                    todo.remove(rev_id)
494
                    done.add(rev_id)
495
        return order
496
497
498
class ConvertBzrDir5To6(Converter):
499
    """Converts format 5 bzr dirs to format 6."""
500
501
    def convert(self, to_convert, pb):
502
        """See Converter.convert()."""
503
        self.bzrdir = to_convert
504
        pb = ui.ui_factory.nested_progress_bar()
505
        try:
6150.3.2 by Jonathan Riddell
gettext() on weave plugin
506
            ui.ui_factory.note(gettext('starting upgrade from format 5 to 6'))
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
507
            self._convert_to_prefixed()
508
            return BzrDir.open(self.bzrdir.user_url)
509
        finally:
510
            pb.finished()
511
512
    def _convert_to_prefixed(self):
513
        from bzrlib.store import TransportStore
514
        self.bzrdir.transport.delete('branch-format')
515
        for store_name in ["weaves", "revision-store"]:
6150.3.6 by Jonathan Riddell
more gettext()ing
516
            ui.ui_factory.note(gettext("adding prefixes to %s") % store_name)
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
517
            store_transport = self.bzrdir.transport.clone(store_name)
518
            store = TransportStore(store_transport, prefixed=True)
519
            for urlfilename in store_transport.list_dir('.'):
520
                filename = urlutils.unescape(urlfilename)
521
                if (filename.endswith(".weave") or
522
                    filename.endswith(".gz") or
523
                    filename.endswith(".sig")):
524
                    file_id, suffix = os.path.splitext(filename)
525
                else:
526
                    file_id = filename
527
                    suffix = ''
528
                new_name = store._mapper.map((file_id,)) + suffix
529
                # FIXME keep track of the dirs made RBC 20060121
530
                try:
531
                    store_transport.move(filename, new_name)
532
                except errors.NoSuchFile: # catches missing dirs strangely enough
533
                    store_transport.mkdir(osutils.dirname(new_name))
534
                    store_transport.move(filename, new_name)
535
        self.bzrdir.transport.put_bytes(
536
            'branch-format',
537
            BzrDirFormat6().get_format_string(),
538
            mode=self.bzrdir._get_file_mode())
539
540
541
class ConvertBzrDir6ToMeta(Converter):
542
    """Converts format 6 bzr dirs to metadirs."""
543
544
    def convert(self, to_convert, pb):
545
        """See Converter.convert()."""
5582.10.90 by Jelmer Vernooij
Merge weave-bzrdir branch.
546
        from bzrlib.plugins.weave_fmt.repository import RepositoryFormat7
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
547
        from bzrlib.branch import BzrBranchFormat5
548
        self.bzrdir = to_convert
549
        self.pb = ui.ui_factory.nested_progress_bar()
550
        self.count = 0
551
        self.total = 20 # the steps we know about
552
        self.garbage_inventories = []
553
        self.dir_mode = self.bzrdir._get_dir_mode()
554
        self.file_mode = self.bzrdir._get_file_mode()
555
6150.3.2 by Jonathan Riddell
gettext() on weave plugin
556
        ui.ui_factory.note(gettext('starting upgrade from format 6 to metadir'))
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
557
        self.bzrdir.transport.put_bytes(
558
                'branch-format',
559
                "Converting to format 6",
560
                mode=self.file_mode)
561
        # its faster to move specific files around than to open and use the apis...
562
        # first off, nuke ancestry.weave, it was never used.
563
        try:
6150.3.2 by Jonathan Riddell
gettext() on weave plugin
564
            self.step(gettext('Removing ancestry.weave'))
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
565
            self.bzrdir.transport.delete('ancestry.weave')
566
        except errors.NoSuchFile:
567
            pass
568
        # find out whats there
6150.3.2 by Jonathan Riddell
gettext() on weave plugin
569
        self.step(gettext('Finding branch files'))
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
570
        last_revision = self.bzrdir.open_branch().last_revision()
571
        bzrcontents = self.bzrdir.transport.list_dir('.')
572
        for name in bzrcontents:
573
            if name.startswith('basis-inventory.'):
574
                self.garbage_inventories.append(name)
575
        # create new directories for repository, working tree and branch
576
        repository_names = [('inventory.weave', True),
577
                            ('revision-store', True),
578
                            ('weaves', True)]
6150.3.10 by Jonathan Riddell
do not include space padding in gettext()
579
        self.step(gettext('Upgrading repository') + '  ')
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
580
        self.bzrdir.transport.mkdir('repository', mode=self.dir_mode)
581
        self.make_lock('repository')
582
        # we hard code the formats here because we are converting into
583
        # the meta format. The meta format upgrader can take this to a
584
        # future format within each component.
585
        self.put_format('repository', RepositoryFormat7())
586
        for entry in repository_names:
587
            self.move_entry('repository', entry)
588
6150.3.10 by Jonathan Riddell
do not include space padding in gettext()
589
        self.step(gettext('Upgrading branch') + '      ')
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
590
        self.bzrdir.transport.mkdir('branch', mode=self.dir_mode)
591
        self.make_lock('branch')
592
        self.put_format('branch', BzrBranchFormat5())
593
        branch_files = [('revision-history', True),
594
                        ('branch-name', True),
595
                        ('parent', False)]
596
        for entry in branch_files:
597
            self.move_entry('branch', entry)
598
599
        checkout_files = [('pending-merges', True),
600
                          ('inventory', True),
601
                          ('stat-cache', False)]
602
        # If a mandatory checkout file is not present, the branch does not have
603
        # a functional checkout. Do not create a checkout in the converted
604
        # branch.
605
        for name, mandatory in checkout_files:
606
            if mandatory and name not in bzrcontents:
607
                has_checkout = False
608
                break
609
        else:
610
            has_checkout = True
611
        if not has_checkout:
6150.3.2 by Jonathan Riddell
gettext() on weave plugin
612
            ui.ui_factory.note(gettext('No working tree.'))
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
613
            # If some checkout files are there, we may as well get rid of them.
614
            for name, mandatory in checkout_files:
615
                if name in bzrcontents:
616
                    self.bzrdir.transport.delete(name)
617
        else:
5816.5.4 by Jelmer Vernooij
Merge bzr.dev.
618
            from bzrlib.workingtree_3 import WorkingTreeFormat3
6150.3.2 by Jonathan Riddell
gettext() on weave plugin
619
            self.step(gettext('Upgrading working tree'))
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
620
            self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
621
            self.make_lock('checkout')
622
            self.put_format(
623
                'checkout', WorkingTreeFormat3())
624
            self.bzrdir.transport.delete_multi(
625
                self.garbage_inventories, self.pb)
626
            for entry in checkout_files:
627
                self.move_entry('checkout', entry)
628
            if last_revision is not None:
629
                self.bzrdir.transport.put_bytes(
630
                    'checkout/last-revision', last_revision)
631
        self.bzrdir.transport.put_bytes(
632
            'branch-format',
633
            BzrDirMetaFormat1().get_format_string(),
634
            mode=self.file_mode)
635
        self.pb.finished()
636
        return BzrDir.open(self.bzrdir.user_url)
637
638
    def make_lock(self, name):
639
        """Make a lock for the new control dir name."""
6150.3.2 by Jonathan Riddell
gettext() on weave plugin
640
        self.step(gettext('Make %s lock') % name)
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
641
        ld = lockdir.LockDir(self.bzrdir.transport,
642
                             '%s/lock' % name,
643
                             file_modebits=self.file_mode,
644
                             dir_modebits=self.dir_mode)
645
        ld.create()
646
647
    def move_entry(self, new_dir, entry):
648
        """Move then entry name into new_dir."""
649
        name = entry[0]
650
        mandatory = entry[1]
6150.3.2 by Jonathan Riddell
gettext() on weave plugin
651
        self.step(gettext('Moving %s') % name)
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
652
        try:
653
            self.bzrdir.transport.move(name, '%s/%s' % (new_dir, name))
654
        except errors.NoSuchFile:
655
            if mandatory:
656
                raise
657
658
    def put_format(self, dirname, format):
659
        self.bzrdir.transport.put_bytes('%s/format' % dirname,
660
            format.get_format_string(),
661
            self.file_mode)
662
663
664
class BzrDirFormat4(BzrDirFormat):
665
    """Bzr dir format 4.
666
667
    This format is a combined format for working tree, branch and repository.
668
    It has:
669
     - Format 1 working trees [always]
670
     - Format 4 branches [always]
671
     - Format 4 repositories [always]
672
673
    This format is deprecated: it indexes texts using a text it which is
674
    removed in format 5; write support for this format has been removed.
675
    """
676
677
    _lock_class = lockable_files.TransportLock
678
5712.4.7 by Jelmer Vernooij
More fixes.
679
    def __eq__(self, other):
680
        return type(self) == type(other)
681
6349.2.1 by Jelmer Vernooij
Add BzrDirMetaComponentFormat.
682
    @classmethod
683
    def get_format_string(cls):
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
684
        """See BzrDirFormat.get_format_string()."""
685
        return "Bazaar-NG branch, format 0.0.4\n"
686
687
    def get_format_description(self):
688
        """See BzrDirFormat.get_format_description()."""
689
        return "All-in-one format 4"
690
691
    def get_converter(self, format=None):
692
        """See BzrDirFormat.get_converter()."""
693
        # there is one and only one upgrade path here.
694
        return ConvertBzrDir4To5()
695
696
    def initialize_on_transport(self, transport):
697
        """Format 4 branches cannot be created."""
698
        raise errors.UninitializableFormat(self)
699
700
    def is_supported(self):
701
        """Format 4 is not supported.
702
703
        It is not supported because the model changed from 4 to 5 and the
704
        conversion logic is expensive - so doing it on the fly was not
705
        feasible.
706
        """
707
        return False
708
709
    def network_name(self):
710
        return self.get_format_string()
711
712
    def _open(self, transport):
713
        """See BzrDirFormat._open."""
714
        return BzrDir4(transport, self)
715
716
    def __return_repository_format(self):
717
        """Circular import protection."""
5582.10.90 by Jelmer Vernooij
Merge weave-bzrdir branch.
718
        from bzrlib.plugins.weave_fmt.repository import RepositoryFormat4
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
719
        return RepositoryFormat4()
720
    repository_format = property(__return_repository_format)
721
6349.2.1 by Jelmer Vernooij
Add BzrDirMetaComponentFormat.
722
    @classmethod
723
    def from_string(cls, format_string):
724
        if format_string != cls.get_format_string():
725
            raise AssertionError("unexpected format string %r" % format_string)
726
        return cls()
727
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
728
729
class BzrDirPreSplitOut(BzrDir):
730
    """A common class for the all-in-one formats."""
731
732
    def __init__(self, _transport, _format):
733
        """See BzrDir.__init__."""
734
        super(BzrDirPreSplitOut, self).__init__(_transport, _format)
735
        self._control_files = lockable_files.LockableFiles(
736
                                            self.get_branch_transport(None),
737
                                            self._format._lock_file_name,
738
                                            self._format._lock_class)
739
740
    def break_lock(self):
741
        """Pre-splitout bzrdirs do not suffer from stale locks."""
742
        raise NotImplementedError(self.break_lock)
743
744
    def cloning_metadir(self, require_stacking=False):
745
        """Produce a metadir suitable for cloning with."""
746
        if require_stacking:
747
            return format_registry.make_bzrdir('1.6')
748
        return self._format.__class__()
749
750
    def clone(self, url, revision_id=None, force_new_repo=False,
751
              preserve_stacking=False):
752
        """See BzrDir.clone().
753
754
        force_new_repo has no effect, since this family of formats always
755
        require a new repository.
756
        preserve_stacking has no effect, since no source branch using this
757
        family of formats can be stacked, so there is no stacking to preserve.
758
        """
759
        self._make_tail(url)
760
        result = self._format._initialize_for_clone(url)
761
        self.open_repository().clone(result, revision_id=revision_id)
762
        from_branch = self.open_branch()
763
        from_branch.clone(result, revision_id=revision_id)
764
        try:
765
            tree = self.open_workingtree()
766
        except errors.NotLocalUrl:
767
            # make a new one, this format always has to have one.
768
            result._init_workingtree()
769
        else:
770
            tree.clone(result)
771
        return result
772
6123.9.12 by Jelmer Vernooij
Add append_revisions_only argument to BranchFormat.initialize.
773
    def create_branch(self, name=None, repository=None,
774
                      append_revisions_only=None):
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
775
        """See BzrDir.create_branch."""
776
        if repository is not None:
777
            raise NotImplementedError(
778
                "create_branch(repository=<not None>) on %r" % (self,))
6123.9.12 by Jelmer Vernooij
Add append_revisions_only argument to BranchFormat.initialize.
779
        return self._format.get_branch_format().initialize(self, name=name,
780
            append_revisions_only=append_revisions_only)
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
781
782
    def destroy_branch(self, name=None):
783
        """See BzrDir.destroy_branch."""
784
        raise errors.UnsupportedOperation(self.destroy_branch, self)
785
786
    def create_repository(self, shared=False):
787
        """See BzrDir.create_repository."""
788
        if shared:
789
            raise errors.IncompatibleFormat('shared repository', self._format)
790
        return self.open_repository()
791
792
    def destroy_repository(self):
793
        """See BzrDir.destroy_repository."""
794
        raise errors.UnsupportedOperation(self.destroy_repository, self)
795
796
    def create_workingtree(self, revision_id=None, from_branch=None,
797
                           accelerator_tree=None, hardlink=False):
798
        """See BzrDir.create_workingtree."""
799
        # The workingtree is sometimes created when the bzrdir is created,
800
        # but not when cloning.
801
802
        # this looks buggy but is not -really-
803
        # because this format creates the workingtree when the bzrdir is
804
        # created
805
        # clone and sprout will have set the revision_id
806
        # and that will have set it for us, its only
807
        # specific uses of create_workingtree in isolation
808
        # that can do wonky stuff here, and that only
809
        # happens for creating checkouts, which cannot be
810
        # done on this format anyway. So - acceptable wart.
811
        if hardlink:
812
            warning("can't support hardlinked working trees in %r"
813
                % (self,))
814
        try:
815
            result = self.open_workingtree(recommend_upgrade=False)
816
        except errors.NoSuchFile:
817
            result = self._init_workingtree()
818
        if revision_id is not None:
819
            if revision_id == _mod_revision.NULL_REVISION:
820
                result.set_parent_ids([])
821
            else:
822
                result.set_parent_ids([revision_id])
823
        return result
824
825
    def _init_workingtree(self):
5582.10.90 by Jelmer Vernooij
Merge weave-bzrdir branch.
826
        from bzrlib.plugins.weave_fmt.workingtree import WorkingTreeFormat2
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
827
        try:
828
            return WorkingTreeFormat2().initialize(self)
829
        except errors.NotLocalUrl:
830
            # Even though we can't access the working tree, we need to
831
            # create its control files.
832
            return WorkingTreeFormat2()._stub_initialize_on_transport(
833
                self.transport, self._control_files._file_mode)
834
835
    def destroy_workingtree(self):
836
        """See BzrDir.destroy_workingtree."""
837
        raise errors.UnsupportedOperation(self.destroy_workingtree, self)
838
839
    def destroy_workingtree_metadata(self):
840
        """See BzrDir.destroy_workingtree_metadata."""
841
        raise errors.UnsupportedOperation(self.destroy_workingtree_metadata,
842
                                          self)
843
844
    def get_branch_transport(self, branch_format, name=None):
845
        """See BzrDir.get_branch_transport()."""
846
        if name is not None:
847
            raise errors.NoColocatedBranchSupport(self)
848
        if branch_format is None:
849
            return self.transport
850
        try:
851
            branch_format.get_format_string()
852
        except NotImplementedError:
853
            return self.transport
854
        raise errors.IncompatibleFormat(branch_format, self._format)
855
856
    def get_repository_transport(self, repository_format):
857
        """See BzrDir.get_repository_transport()."""
858
        if repository_format is None:
859
            return self.transport
860
        try:
861
            repository_format.get_format_string()
862
        except NotImplementedError:
863
            return self.transport
864
        raise errors.IncompatibleFormat(repository_format, self._format)
865
866
    def get_workingtree_transport(self, workingtree_format):
867
        """See BzrDir.get_workingtree_transport()."""
868
        if workingtree_format is None:
869
            return self.transport
870
        try:
871
            workingtree_format.get_format_string()
872
        except NotImplementedError:
873
            return self.transport
874
        raise errors.IncompatibleFormat(workingtree_format, self._format)
875
876
    def needs_format_conversion(self, format=None):
877
        """See BzrDir.needs_format_conversion()."""
878
        # if the format is not the same as the system default,
879
        # an upgrade is needed.
880
        if format is None:
881
            symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
882
                % 'needs_format_conversion(format=None)')
883
            format = BzrDirFormat.get_default_format()
884
        return not isinstance(self._format, format.__class__)
885
886
    def open_branch(self, name=None, unsupported=False,
6305.3.3 by Jelmer Vernooij
Fix use of possible_transports.
887
                    ignore_fallbacks=False, possible_transports=None):
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
888
        """See BzrDir.open_branch."""
5582.10.90 by Jelmer Vernooij
Merge weave-bzrdir branch.
889
        from bzrlib.plugins.weave_fmt.branch import BzrBranchFormat4
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
890
        format = BzrBranchFormat4()
5717.1.10 by Jelmer Vernooij
Fix typo.
891
        format.check_support_status(unsupported)
6305.3.3 by Jelmer Vernooij
Fix use of possible_transports.
892
        return format.open(self, name, _found=True,
893
            possible_transports=possible_transports)
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
894
895
    def sprout(self, url, revision_id=None, force_new_repo=False,
896
               possible_transports=None, accelerator_tree=None,
897
               hardlink=False, stacked=False, create_tree_if_local=True,
898
               source_branch=None):
899
        """See BzrDir.sprout()."""
900
        if source_branch is not None:
901
            my_branch = self.open_branch()
902
            if source_branch.base != my_branch.base:
903
                raise AssertionError(
904
                    "source branch %r is not within %r with branch %r" %
905
                    (source_branch, self, my_branch))
906
        if stacked:
907
            raise errors.UnstackableBranchFormat(
908
                self._format, self.root_transport.base)
909
        if not create_tree_if_local:
910
            raise errors.MustHaveWorkingTree(
911
                self._format, self.root_transport.base)
5582.10.90 by Jelmer Vernooij
Merge weave-bzrdir branch.
912
        from bzrlib.plugins.weave_fmt.workingtree import WorkingTreeFormat2
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
913
        self._make_tail(url)
914
        result = self._format._initialize_for_clone(url)
915
        try:
916
            self.open_repository().clone(result, revision_id=revision_id)
917
        except errors.NoRepositoryPresent:
918
            pass
919
        try:
920
            self.open_branch().sprout(result, revision_id=revision_id)
921
        except errors.NotBranchError:
922
            pass
923
924
        # we always want a working tree
925
        WorkingTreeFormat2().initialize(result,
926
                                        accelerator_tree=accelerator_tree,
927
                                        hardlink=hardlink)
928
        return result
929
930
931
class BzrDir4(BzrDirPreSplitOut):
932
    """A .bzr version 4 control object.
933
934
    This is a deprecated format and may be removed after sept 2006.
935
    """
936
937
    def create_repository(self, shared=False):
938
        """See BzrDir.create_repository."""
939
        return self._format.repository_format.initialize(self, shared)
940
941
    def needs_format_conversion(self, format=None):
942
        """Format 4 dirs are always in need of conversion."""
943
        if format is None:
944
            symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
945
                % 'needs_format_conversion(format=None)')
946
        return True
947
948
    def open_repository(self):
949
        """See BzrDir.open_repository."""
5582.10.90 by Jelmer Vernooij
Merge weave-bzrdir branch.
950
        from bzrlib.plugins.weave_fmt.repository import RepositoryFormat4
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
951
        return RepositoryFormat4().open(self, _found=True)
952
953
954
class BzrDir5(BzrDirPreSplitOut):
955
    """A .bzr version 5 control object.
956
957
    This is a deprecated format and may be removed after sept 2006.
958
    """
959
960
    def has_workingtree(self):
961
        """See BzrDir.has_workingtree."""
962
        return True
963
    
964
    def open_repository(self):
965
        """See BzrDir.open_repository."""
5582.10.90 by Jelmer Vernooij
Merge weave-bzrdir branch.
966
        from bzrlib.plugins.weave_fmt.repository import RepositoryFormat5
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
967
        return RepositoryFormat5().open(self, _found=True)
968
969
    def open_workingtree(self, _unsupported=False,
970
            recommend_upgrade=True):
971
        """See BzrDir.create_workingtree."""
5582.10.90 by Jelmer Vernooij
Merge weave-bzrdir branch.
972
        from bzrlib.plugins.weave_fmt.workingtree import WorkingTreeFormat2
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
973
        wt_format = WorkingTreeFormat2()
974
        # we don't warn here about upgrades; that ought to be handled for the
975
        # bzrdir as a whole
976
        return wt_format.open(self, _found=True)
977
978
979
class BzrDir6(BzrDirPreSplitOut):
980
    """A .bzr version 6 control object.
981
982
    This is a deprecated format and may be removed after sept 2006.
983
    """
984
985
    def has_workingtree(self):
986
        """See BzrDir.has_workingtree."""
987
        return True
988
989
    def open_repository(self):
990
        """See BzrDir.open_repository."""
5582.10.90 by Jelmer Vernooij
Merge weave-bzrdir branch.
991
        from bzrlib.plugins.weave_fmt.repository import RepositoryFormat6
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
992
        return RepositoryFormat6().open(self, _found=True)
993
994
    def open_workingtree(self, _unsupported=False,
995
        recommend_upgrade=True):
996
        """See BzrDir.create_workingtree."""
997
        # we don't warn here about upgrades; that ought to be handled for the
998
        # bzrdir as a whole
5582.10.90 by Jelmer Vernooij
Merge weave-bzrdir branch.
999
        from bzrlib.plugins.weave_fmt.workingtree import WorkingTreeFormat2
5712.4.1 by Jelmer Vernooij
Move weave-era BzrDir directories to a separate file.
1000
        return WorkingTreeFormat2().open(self, _found=True)