~bzr-pqm/bzr/bzr.dev

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