/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/bzrdir.py

Warn if a config variable can't be interpreted as a boolean

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
"""BzrDir logic. The BzrDir is the basic control directory used by bzr.
 
18
 
 
19
At format 7 this was split out into Branch, Repository and Checkout control
 
20
directories.
 
21
 
 
22
Note: This module has a lot of ``open`` functions/methods that return
 
23
references to in-memory objects. As a rule, there are no matching ``close``
 
24
methods. To free any associated resources, simply stop referencing the
 
25
objects returned.
 
26
"""
 
27
 
 
28
# TODO: Move old formats into a plugin to make this file smaller.
 
29
 
 
30
import os
 
31
import sys
 
32
import warnings
 
33
 
 
34
from bzrlib.lazy_import import lazy_import
 
35
lazy_import(globals(), """
 
36
from stat import S_ISDIR
 
37
import textwrap
 
38
 
 
39
import bzrlib
 
40
from bzrlib import (
 
41
    branch,
 
42
    config,
 
43
    errors,
 
44
    graph,
 
45
    lockable_files,
 
46
    lockdir,
 
47
    osutils,
 
48
    remote,
 
49
    repository,
 
50
    revision as _mod_revision,
 
51
    ui,
 
52
    urlutils,
 
53
    versionedfile,
 
54
    win32utils,
 
55
    workingtree,
 
56
    workingtree_4,
 
57
    xml4,
 
58
    xml5,
 
59
    )
 
60
from bzrlib.osutils import (
 
61
    sha_string,
 
62
    )
 
63
from bzrlib.push import (
 
64
    PushResult,
 
65
    )
 
66
from bzrlib.repofmt import pack_repo
 
67
from bzrlib.smart.client import _SmartClient
 
68
from bzrlib.store.versioned import WeaveStore
 
69
from bzrlib.transactions import WriteTransaction
 
70
from bzrlib.transport import (
 
71
    do_catching_redirections,
 
72
    get_transport,
 
73
    local,
 
74
    )
 
75
from bzrlib.weave import Weave
 
76
""")
 
77
 
 
78
from bzrlib.trace import (
 
79
    mutter,
 
80
    note,
 
81
    warning,
 
82
    )
 
83
 
 
84
from bzrlib import (
 
85
    hooks,
 
86
    registry,
 
87
    symbol_versioning,
 
88
    )
 
89
 
 
90
 
 
91
class BzrDir(object):
 
92
    """A .bzr control diretory.
 
93
 
 
94
    BzrDir instances let you create or open any of the things that can be
 
95
    found within .bzr - checkouts, branches and repositories.
 
96
 
 
97
    :ivar transport:
 
98
        the transport which this bzr dir is rooted at (i.e. file:///.../.bzr/)
 
99
    :ivar root_transport:
 
100
        a transport connected to the directory this bzr was opened from
 
101
        (i.e. the parent directory holding the .bzr directory).
 
102
 
 
103
    Everything in the bzrdir should have the same file permissions.
 
104
 
 
105
    :cvar hooks: An instance of BzrDirHooks.
 
106
    """
 
107
 
 
108
    def break_lock(self):
 
109
        """Invoke break_lock on the first object in the bzrdir.
 
110
 
 
111
        If there is a tree, the tree is opened and break_lock() called.
 
112
        Otherwise, branch is tried, and finally repository.
 
113
        """
 
114
        # XXX: This seems more like a UI function than something that really
 
115
        # belongs in this class.
 
116
        try:
 
117
            thing_to_unlock = self.open_workingtree()
 
118
        except (errors.NotLocalUrl, errors.NoWorkingTree):
 
119
            try:
 
120
                thing_to_unlock = self.open_branch()
 
121
            except errors.NotBranchError:
 
122
                try:
 
123
                    thing_to_unlock = self.open_repository()
 
124
                except errors.NoRepositoryPresent:
 
125
                    return
 
126
        thing_to_unlock.break_lock()
 
127
 
 
128
    def can_convert_format(self):
 
129
        """Return true if this bzrdir is one whose format we can convert from."""
 
130
        return True
 
131
 
 
132
    def check_conversion_target(self, target_format):
 
133
        """Check that a bzrdir as a whole can be converted to a new format."""
 
134
        # The only current restriction is that the repository content can be 
 
135
        # fetched compatibly with the target.
 
136
        target_repo_format = target_format.repository_format
 
137
        try:
 
138
            self.open_repository()._format.check_conversion_target(
 
139
                target_repo_format)
 
140
        except errors.NoRepositoryPresent:
 
141
            # No repo, no problem.
 
142
            pass
 
143
 
 
144
    @staticmethod
 
145
    def _check_supported(format, allow_unsupported,
 
146
        recommend_upgrade=True,
 
147
        basedir=None):
 
148
        """Give an error or warning on old formats.
 
149
 
 
150
        :param format: may be any kind of format - workingtree, branch,
 
151
        or repository.
 
152
 
 
153
        :param allow_unsupported: If true, allow opening
 
154
        formats that are strongly deprecated, and which may
 
155
        have limited functionality.
 
156
 
 
157
        :param recommend_upgrade: If true (default), warn
 
158
        the user through the ui object that they may wish
 
159
        to upgrade the object.
 
160
        """
 
161
        # TODO: perhaps move this into a base Format class; it's not BzrDir
 
162
        # specific. mbp 20070323
 
163
        if not allow_unsupported and not format.is_supported():
 
164
            # see open_downlevel to open legacy branches.
 
165
            raise errors.UnsupportedFormatError(format=format)
 
166
        if recommend_upgrade \
 
167
            and getattr(format, 'upgrade_recommended', False):
 
168
            ui.ui_factory.recommend_upgrade(
 
169
                format.get_format_description(),
 
170
                basedir)
 
171
 
 
172
    def clone(self, url, revision_id=None, force_new_repo=False,
 
173
              preserve_stacking=False):
 
174
        """Clone this bzrdir and its contents to url verbatim.
 
175
 
 
176
        :param url: The url create the clone at.  If url's last component does
 
177
            not exist, it will be created.
 
178
        :param revision_id: The tip revision-id to use for any branch or
 
179
            working tree.  If not None, then the clone operation may tune
 
180
            itself to download less data.
 
181
        :param force_new_repo: Do not use a shared repository for the target
 
182
                               even if one is available.
 
183
        :param preserve_stacking: When cloning a stacked branch, stack the
 
184
            new branch on top of the other branch's stacked-on branch.
 
185
        """
 
186
        return self.clone_on_transport(get_transport(url),
 
187
                                       revision_id=revision_id,
 
188
                                       force_new_repo=force_new_repo,
 
189
                                       preserve_stacking=preserve_stacking)
 
190
 
 
191
    def clone_on_transport(self, transport, revision_id=None,
 
192
        force_new_repo=False, preserve_stacking=False, stacked_on=None,
 
193
        create_prefix=False, use_existing_dir=True):
 
194
        """Clone this bzrdir and its contents to transport verbatim.
 
195
 
 
196
        :param transport: The transport for the location to produce the clone
 
197
            at.  If the target directory does not exist, it will be created.
 
198
        :param revision_id: The tip revision-id to use for any branch or
 
199
            working tree.  If not None, then the clone operation may tune
 
200
            itself to download less data.
 
201
        :param force_new_repo: Do not use a shared repository for the target,
 
202
                               even if one is available.
 
203
        :param preserve_stacking: When cloning a stacked branch, stack the
 
204
            new branch on top of the other branch's stacked-on branch.
 
205
        :param create_prefix: Create any missing directories leading up to
 
206
            to_transport.
 
207
        :param use_existing_dir: Use an existing directory if one exists.
 
208
        """
 
209
        # Overview: put together a broad description of what we want to end up
 
210
        # with; then make as few api calls as possible to do it.
 
211
        
 
212
        # We may want to create a repo/branch/tree, if we do so what format
 
213
        # would we want for each:
 
214
        require_stacking = (stacked_on is not None)
 
215
        format = self.cloning_metadir(require_stacking)
 
216
        
 
217
        # Figure out what objects we want:
 
218
        try:
 
219
            local_repo = self.find_repository()
 
220
        except errors.NoRepositoryPresent:
 
221
            local_repo = None
 
222
        try:
 
223
            local_branch = self.open_branch()
 
224
        except errors.NotBranchError:
 
225
            local_branch = None
 
226
        else:
 
227
            # enable fallbacks when branch is not a branch reference
 
228
            if local_branch.repository.has_same_location(local_repo):
 
229
                local_repo = local_branch.repository
 
230
            if preserve_stacking:
 
231
                try:
 
232
                    stacked_on = local_branch.get_stacked_on_url()
 
233
                except (errors.UnstackableBranchFormat,
 
234
                        errors.UnstackableRepositoryFormat,
 
235
                        errors.NotStacked):
 
236
                    pass
 
237
        # Bug: We create a metadir without knowing if it can support stacking,
 
238
        # we should look up the policy needs first, or just use it as a hint,
 
239
        # or something.
 
240
        if local_repo:
 
241
            make_working_trees = local_repo.make_working_trees()
 
242
            want_shared = local_repo.is_shared()
 
243
            repo_format_name = format.repository_format.network_name()
 
244
        else:
 
245
            make_working_trees = False
 
246
            want_shared = False
 
247
            repo_format_name = None
 
248
 
 
249
        result_repo, result, require_stacking, repository_policy = \
 
250
            format.initialize_on_transport_ex(transport,
 
251
            use_existing_dir=use_existing_dir, create_prefix=create_prefix,
 
252
            force_new_repo=force_new_repo, stacked_on=stacked_on,
 
253
            stack_on_pwd=self.root_transport.base,
 
254
            repo_format_name=repo_format_name,
 
255
            make_working_trees=make_working_trees, shared_repo=want_shared)
 
256
        if repo_format_name:
 
257
            try:
 
258
                # If the result repository is in the same place as the
 
259
                # resulting bzr dir, it will have no content, further if the
 
260
                # result is not stacked then we know all content should be
 
261
                # copied, and finally if we are copying up to a specific
 
262
                # revision_id then we can use the pending-ancestry-result which
 
263
                # does not require traversing all of history to describe it.
 
264
                if (result_repo.bzrdir.root_transport.base ==
 
265
                    result.root_transport.base and not require_stacking and
 
266
                    revision_id is not None):
 
267
                    fetch_spec = graph.PendingAncestryResult(
 
268
                        [revision_id], local_repo)
 
269
                    result_repo.fetch(local_repo, fetch_spec=fetch_spec)
 
270
                else:
 
271
                    result_repo.fetch(local_repo, revision_id=revision_id)
 
272
            finally:
 
273
                result_repo.unlock()
 
274
        else:
 
275
            if result_repo is not None:
 
276
                raise AssertionError('result_repo not None(%r)' % result_repo)
 
277
        # 1 if there is a branch present
 
278
        #   make sure its content is available in the target repository
 
279
        #   clone it.
 
280
        if local_branch is not None:
 
281
            result_branch = local_branch.clone(result, revision_id=revision_id,
 
282
                repository_policy=repository_policy)
 
283
        try:
 
284
            # Cheaper to check if the target is not local, than to try making
 
285
            # the tree and fail.
 
286
            result.root_transport.local_abspath('.')
 
287
            if result_repo is None or result_repo.make_working_trees():
 
288
                self.open_workingtree().clone(result)
 
289
        except (errors.NoWorkingTree, errors.NotLocalUrl):
 
290
            pass
 
291
        return result
 
292
 
 
293
    # TODO: This should be given a Transport, and should chdir up; otherwise
 
294
    # this will open a new connection.
 
295
    def _make_tail(self, url):
 
296
        t = get_transport(url)
 
297
        t.ensure_base()
 
298
 
 
299
    @classmethod
 
300
    def create(cls, base, format=None, possible_transports=None):
 
301
        """Create a new BzrDir at the url 'base'.
 
302
 
 
303
        :param format: If supplied, the format of branch to create.  If not
 
304
            supplied, the default is used.
 
305
        :param possible_transports: If supplied, a list of transports that
 
306
            can be reused to share a remote connection.
 
307
        """
 
308
        if cls is not BzrDir:
 
309
            raise AssertionError("BzrDir.create always creates the default"
 
310
                " format, not one of %r" % cls)
 
311
        t = get_transport(base, possible_transports)
 
312
        t.ensure_base()
 
313
        if format is None:
 
314
            format = BzrDirFormat.get_default_format()
 
315
        return format.initialize_on_transport(t)
 
316
 
 
317
    @staticmethod
 
318
    def find_bzrdirs(transport, evaluate=None, list_current=None):
 
319
        """Find bzrdirs recursively from current location.
 
320
 
 
321
        This is intended primarily as a building block for more sophisticated
 
322
        functionality, like finding trees under a directory, or finding
 
323
        branches that use a given repository.
 
324
        :param evaluate: An optional callable that yields recurse, value,
 
325
            where recurse controls whether this bzrdir is recursed into
 
326
            and value is the value to yield.  By default, all bzrdirs
 
327
            are recursed into, and the return value is the bzrdir.
 
328
        :param list_current: if supplied, use this function to list the current
 
329
            directory, instead of Transport.list_dir
 
330
        :return: a generator of found bzrdirs, or whatever evaluate returns.
 
331
        """
 
332
        if list_current is None:
 
333
            def list_current(transport):
 
334
                return transport.list_dir('')
 
335
        if evaluate is None:
 
336
            def evaluate(bzrdir):
 
337
                return True, bzrdir
 
338
 
 
339
        pending = [transport]
 
340
        while len(pending) > 0:
 
341
            current_transport = pending.pop()
 
342
            recurse = True
 
343
            try:
 
344
                bzrdir = BzrDir.open_from_transport(current_transport)
 
345
            except errors.NotBranchError:
 
346
                pass
 
347
            else:
 
348
                recurse, value = evaluate(bzrdir)
 
349
                yield value
 
350
            try:
 
351
                subdirs = list_current(current_transport)
 
352
            except errors.NoSuchFile:
 
353
                continue
 
354
            if recurse:
 
355
                for subdir in sorted(subdirs, reverse=True):
 
356
                    pending.append(current_transport.clone(subdir))
 
357
 
 
358
    def list_branches(self):
 
359
        """Return a sequence of all branches local to this control directory.
 
360
 
 
361
        """
 
362
        try:
 
363
            return [self.open_branch()]
 
364
        except errors.NotBranchError:
 
365
            return []
 
366
 
 
367
    @staticmethod
 
368
    def find_branches(transport):
 
369
        """Find all branches under a transport.
 
370
 
 
371
        This will find all branches below the transport, including branches
 
372
        inside other branches.  Where possible, it will use
 
373
        Repository.find_branches.
 
374
 
 
375
        To list all the branches that use a particular Repository, see
 
376
        Repository.find_branches
 
377
        """
 
378
        def evaluate(bzrdir):
 
379
            try:
 
380
                repository = bzrdir.open_repository()
 
381
            except errors.NoRepositoryPresent:
 
382
                pass
 
383
            else:
 
384
                return False, ([], repository)
 
385
            return True, (bzrdir.list_branches(), None)
 
386
        ret = []
 
387
        for branches, repo in BzrDir.find_bzrdirs(transport,
 
388
                                                  evaluate=evaluate):
 
389
            if repo is not None:
 
390
                ret.extend(repo.find_branches())
 
391
            if branches is not None:
 
392
                ret.extend(branches)
 
393
        return ret
 
394
 
 
395
    def destroy_repository(self):
 
396
        """Destroy the repository in this BzrDir"""
 
397
        raise NotImplementedError(self.destroy_repository)
 
398
 
 
399
    def create_branch(self, name=None):
 
400
        """Create a branch in this BzrDir.
 
401
 
 
402
        :param name: Name of the colocated branch to create, None for
 
403
            the default branch.
 
404
 
 
405
        The bzrdir's format will control what branch format is created.
 
406
        For more control see BranchFormatXX.create(a_bzrdir).
 
407
        """
 
408
        raise NotImplementedError(self.create_branch)
 
409
 
 
410
    def destroy_branch(self, name=None):
 
411
        """Destroy a branch in this BzrDir.
 
412
        
 
413
        :param name: Name of the branch to destroy, None for the default 
 
414
            branch.
 
415
        """
 
416
        raise NotImplementedError(self.destroy_branch)
 
417
 
 
418
    @staticmethod
 
419
    def create_branch_and_repo(base, force_new_repo=False, format=None):
 
420
        """Create a new BzrDir, Branch and Repository at the url 'base'.
 
421
 
 
422
        This will use the current default BzrDirFormat unless one is
 
423
        specified, and use whatever
 
424
        repository format that that uses via bzrdir.create_branch and
 
425
        create_repository. If a shared repository is available that is used
 
426
        preferentially.
 
427
 
 
428
        The created Branch object is returned.
 
429
 
 
430
        :param base: The URL to create the branch at.
 
431
        :param force_new_repo: If True a new repository is always created.
 
432
        :param format: If supplied, the format of branch to create.  If not
 
433
            supplied, the default is used.
 
434
        """
 
435
        bzrdir = BzrDir.create(base, format)
 
436
        bzrdir._find_or_create_repository(force_new_repo)
 
437
        return bzrdir.create_branch()
 
438
 
 
439
    def determine_repository_policy(self, force_new_repo=False, stack_on=None,
 
440
                                    stack_on_pwd=None, require_stacking=False):
 
441
        """Return an object representing a policy to use.
 
442
 
 
443
        This controls whether a new repository is created, and the format of
 
444
        that repository, or some existing shared repository used instead.
 
445
 
 
446
        If stack_on is supplied, will not seek a containing shared repo.
 
447
 
 
448
        :param force_new_repo: If True, require a new repository to be created.
 
449
        :param stack_on: If supplied, the location to stack on.  If not
 
450
            supplied, a default_stack_on location may be used.
 
451
        :param stack_on_pwd: If stack_on is relative, the location it is
 
452
            relative to.
 
453
        """
 
454
        def repository_policy(found_bzrdir):
 
455
            stack_on = None
 
456
            stack_on_pwd = None
 
457
            config = found_bzrdir.get_config()
 
458
            stop = False
 
459
            stack_on = config.get_default_stack_on()
 
460
            if stack_on is not None:
 
461
                stack_on_pwd = found_bzrdir.root_transport.base
 
462
                stop = True
 
463
            # does it have a repository ?
 
464
            try:
 
465
                repository = found_bzrdir.open_repository()
 
466
            except errors.NoRepositoryPresent:
 
467
                repository = None
 
468
            else:
 
469
                if ((found_bzrdir.root_transport.base !=
 
470
                     self.root_transport.base) and not repository.is_shared()):
 
471
                    # Don't look higher, can't use a higher shared repo.
 
472
                    repository = None
 
473
                    stop = True
 
474
                else:
 
475
                    stop = True
 
476
            if not stop:
 
477
                return None, False
 
478
            if repository:
 
479
                return UseExistingRepository(repository, stack_on,
 
480
                    stack_on_pwd, require_stacking=require_stacking), True
 
481
            else:
 
482
                return CreateRepository(self, stack_on, stack_on_pwd,
 
483
                    require_stacking=require_stacking), True
 
484
 
 
485
        if not force_new_repo:
 
486
            if stack_on is None:
 
487
                policy = self._find_containing(repository_policy)
 
488
                if policy is not None:
 
489
                    return policy
 
490
            else:
 
491
                try:
 
492
                    return UseExistingRepository(self.open_repository(),
 
493
                        stack_on, stack_on_pwd,
 
494
                        require_stacking=require_stacking)
 
495
                except errors.NoRepositoryPresent:
 
496
                    pass
 
497
        return CreateRepository(self, stack_on, stack_on_pwd,
 
498
                                require_stacking=require_stacking)
 
499
 
 
500
    def _find_or_create_repository(self, force_new_repo):
 
501
        """Create a new repository if needed, returning the repository."""
 
502
        policy = self.determine_repository_policy(force_new_repo)
 
503
        return policy.acquire_repository()[0]
 
504
 
 
505
    @staticmethod
 
506
    def create_branch_convenience(base, force_new_repo=False,
 
507
                                  force_new_tree=None, format=None,
 
508
                                  possible_transports=None):
 
509
        """Create a new BzrDir, Branch and Repository at the url 'base'.
 
510
 
 
511
        This is a convenience function - it will use an existing repository
 
512
        if possible, can be told explicitly whether to create a working tree or
 
513
        not.
 
514
 
 
515
        This will use the current default BzrDirFormat unless one is
 
516
        specified, and use whatever
 
517
        repository format that that uses via bzrdir.create_branch and
 
518
        create_repository. If a shared repository is available that is used
 
519
        preferentially. Whatever repository is used, its tree creation policy
 
520
        is followed.
 
521
 
 
522
        The created Branch object is returned.
 
523
        If a working tree cannot be made due to base not being a file:// url,
 
524
        no error is raised unless force_new_tree is True, in which case no
 
525
        data is created on disk and NotLocalUrl is raised.
 
526
 
 
527
        :param base: The URL to create the branch at.
 
528
        :param force_new_repo: If True a new repository is always created.
 
529
        :param force_new_tree: If True or False force creation of a tree or
 
530
                               prevent such creation respectively.
 
531
        :param format: Override for the bzrdir format to create.
 
532
        :param possible_transports: An optional reusable transports list.
 
533
        """
 
534
        if force_new_tree:
 
535
            # check for non local urls
 
536
            t = get_transport(base, possible_transports)
 
537
            if not isinstance(t, local.LocalTransport):
 
538
                raise errors.NotLocalUrl(base)
 
539
        bzrdir = BzrDir.create(base, format, possible_transports)
 
540
        repo = bzrdir._find_or_create_repository(force_new_repo)
 
541
        result = bzrdir.create_branch()
 
542
        if force_new_tree or (repo.make_working_trees() and
 
543
                              force_new_tree is None):
 
544
            try:
 
545
                bzrdir.create_workingtree()
 
546
            except errors.NotLocalUrl:
 
547
                pass
 
548
        return result
 
549
 
 
550
    @staticmethod
 
551
    def create_standalone_workingtree(base, format=None):
 
552
        """Create a new BzrDir, WorkingTree, Branch and Repository at 'base'.
 
553
 
 
554
        'base' must be a local path or a file:// url.
 
555
 
 
556
        This will use the current default BzrDirFormat unless one is
 
557
        specified, and use whatever
 
558
        repository format that that uses for bzrdirformat.create_workingtree,
 
559
        create_branch and create_repository.
 
560
 
 
561
        :param format: Override for the bzrdir format to create.
 
562
        :return: The WorkingTree object.
 
563
        """
 
564
        t = get_transport(base)
 
565
        if not isinstance(t, local.LocalTransport):
 
566
            raise errors.NotLocalUrl(base)
 
567
        bzrdir = BzrDir.create_branch_and_repo(base,
 
568
                                               force_new_repo=True,
 
569
                                               format=format).bzrdir
 
570
        return bzrdir.create_workingtree()
 
571
 
 
572
    def create_workingtree(self, revision_id=None, from_branch=None,
 
573
        accelerator_tree=None, hardlink=False):
 
574
        """Create a working tree at this BzrDir.
 
575
 
 
576
        :param revision_id: create it as of this revision id.
 
577
        :param from_branch: override bzrdir branch (for lightweight checkouts)
 
578
        :param accelerator_tree: A tree which can be used for retrieving file
 
579
            contents more quickly than the revision tree, i.e. a workingtree.
 
580
            The revision tree will be used for cases where accelerator_tree's
 
581
            content is different.
 
582
        """
 
583
        raise NotImplementedError(self.create_workingtree)
 
584
 
 
585
    def backup_bzrdir(self):
 
586
        """Backup this bzr control directory.
 
587
 
 
588
        :return: Tuple with old path name and new path name
 
589
        """
 
590
        def name_gen(base='backup.bzr'):
 
591
            counter = 1
 
592
            name = "%s.~%d~" % (base, counter)
 
593
            while self.root_transport.has(name):
 
594
                counter += 1
 
595
                name = "%s.~%d~" % (base, counter)
 
596
            return name
 
597
 
 
598
        backup_dir=name_gen()
 
599
        pb = ui.ui_factory.nested_progress_bar()
 
600
        try:
 
601
            # FIXME: bug 300001 -- the backup fails if the backup directory
 
602
            # already exists, but it should instead either remove it or make
 
603
            # a new backup directory.
 
604
            #
 
605
            old_path = self.root_transport.abspath('.bzr')
 
606
            new_path = self.root_transport.abspath(backup_dir)
 
607
            ui.ui_factory.note('making backup of %s\n  to %s' % (old_path, new_path,))
 
608
            self.root_transport.copy_tree('.bzr', backup_dir)
 
609
            return (old_path, new_path)
 
610
        finally:
 
611
            pb.finished()
 
612
 
 
613
    def retire_bzrdir(self, limit=10000):
 
614
        """Permanently disable the bzrdir.
 
615
 
 
616
        This is done by renaming it to give the user some ability to recover
 
617
        if there was a problem.
 
618
 
 
619
        This will have horrible consequences if anyone has anything locked or
 
620
        in use.
 
621
        :param limit: number of times to retry
 
622
        """
 
623
        i  = 0
 
624
        while True:
 
625
            try:
 
626
                to_path = '.bzr.retired.%d' % i
 
627
                self.root_transport.rename('.bzr', to_path)
 
628
                note("renamed %s to %s"
 
629
                    % (self.root_transport.abspath('.bzr'), to_path))
 
630
                return
 
631
            except (errors.TransportError, IOError, errors.PathError):
 
632
                i += 1
 
633
                if i > limit:
 
634
                    raise
 
635
                else:
 
636
                    pass
 
637
 
 
638
    def destroy_workingtree(self):
 
639
        """Destroy the working tree at this BzrDir.
 
640
 
 
641
        Formats that do not support this may raise UnsupportedOperation.
 
642
        """
 
643
        raise NotImplementedError(self.destroy_workingtree)
 
644
 
 
645
    def destroy_workingtree_metadata(self):
 
646
        """Destroy the control files for the working tree at this BzrDir.
 
647
 
 
648
        The contents of working tree files are not affected.
 
649
        Formats that do not support this may raise UnsupportedOperation.
 
650
        """
 
651
        raise NotImplementedError(self.destroy_workingtree_metadata)
 
652
 
 
653
    def _find_containing(self, evaluate):
 
654
        """Find something in a containing control directory.
 
655
 
 
656
        This method will scan containing control dirs, until it finds what
 
657
        it is looking for, decides that it will never find it, or runs out
 
658
        of containing control directories to check.
 
659
 
 
660
        It is used to implement find_repository and
 
661
        determine_repository_policy.
 
662
 
 
663
        :param evaluate: A function returning (value, stop).  If stop is True,
 
664
            the value will be returned.
 
665
        """
 
666
        found_bzrdir = self
 
667
        while True:
 
668
            result, stop = evaluate(found_bzrdir)
 
669
            if stop:
 
670
                return result
 
671
            next_transport = found_bzrdir.root_transport.clone('..')
 
672
            if (found_bzrdir.root_transport.base == next_transport.base):
 
673
                # top of the file system
 
674
                return None
 
675
            # find the next containing bzrdir
 
676
            try:
 
677
                found_bzrdir = BzrDir.open_containing_from_transport(
 
678
                    next_transport)[0]
 
679
            except errors.NotBranchError:
 
680
                return None
 
681
 
 
682
    def find_repository(self):
 
683
        """Find the repository that should be used.
 
684
 
 
685
        This does not require a branch as we use it to find the repo for
 
686
        new branches as well as to hook existing branches up to their
 
687
        repository.
 
688
        """
 
689
        def usable_repository(found_bzrdir):
 
690
            # does it have a repository ?
 
691
            try:
 
692
                repository = found_bzrdir.open_repository()
 
693
            except errors.NoRepositoryPresent:
 
694
                return None, False
 
695
            if found_bzrdir.root_transport.base == self.root_transport.base:
 
696
                return repository, True
 
697
            elif repository.is_shared():
 
698
                return repository, True
 
699
            else:
 
700
                return None, True
 
701
 
 
702
        found_repo = self._find_containing(usable_repository)
 
703
        if found_repo is None:
 
704
            raise errors.NoRepositoryPresent(self)
 
705
        return found_repo
 
706
 
 
707
    def get_branch_reference(self):
 
708
        """Return the referenced URL for the branch in this bzrdir.
 
709
 
 
710
        :raises NotBranchError: If there is no Branch.
 
711
        :return: The URL the branch in this bzrdir references if it is a
 
712
            reference branch, or None for regular branches.
 
713
        """
 
714
        return None
 
715
 
 
716
    def get_branch_transport(self, branch_format, name=None):
 
717
        """Get the transport for use by branch format in this BzrDir.
 
718
 
 
719
        Note that bzr dirs that do not support format strings will raise
 
720
        IncompatibleFormat if the branch format they are given has
 
721
        a format string, and vice versa.
 
722
 
 
723
        If branch_format is None, the transport is returned with no
 
724
        checking. If it is not None, then the returned transport is
 
725
        guaranteed to point to an existing directory ready for use.
 
726
        """
 
727
        raise NotImplementedError(self.get_branch_transport)
 
728
 
 
729
    def _find_creation_modes(self):
 
730
        """Determine the appropriate modes for files and directories.
 
731
 
 
732
        They're always set to be consistent with the base directory,
 
733
        assuming that this transport allows setting modes.
 
734
        """
 
735
        # TODO: Do we need or want an option (maybe a config setting) to turn
 
736
        # this off or override it for particular locations? -- mbp 20080512
 
737
        if self._mode_check_done:
 
738
            return
 
739
        self._mode_check_done = True
 
740
        try:
 
741
            st = self.transport.stat('.')
 
742
        except errors.TransportNotPossible:
 
743
            self._dir_mode = None
 
744
            self._file_mode = None
 
745
        else:
 
746
            # Check the directory mode, but also make sure the created
 
747
            # directories and files are read-write for this user. This is
 
748
            # mostly a workaround for filesystems which lie about being able to
 
749
            # write to a directory (cygwin & win32)
 
750
            if (st.st_mode & 07777 == 00000):
 
751
                # FTP allows stat but does not return dir/file modes
 
752
                self._dir_mode = None
 
753
                self._file_mode = None
 
754
            else:
 
755
                self._dir_mode = (st.st_mode & 07777) | 00700
 
756
                # Remove the sticky and execute bits for files
 
757
                self._file_mode = self._dir_mode & ~07111
 
758
 
 
759
    def _get_file_mode(self):
 
760
        """Return Unix mode for newly created files, or None.
 
761
        """
 
762
        if not self._mode_check_done:
 
763
            self._find_creation_modes()
 
764
        return self._file_mode
 
765
 
 
766
    def _get_dir_mode(self):
 
767
        """Return Unix mode for newly created directories, or None.
 
768
        """
 
769
        if not self._mode_check_done:
 
770
            self._find_creation_modes()
 
771
        return self._dir_mode
 
772
 
 
773
    def get_repository_transport(self, repository_format):
 
774
        """Get the transport for use by repository format in this BzrDir.
 
775
 
 
776
        Note that bzr dirs that do not support format strings will raise
 
777
        IncompatibleFormat if the repository format they are given has
 
778
        a format string, and vice versa.
 
779
 
 
780
        If repository_format is None, the transport is returned with no
 
781
        checking. If it is not None, then the returned transport is
 
782
        guaranteed to point to an existing directory ready for use.
 
783
        """
 
784
        raise NotImplementedError(self.get_repository_transport)
 
785
 
 
786
    def get_workingtree_transport(self, tree_format):
 
787
        """Get the transport for use by workingtree format in this BzrDir.
 
788
 
 
789
        Note that bzr dirs that do not support format strings will raise
 
790
        IncompatibleFormat if the workingtree format they are given has a
 
791
        format string, and vice versa.
 
792
 
 
793
        If workingtree_format is None, the transport is returned with no
 
794
        checking. If it is not None, then the returned transport is
 
795
        guaranteed to point to an existing directory ready for use.
 
796
        """
 
797
        raise NotImplementedError(self.get_workingtree_transport)
 
798
 
 
799
    def get_config(self):
 
800
        """Get configuration for this BzrDir."""
 
801
        return config.BzrDirConfig(self)
 
802
 
 
803
    def _get_config(self):
 
804
        """By default, no configuration is available."""
 
805
        return None
 
806
 
 
807
    def __init__(self, _transport, _format):
 
808
        """Initialize a Bzr control dir object.
 
809
 
 
810
        Only really common logic should reside here, concrete classes should be
 
811
        made with varying behaviours.
 
812
 
 
813
        :param _format: the format that is creating this BzrDir instance.
 
814
        :param _transport: the transport this dir is based at.
 
815
        """
 
816
        self._format = _format
 
817
        self.transport = _transport.clone('.bzr')
 
818
        self.root_transport = _transport
 
819
        self._mode_check_done = False
 
820
 
 
821
    def is_control_filename(self, filename):
 
822
        """True if filename is the name of a path which is reserved for bzrdir's.
 
823
 
 
824
        :param filename: A filename within the root transport of this bzrdir.
 
825
 
 
826
        This is true IF and ONLY IF the filename is part of the namespace reserved
 
827
        for bzr control dirs. Currently this is the '.bzr' directory in the root
 
828
        of the root_transport. it is expected that plugins will need to extend
 
829
        this in the future - for instance to make bzr talk with svn working
 
830
        trees.
 
831
        """
 
832
        # this might be better on the BzrDirFormat class because it refers to
 
833
        # all the possible bzrdir disk formats.
 
834
        # This method is tested via the workingtree is_control_filename tests-
 
835
        # it was extracted from WorkingTree.is_control_filename. If the method's
 
836
        # contract is extended beyond the current trivial implementation, please
 
837
        # add new tests for it to the appropriate place.
 
838
        return filename == '.bzr' or filename.startswith('.bzr/')
 
839
 
 
840
    def needs_format_conversion(self, format=None):
 
841
        """Return true if this bzrdir needs convert_format run on it.
 
842
 
 
843
        For instance, if the repository format is out of date but the
 
844
        branch and working tree are not, this should return True.
 
845
 
 
846
        :param format: Optional parameter indicating a specific desired
 
847
                       format we plan to arrive at.
 
848
        """
 
849
        raise NotImplementedError(self.needs_format_conversion)
 
850
 
 
851
    @staticmethod
 
852
    def open_unsupported(base):
 
853
        """Open a branch which is not supported."""
 
854
        return BzrDir.open(base, _unsupported=True)
 
855
 
 
856
    @staticmethod
 
857
    def open(base, _unsupported=False, possible_transports=None):
 
858
        """Open an existing bzrdir, rooted at 'base' (url).
 
859
 
 
860
        :param _unsupported: a private parameter to the BzrDir class.
 
861
        """
 
862
        t = get_transport(base, possible_transports=possible_transports)
 
863
        return BzrDir.open_from_transport(t, _unsupported=_unsupported)
 
864
 
 
865
    @staticmethod
 
866
    def open_from_transport(transport, _unsupported=False,
 
867
                            _server_formats=True):
 
868
        """Open a bzrdir within a particular directory.
 
869
 
 
870
        :param transport: Transport containing the bzrdir.
 
871
        :param _unsupported: private.
 
872
        """
 
873
        for hook in BzrDir.hooks['pre_open']:
 
874
            hook(transport)
 
875
        # Keep initial base since 'transport' may be modified while following
 
876
        # the redirections.
 
877
        base = transport.base
 
878
        def find_format(transport):
 
879
            return transport, BzrDirFormat.find_format(
 
880
                transport, _server_formats=_server_formats)
 
881
 
 
882
        def redirected(transport, e, redirection_notice):
 
883
            redirected_transport = transport._redirected_to(e.source, e.target)
 
884
            if redirected_transport is None:
 
885
                raise errors.NotBranchError(base)
 
886
            note('%s is%s redirected to %s',
 
887
                 transport.base, e.permanently, redirected_transport.base)
 
888
            return redirected_transport
 
889
 
 
890
        try:
 
891
            transport, format = do_catching_redirections(find_format,
 
892
                                                         transport,
 
893
                                                         redirected)
 
894
        except errors.TooManyRedirections:
 
895
            raise errors.NotBranchError(base)
 
896
 
 
897
        BzrDir._check_supported(format, _unsupported)
 
898
        return format.open(transport, _found=True)
 
899
 
 
900
    def open_branch(self, name=None, unsupported=False,
 
901
                    ignore_fallbacks=False):
 
902
        """Open the branch object at this BzrDir if one is present.
 
903
 
 
904
        If unsupported is True, then no longer supported branch formats can
 
905
        still be opened.
 
906
 
 
907
        TODO: static convenience version of this?
 
908
        """
 
909
        raise NotImplementedError(self.open_branch)
 
910
 
 
911
    @staticmethod
 
912
    def open_containing(url, possible_transports=None):
 
913
        """Open an existing branch which contains url.
 
914
 
 
915
        :param url: url to search from.
 
916
        See open_containing_from_transport for more detail.
 
917
        """
 
918
        transport = get_transport(url, possible_transports)
 
919
        return BzrDir.open_containing_from_transport(transport)
 
920
 
 
921
    @staticmethod
 
922
    def open_containing_from_transport(a_transport):
 
923
        """Open an existing branch which contains a_transport.base.
 
924
 
 
925
        This probes for a branch at a_transport, and searches upwards from there.
 
926
 
 
927
        Basically we keep looking up until we find the control directory or
 
928
        run into the root.  If there isn't one, raises NotBranchError.
 
929
        If there is one and it is either an unrecognised format or an unsupported
 
930
        format, UnknownFormatError or UnsupportedFormatError are raised.
 
931
        If there is one, it is returned, along with the unused portion of url.
 
932
 
 
933
        :return: The BzrDir that contains the path, and a Unicode path
 
934
                for the rest of the URL.
 
935
        """
 
936
        # this gets the normalised url back. I.e. '.' -> the full path.
 
937
        url = a_transport.base
 
938
        while True:
 
939
            try:
 
940
                result = BzrDir.open_from_transport(a_transport)
 
941
                return result, urlutils.unescape(a_transport.relpath(url))
 
942
            except errors.NotBranchError, e:
 
943
                pass
 
944
            try:
 
945
                new_t = a_transport.clone('..')
 
946
            except errors.InvalidURLJoin:
 
947
                # reached the root, whatever that may be
 
948
                raise errors.NotBranchError(path=url)
 
949
            if new_t.base == a_transport.base:
 
950
                # reached the root, whatever that may be
 
951
                raise errors.NotBranchError(path=url)
 
952
            a_transport = new_t
 
953
 
 
954
    def _get_tree_branch(self):
 
955
        """Return the branch and tree, if any, for this bzrdir.
 
956
 
 
957
        Return None for tree if not present or inaccessible.
 
958
        Raise NotBranchError if no branch is present.
 
959
        :return: (tree, branch)
 
960
        """
 
961
        try:
 
962
            tree = self.open_workingtree()
 
963
        except (errors.NoWorkingTree, errors.NotLocalUrl):
 
964
            tree = None
 
965
            branch = self.open_branch()
 
966
        else:
 
967
            branch = tree.branch
 
968
        return tree, branch
 
969
 
 
970
    @classmethod
 
971
    def open_tree_or_branch(klass, location):
 
972
        """Return the branch and working tree at a location.
 
973
 
 
974
        If there is no tree at the location, tree will be None.
 
975
        If there is no branch at the location, an exception will be
 
976
        raised
 
977
        :return: (tree, branch)
 
978
        """
 
979
        bzrdir = klass.open(location)
 
980
        return bzrdir._get_tree_branch()
 
981
 
 
982
    @classmethod
 
983
    def open_containing_tree_or_branch(klass, location):
 
984
        """Return the branch and working tree contained by a location.
 
985
 
 
986
        Returns (tree, branch, relpath).
 
987
        If there is no tree at containing the location, tree will be None.
 
988
        If there is no branch containing the location, an exception will be
 
989
        raised
 
990
        relpath is the portion of the path that is contained by the branch.
 
991
        """
 
992
        bzrdir, relpath = klass.open_containing(location)
 
993
        tree, branch = bzrdir._get_tree_branch()
 
994
        return tree, branch, relpath
 
995
 
 
996
    @classmethod
 
997
    def open_containing_tree_branch_or_repository(klass, location):
 
998
        """Return the working tree, branch and repo contained by a location.
 
999
 
 
1000
        Returns (tree, branch, repository, relpath).
 
1001
        If there is no tree containing the location, tree will be None.
 
1002
        If there is no branch containing the location, branch will be None.
 
1003
        If there is no repository containing the location, repository will be
 
1004
        None.
 
1005
        relpath is the portion of the path that is contained by the innermost
 
1006
        BzrDir.
 
1007
 
 
1008
        If no tree, branch or repository is found, a NotBranchError is raised.
 
1009
        """
 
1010
        bzrdir, relpath = klass.open_containing(location)
 
1011
        try:
 
1012
            tree, branch = bzrdir._get_tree_branch()
 
1013
        except errors.NotBranchError:
 
1014
            try:
 
1015
                repo = bzrdir.find_repository()
 
1016
                return None, None, repo, relpath
 
1017
            except (errors.NoRepositoryPresent):
 
1018
                raise errors.NotBranchError(location)
 
1019
        return tree, branch, branch.repository, relpath
 
1020
 
 
1021
    def open_repository(self, _unsupported=False):
 
1022
        """Open the repository object at this BzrDir if one is present.
 
1023
 
 
1024
        This will not follow the Branch object pointer - it's strictly a direct
 
1025
        open facility. Most client code should use open_branch().repository to
 
1026
        get at a repository.
 
1027
 
 
1028
        :param _unsupported: a private parameter, not part of the api.
 
1029
        TODO: static convenience version of this?
 
1030
        """
 
1031
        raise NotImplementedError(self.open_repository)
 
1032
 
 
1033
    def open_workingtree(self, _unsupported=False,
 
1034
                         recommend_upgrade=True, from_branch=None):
 
1035
        """Open the workingtree object at this BzrDir if one is present.
 
1036
 
 
1037
        :param recommend_upgrade: Optional keyword parameter, when True (the
 
1038
            default), emit through the ui module a recommendation that the user
 
1039
            upgrade the working tree when the workingtree being opened is old
 
1040
            (but still fully supported).
 
1041
        :param from_branch: override bzrdir branch (for lightweight checkouts)
 
1042
        """
 
1043
        raise NotImplementedError(self.open_workingtree)
 
1044
 
 
1045
    def has_branch(self, name=None):
 
1046
        """Tell if this bzrdir contains a branch.
 
1047
 
 
1048
        Note: if you're going to open the branch, you should just go ahead
 
1049
        and try, and not ask permission first.  (This method just opens the
 
1050
        branch and discards it, and that's somewhat expensive.)
 
1051
        """
 
1052
        try:
 
1053
            self.open_branch(name)
 
1054
            return True
 
1055
        except errors.NotBranchError:
 
1056
            return False
 
1057
 
 
1058
    def has_workingtree(self):
 
1059
        """Tell if this bzrdir contains a working tree.
 
1060
 
 
1061
        This will still raise an exception if the bzrdir has a workingtree that
 
1062
        is remote & inaccessible.
 
1063
 
 
1064
        Note: if you're going to open the working tree, you should just go ahead
 
1065
        and try, and not ask permission first.  (This method just opens the
 
1066
        workingtree and discards it, and that's somewhat expensive.)
 
1067
        """
 
1068
        try:
 
1069
            self.open_workingtree(recommend_upgrade=False)
 
1070
            return True
 
1071
        except errors.NoWorkingTree:
 
1072
            return False
 
1073
 
 
1074
    def _cloning_metadir(self):
 
1075
        """Produce a metadir suitable for cloning with.
 
1076
 
 
1077
        :returns: (destination_bzrdir_format, source_repository)
 
1078
        """
 
1079
        result_format = self._format.__class__()
 
1080
        try:
 
1081
            try:
 
1082
                branch = self.open_branch(ignore_fallbacks=True)
 
1083
                source_repository = branch.repository
 
1084
                result_format._branch_format = branch._format
 
1085
            except errors.NotBranchError:
 
1086
                source_branch = None
 
1087
                source_repository = self.open_repository()
 
1088
        except errors.NoRepositoryPresent:
 
1089
            source_repository = None
 
1090
        else:
 
1091
            # XXX TODO: This isinstance is here because we have not implemented
 
1092
            # the fix recommended in bug # 103195 - to delegate this choice the
 
1093
            # repository itself.
 
1094
            repo_format = source_repository._format
 
1095
            if isinstance(repo_format, remote.RemoteRepositoryFormat):
 
1096
                source_repository._ensure_real()
 
1097
                repo_format = source_repository._real_repository._format
 
1098
            result_format.repository_format = repo_format
 
1099
        try:
 
1100
            # TODO: Couldn't we just probe for the format in these cases,
 
1101
            # rather than opening the whole tree?  It would be a little
 
1102
            # faster. mbp 20070401
 
1103
            tree = self.open_workingtree(recommend_upgrade=False)
 
1104
        except (errors.NoWorkingTree, errors.NotLocalUrl):
 
1105
            result_format.workingtree_format = None
 
1106
        else:
 
1107
            result_format.workingtree_format = tree._format.__class__()
 
1108
        return result_format, source_repository
 
1109
 
 
1110
    def cloning_metadir(self, require_stacking=False):
 
1111
        """Produce a metadir suitable for cloning or sprouting with.
 
1112
 
 
1113
        These operations may produce workingtrees (yes, even though they're
 
1114
        "cloning" something that doesn't have a tree), so a viable workingtree
 
1115
        format must be selected.
 
1116
 
 
1117
        :require_stacking: If True, non-stackable formats will be upgraded
 
1118
            to similar stackable formats.
 
1119
        :returns: a BzrDirFormat with all component formats either set
 
1120
            appropriately or set to None if that component should not be
 
1121
            created.
 
1122
        """
 
1123
        format, repository = self._cloning_metadir()
 
1124
        if format._workingtree_format is None:
 
1125
            # No tree in self.
 
1126
            if repository is None:
 
1127
                # No repository either
 
1128
                return format
 
1129
            # We have a repository, so set a working tree? (Why? This seems to
 
1130
            # contradict the stated return value in the docstring).
 
1131
            tree_format = repository._format._matchingbzrdir.workingtree_format
 
1132
            format.workingtree_format = tree_format.__class__()
 
1133
        if require_stacking:
 
1134
            format.require_stacking()
 
1135
        return format
 
1136
 
 
1137
    def checkout_metadir(self):
 
1138
        return self.cloning_metadir()
 
1139
 
 
1140
    def sprout(self, url, revision_id=None, force_new_repo=False,
 
1141
               recurse='down', possible_transports=None,
 
1142
               accelerator_tree=None, hardlink=False, stacked=False,
 
1143
               source_branch=None, create_tree_if_local=True):
 
1144
        """Create a copy of this bzrdir prepared for use as a new line of
 
1145
        development.
 
1146
 
 
1147
        If url's last component does not exist, it will be created.
 
1148
 
 
1149
        Attributes related to the identity of the source branch like
 
1150
        branch nickname will be cleaned, a working tree is created
 
1151
        whether one existed before or not; and a local branch is always
 
1152
        created.
 
1153
 
 
1154
        if revision_id is not None, then the clone operation may tune
 
1155
            itself to download less data.
 
1156
        :param accelerator_tree: A tree which can be used for retrieving file
 
1157
            contents more quickly than the revision tree, i.e. a workingtree.
 
1158
            The revision tree will be used for cases where accelerator_tree's
 
1159
            content is different.
 
1160
        :param hardlink: If true, hard-link files from accelerator_tree,
 
1161
            where possible.
 
1162
        :param stacked: If true, create a stacked branch referring to the
 
1163
            location of this control directory.
 
1164
        :param create_tree_if_local: If true, a working-tree will be created
 
1165
            when working locally.
 
1166
        """
 
1167
        target_transport = get_transport(url, possible_transports)
 
1168
        target_transport.ensure_base()
 
1169
        cloning_format = self.cloning_metadir(stacked)
 
1170
        # Create/update the result branch
 
1171
        result = cloning_format.initialize_on_transport(target_transport)
 
1172
        # if a stacked branch wasn't requested, we don't create one
 
1173
        # even if the origin was stacked
 
1174
        stacked_branch_url = None
 
1175
        if source_branch is not None:
 
1176
            if stacked:
 
1177
                stacked_branch_url = self.root_transport.base
 
1178
            source_repository = source_branch.repository
 
1179
        else:
 
1180
            try:
 
1181
                source_branch = self.open_branch()
 
1182
                source_repository = source_branch.repository
 
1183
                if stacked:
 
1184
                    stacked_branch_url = self.root_transport.base
 
1185
            except errors.NotBranchError:
 
1186
                source_branch = None
 
1187
                try:
 
1188
                    source_repository = self.open_repository()
 
1189
                except errors.NoRepositoryPresent:
 
1190
                    source_repository = None
 
1191
        repository_policy = result.determine_repository_policy(
 
1192
            force_new_repo, stacked_branch_url, require_stacking=stacked)
 
1193
        result_repo, is_new_repo = repository_policy.acquire_repository()
 
1194
        if is_new_repo and revision_id is not None and not stacked:
 
1195
            fetch_spec = graph.PendingAncestryResult(
 
1196
                [revision_id], source_repository)
 
1197
        else:
 
1198
            fetch_spec = None
 
1199
        if source_repository is not None:
 
1200
            # Fetch while stacked to prevent unstacked fetch from
 
1201
            # Branch.sprout.
 
1202
            if fetch_spec is None:
 
1203
                result_repo.fetch(source_repository, revision_id=revision_id)
 
1204
            else:
 
1205
                result_repo.fetch(source_repository, fetch_spec=fetch_spec)
 
1206
 
 
1207
        if source_branch is None:
 
1208
            # this is for sprouting a bzrdir without a branch; is that
 
1209
            # actually useful?
 
1210
            # Not especially, but it's part of the contract.
 
1211
            result_branch = result.create_branch()
 
1212
        else:
 
1213
            result_branch = source_branch.sprout(result,
 
1214
                revision_id=revision_id, repository_policy=repository_policy)
 
1215
        mutter("created new branch %r" % (result_branch,))
 
1216
 
 
1217
        # Create/update the result working tree
 
1218
        if (create_tree_if_local and
 
1219
            isinstance(target_transport, local.LocalTransport) and
 
1220
            (result_repo is None or result_repo.make_working_trees())):
 
1221
            wt = result.create_workingtree(accelerator_tree=accelerator_tree,
 
1222
                hardlink=hardlink)
 
1223
            wt.lock_write()
 
1224
            try:
 
1225
                if wt.path2id('') is None:
 
1226
                    try:
 
1227
                        wt.set_root_id(self.open_workingtree.get_root_id())
 
1228
                    except errors.NoWorkingTree:
 
1229
                        pass
 
1230
            finally:
 
1231
                wt.unlock()
 
1232
        else:
 
1233
            wt = None
 
1234
        if recurse == 'down':
 
1235
            if wt is not None:
 
1236
                basis = wt.basis_tree()
 
1237
                basis.lock_read()
 
1238
                subtrees = basis.iter_references()
 
1239
            elif result_branch is not None:
 
1240
                basis = result_branch.basis_tree()
 
1241
                basis.lock_read()
 
1242
                subtrees = basis.iter_references()
 
1243
            elif source_branch is not None:
 
1244
                basis = source_branch.basis_tree()
 
1245
                basis.lock_read()
 
1246
                subtrees = basis.iter_references()
 
1247
            else:
 
1248
                subtrees = []
 
1249
                basis = None
 
1250
            try:
 
1251
                for path, file_id in subtrees:
 
1252
                    target = urlutils.join(url, urlutils.escape(path))
 
1253
                    sublocation = source_branch.reference_parent(file_id, path)
 
1254
                    sublocation.bzrdir.sprout(target,
 
1255
                        basis.get_reference_revision(file_id, path),
 
1256
                        force_new_repo=force_new_repo, recurse=recurse,
 
1257
                        stacked=stacked)
 
1258
            finally:
 
1259
                if basis is not None:
 
1260
                    basis.unlock()
 
1261
        return result
 
1262
 
 
1263
    def push_branch(self, source, revision_id=None, overwrite=False, 
 
1264
        remember=False, create_prefix=False):
 
1265
        """Push the source branch into this BzrDir."""
 
1266
        br_to = None
 
1267
        # If we can open a branch, use its direct repository, otherwise see
 
1268
        # if there is a repository without a branch.
 
1269
        try:
 
1270
            br_to = self.open_branch()
 
1271
        except errors.NotBranchError:
 
1272
            # Didn't find a branch, can we find a repository?
 
1273
            repository_to = self.find_repository()
 
1274
        else:
 
1275
            # Found a branch, so we must have found a repository
 
1276
            repository_to = br_to.repository
 
1277
 
 
1278
        push_result = PushResult()
 
1279
        push_result.source_branch = source
 
1280
        if br_to is None:
 
1281
            # We have a repository but no branch, copy the revisions, and then
 
1282
            # create a branch.
 
1283
            repository_to.fetch(source.repository, revision_id=revision_id)
 
1284
            br_to = source.clone(self, revision_id=revision_id)
 
1285
            if source.get_push_location() is None or remember:
 
1286
                source.set_push_location(br_to.base)
 
1287
            push_result.stacked_on = None
 
1288
            push_result.branch_push_result = None
 
1289
            push_result.old_revno = None
 
1290
            push_result.old_revid = _mod_revision.NULL_REVISION
 
1291
            push_result.target_branch = br_to
 
1292
            push_result.master_branch = None
 
1293
            push_result.workingtree_updated = False
 
1294
        else:
 
1295
            # We have successfully opened the branch, remember if necessary:
 
1296
            if source.get_push_location() is None or remember:
 
1297
                source.set_push_location(br_to.base)
 
1298
            try:
 
1299
                tree_to = self.open_workingtree()
 
1300
            except errors.NotLocalUrl:
 
1301
                push_result.branch_push_result = source.push(br_to, 
 
1302
                    overwrite, stop_revision=revision_id)
 
1303
                push_result.workingtree_updated = False
 
1304
            except errors.NoWorkingTree:
 
1305
                push_result.branch_push_result = source.push(br_to,
 
1306
                    overwrite, stop_revision=revision_id)
 
1307
                push_result.workingtree_updated = None # Not applicable
 
1308
            else:
 
1309
                tree_to.lock_write()
 
1310
                try:
 
1311
                    push_result.branch_push_result = source.push(
 
1312
                        tree_to.branch, overwrite, stop_revision=revision_id)
 
1313
                    tree_to.update()
 
1314
                finally:
 
1315
                    tree_to.unlock()
 
1316
                push_result.workingtree_updated = True
 
1317
            push_result.old_revno = push_result.branch_push_result.old_revno
 
1318
            push_result.old_revid = push_result.branch_push_result.old_revid
 
1319
            push_result.target_branch = \
 
1320
                push_result.branch_push_result.target_branch
 
1321
        return push_result
 
1322
 
 
1323
 
 
1324
class BzrDirHooks(hooks.Hooks):
 
1325
    """Hooks for BzrDir operations."""
 
1326
 
 
1327
    def __init__(self):
 
1328
        """Create the default hooks."""
 
1329
        hooks.Hooks.__init__(self)
 
1330
        self.create_hook(hooks.HookPoint('pre_open',
 
1331
            "Invoked before attempting to open a BzrDir with the transport "
 
1332
            "that the open will use.", (1, 14), None))
 
1333
        self.create_hook(hooks.HookPoint('post_repo_init',
 
1334
            "Invoked after a repository has been initialized. "
 
1335
            "post_repo_init is called with a "
 
1336
            "bzrlib.bzrdir.RepoInitHookParams.",
 
1337
            (2, 2), None))
 
1338
 
 
1339
# install the default hooks
 
1340
BzrDir.hooks = BzrDirHooks()
 
1341
 
 
1342
 
 
1343
class RepoInitHookParams(object):
 
1344
    """Object holding parameters passed to *_repo_init hooks.
 
1345
 
 
1346
    There are 4 fields that hooks may wish to access:
 
1347
 
 
1348
    :ivar repository: Repository created
 
1349
    :ivar format: Repository format
 
1350
    :ivar bzrdir: The bzrdir for the repository
 
1351
    :ivar shared: The repository is shared
 
1352
    """
 
1353
 
 
1354
    def __init__(self, repository, format, a_bzrdir, shared):
 
1355
        """Create a group of RepoInitHook parameters.
 
1356
 
 
1357
        :param repository: Repository created
 
1358
        :param format: Repository format
 
1359
        :param bzrdir: The bzrdir for the repository
 
1360
        :param shared: The repository is shared
 
1361
        """
 
1362
        self.repository = repository
 
1363
        self.format = format
 
1364
        self.bzrdir = a_bzrdir
 
1365
        self.shared = shared
 
1366
 
 
1367
    def __eq__(self, other):
 
1368
        return self.__dict__ == other.__dict__
 
1369
 
 
1370
    def __repr__(self):
 
1371
        if self.repository:
 
1372
            return "<%s for %s>" % (self.__class__.__name__,
 
1373
                self.repository)
 
1374
        else:
 
1375
            return "<%s for %s>" % (self.__class__.__name__,
 
1376
                self.bzrdir)
 
1377
 
 
1378
 
 
1379
class BzrDirPreSplitOut(BzrDir):
 
1380
    """A common class for the all-in-one formats."""
 
1381
 
 
1382
    def __init__(self, _transport, _format):
 
1383
        """See BzrDir.__init__."""
 
1384
        super(BzrDirPreSplitOut, self).__init__(_transport, _format)
 
1385
        self._control_files = lockable_files.LockableFiles(
 
1386
                                            self.get_branch_transport(None),
 
1387
                                            self._format._lock_file_name,
 
1388
                                            self._format._lock_class)
 
1389
 
 
1390
    def break_lock(self):
 
1391
        """Pre-splitout bzrdirs do not suffer from stale locks."""
 
1392
        raise NotImplementedError(self.break_lock)
 
1393
 
 
1394
    def cloning_metadir(self, require_stacking=False):
 
1395
        """Produce a metadir suitable for cloning with."""
 
1396
        if require_stacking:
 
1397
            return format_registry.make_bzrdir('1.6')
 
1398
        return self._format.__class__()
 
1399
 
 
1400
    def clone(self, url, revision_id=None, force_new_repo=False,
 
1401
              preserve_stacking=False):
 
1402
        """See BzrDir.clone().
 
1403
 
 
1404
        force_new_repo has no effect, since this family of formats always
 
1405
        require a new repository.
 
1406
        preserve_stacking has no effect, since no source branch using this
 
1407
        family of formats can be stacked, so there is no stacking to preserve.
 
1408
        """
 
1409
        self._make_tail(url)
 
1410
        result = self._format._initialize_for_clone(url)
 
1411
        self.open_repository().clone(result, revision_id=revision_id)
 
1412
        from_branch = self.open_branch()
 
1413
        from_branch.clone(result, revision_id=revision_id)
 
1414
        try:
 
1415
            tree = self.open_workingtree()
 
1416
        except errors.NotLocalUrl:
 
1417
            # make a new one, this format always has to have one.
 
1418
            result._init_workingtree()
 
1419
        else:
 
1420
            tree.clone(result)
 
1421
        return result
 
1422
 
 
1423
    def create_branch(self, name=None):
 
1424
        """See BzrDir.create_branch."""
 
1425
        return self._format.get_branch_format().initialize(self, name=name)
 
1426
 
 
1427
    def destroy_branch(self, name=None):
 
1428
        """See BzrDir.destroy_branch."""
 
1429
        raise errors.UnsupportedOperation(self.destroy_branch, self)
 
1430
 
 
1431
    def create_repository(self, shared=False):
 
1432
        """See BzrDir.create_repository."""
 
1433
        if shared:
 
1434
            raise errors.IncompatibleFormat('shared repository', self._format)
 
1435
        return self.open_repository()
 
1436
 
 
1437
    def destroy_repository(self):
 
1438
        """See BzrDir.destroy_repository."""
 
1439
        raise errors.UnsupportedOperation(self.destroy_repository, self)
 
1440
 
 
1441
    def create_workingtree(self, revision_id=None, from_branch=None,
 
1442
                           accelerator_tree=None, hardlink=False):
 
1443
        """See BzrDir.create_workingtree."""
 
1444
        # The workingtree is sometimes created when the bzrdir is created,
 
1445
        # but not when cloning.
 
1446
 
 
1447
        # this looks buggy but is not -really-
 
1448
        # because this format creates the workingtree when the bzrdir is
 
1449
        # created
 
1450
        # clone and sprout will have set the revision_id
 
1451
        # and that will have set it for us, its only
 
1452
        # specific uses of create_workingtree in isolation
 
1453
        # that can do wonky stuff here, and that only
 
1454
        # happens for creating checkouts, which cannot be
 
1455
        # done on this format anyway. So - acceptable wart.
 
1456
        if hardlink:
 
1457
            warning("can't support hardlinked working trees in %r"
 
1458
                % (self,))
 
1459
        try:
 
1460
            result = self.open_workingtree(recommend_upgrade=False)
 
1461
        except errors.NoSuchFile:
 
1462
            result = self._init_workingtree()
 
1463
        if revision_id is not None:
 
1464
            if revision_id == _mod_revision.NULL_REVISION:
 
1465
                result.set_parent_ids([])
 
1466
            else:
 
1467
                result.set_parent_ids([revision_id])
 
1468
        return result
 
1469
 
 
1470
    def _init_workingtree(self):
 
1471
        from bzrlib.workingtree import WorkingTreeFormat2
 
1472
        try:
 
1473
            return WorkingTreeFormat2().initialize(self)
 
1474
        except errors.NotLocalUrl:
 
1475
            # Even though we can't access the working tree, we need to
 
1476
            # create its control files.
 
1477
            return WorkingTreeFormat2()._stub_initialize_on_transport(
 
1478
                self.transport, self._control_files._file_mode)
 
1479
 
 
1480
    def destroy_workingtree(self):
 
1481
        """See BzrDir.destroy_workingtree."""
 
1482
        raise errors.UnsupportedOperation(self.destroy_workingtree, self)
 
1483
 
 
1484
    def destroy_workingtree_metadata(self):
 
1485
        """See BzrDir.destroy_workingtree_metadata."""
 
1486
        raise errors.UnsupportedOperation(self.destroy_workingtree_metadata,
 
1487
                                          self)
 
1488
 
 
1489
    def get_branch_transport(self, branch_format, name=None):
 
1490
        """See BzrDir.get_branch_transport()."""
 
1491
        if name is not None:
 
1492
            raise errors.NoColocatedBranchSupport(self)
 
1493
        if branch_format is None:
 
1494
            return self.transport
 
1495
        try:
 
1496
            branch_format.get_format_string()
 
1497
        except NotImplementedError:
 
1498
            return self.transport
 
1499
        raise errors.IncompatibleFormat(branch_format, self._format)
 
1500
 
 
1501
    def get_repository_transport(self, repository_format):
 
1502
        """See BzrDir.get_repository_transport()."""
 
1503
        if repository_format is None:
 
1504
            return self.transport
 
1505
        try:
 
1506
            repository_format.get_format_string()
 
1507
        except NotImplementedError:
 
1508
            return self.transport
 
1509
        raise errors.IncompatibleFormat(repository_format, self._format)
 
1510
 
 
1511
    def get_workingtree_transport(self, workingtree_format):
 
1512
        """See BzrDir.get_workingtree_transport()."""
 
1513
        if workingtree_format is None:
 
1514
            return self.transport
 
1515
        try:
 
1516
            workingtree_format.get_format_string()
 
1517
        except NotImplementedError:
 
1518
            return self.transport
 
1519
        raise errors.IncompatibleFormat(workingtree_format, self._format)
 
1520
 
 
1521
    def needs_format_conversion(self, format=None):
 
1522
        """See BzrDir.needs_format_conversion()."""
 
1523
        # if the format is not the same as the system default,
 
1524
        # an upgrade is needed.
 
1525
        if format is None:
 
1526
            symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
 
1527
                % 'needs_format_conversion(format=None)')
 
1528
            format = BzrDirFormat.get_default_format()
 
1529
        return not isinstance(self._format, format.__class__)
 
1530
 
 
1531
    def open_branch(self, name=None, unsupported=False,
 
1532
                    ignore_fallbacks=False):
 
1533
        """See BzrDir.open_branch."""
 
1534
        from bzrlib.branch import BzrBranchFormat4
 
1535
        format = BzrBranchFormat4()
 
1536
        self._check_supported(format, unsupported)
 
1537
        return format.open(self, name, _found=True)
 
1538
 
 
1539
    def sprout(self, url, revision_id=None, force_new_repo=False,
 
1540
               possible_transports=None, accelerator_tree=None,
 
1541
               hardlink=False, stacked=False, create_tree_if_local=True,
 
1542
               source_branch=None):
 
1543
        """See BzrDir.sprout()."""
 
1544
        if source_branch is not None:
 
1545
            my_branch = self.open_branch()
 
1546
            if source_branch.base != my_branch.base:
 
1547
                raise AssertionError(
 
1548
                    "source branch %r is not within %r with branch %r" %
 
1549
                    (source_branch, self, my_branch))
 
1550
        if stacked:
 
1551
            raise errors.UnstackableBranchFormat(
 
1552
                self._format, self.root_transport.base)
 
1553
        if not create_tree_if_local:
 
1554
            raise errors.MustHaveWorkingTree(
 
1555
                self._format, self.root_transport.base)
 
1556
        from bzrlib.workingtree import WorkingTreeFormat2
 
1557
        self._make_tail(url)
 
1558
        result = self._format._initialize_for_clone(url)
 
1559
        try:
 
1560
            self.open_repository().clone(result, revision_id=revision_id)
 
1561
        except errors.NoRepositoryPresent:
 
1562
            pass
 
1563
        try:
 
1564
            self.open_branch().sprout(result, revision_id=revision_id)
 
1565
        except errors.NotBranchError:
 
1566
            pass
 
1567
 
 
1568
        # we always want a working tree
 
1569
        WorkingTreeFormat2().initialize(result,
 
1570
                                        accelerator_tree=accelerator_tree,
 
1571
                                        hardlink=hardlink)
 
1572
        return result
 
1573
 
 
1574
 
 
1575
class BzrDir4(BzrDirPreSplitOut):
 
1576
    """A .bzr version 4 control object.
 
1577
 
 
1578
    This is a deprecated format and may be removed after sept 2006.
 
1579
    """
 
1580
 
 
1581
    def create_repository(self, shared=False):
 
1582
        """See BzrDir.create_repository."""
 
1583
        return self._format.repository_format.initialize(self, shared)
 
1584
 
 
1585
    def needs_format_conversion(self, format=None):
 
1586
        """Format 4 dirs are always in need of conversion."""
 
1587
        if format is None:
 
1588
            symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
 
1589
                % 'needs_format_conversion(format=None)')
 
1590
        return True
 
1591
 
 
1592
    def open_repository(self):
 
1593
        """See BzrDir.open_repository."""
 
1594
        from bzrlib.repofmt.weaverepo import RepositoryFormat4
 
1595
        return RepositoryFormat4().open(self, _found=True)
 
1596
 
 
1597
 
 
1598
class BzrDir5(BzrDirPreSplitOut):
 
1599
    """A .bzr version 5 control object.
 
1600
 
 
1601
    This is a deprecated format and may be removed after sept 2006.
 
1602
    """
 
1603
 
 
1604
    def has_workingtree(self):
 
1605
        """See BzrDir.has_workingtree."""
 
1606
        return True
 
1607
    
 
1608
    def open_repository(self):
 
1609
        """See BzrDir.open_repository."""
 
1610
        from bzrlib.repofmt.weaverepo import RepositoryFormat5
 
1611
        return RepositoryFormat5().open(self, _found=True)
 
1612
 
 
1613
    def open_workingtree(self, _unsupported=False,
 
1614
            recommend_upgrade=True):
 
1615
        """See BzrDir.create_workingtree."""
 
1616
        from bzrlib.workingtree import WorkingTreeFormat2
 
1617
        wt_format = WorkingTreeFormat2()
 
1618
        # we don't warn here about upgrades; that ought to be handled for the
 
1619
        # bzrdir as a whole
 
1620
        return wt_format.open(self, _found=True)
 
1621
 
 
1622
 
 
1623
class BzrDir6(BzrDirPreSplitOut):
 
1624
    """A .bzr version 6 control object.
 
1625
 
 
1626
    This is a deprecated format and may be removed after sept 2006.
 
1627
    """
 
1628
 
 
1629
    def has_workingtree(self):
 
1630
        """See BzrDir.has_workingtree."""
 
1631
        return True
 
1632
    
 
1633
    def open_repository(self):
 
1634
        """See BzrDir.open_repository."""
 
1635
        from bzrlib.repofmt.weaverepo import RepositoryFormat6
 
1636
        return RepositoryFormat6().open(self, _found=True)
 
1637
 
 
1638
    def open_workingtree(self, _unsupported=False,
 
1639
        recommend_upgrade=True):
 
1640
        """See BzrDir.create_workingtree."""
 
1641
        # we don't warn here about upgrades; that ought to be handled for the
 
1642
        # bzrdir as a whole
 
1643
        from bzrlib.workingtree import WorkingTreeFormat2
 
1644
        return WorkingTreeFormat2().open(self, _found=True)
 
1645
 
 
1646
 
 
1647
class BzrDirMeta1(BzrDir):
 
1648
    """A .bzr meta version 1 control object.
 
1649
 
 
1650
    This is the first control object where the
 
1651
    individual aspects are really split out: there are separate repository,
 
1652
    workingtree and branch subdirectories and any subset of the three can be
 
1653
    present within a BzrDir.
 
1654
    """
 
1655
 
 
1656
    def can_convert_format(self):
 
1657
        """See BzrDir.can_convert_format()."""
 
1658
        return True
 
1659
 
 
1660
    def create_branch(self, name=None):
 
1661
        """See BzrDir.create_branch."""
 
1662
        return self._format.get_branch_format().initialize(self, name=name)
 
1663
 
 
1664
    def destroy_branch(self, name=None):
 
1665
        """See BzrDir.create_branch."""
 
1666
        if name is not None:
 
1667
            raise errors.NoColocatedBranchSupport(self)
 
1668
        self.transport.delete_tree('branch')
 
1669
 
 
1670
    def create_repository(self, shared=False):
 
1671
        """See BzrDir.create_repository."""
 
1672
        return self._format.repository_format.initialize(self, shared)
 
1673
 
 
1674
    def destroy_repository(self):
 
1675
        """See BzrDir.destroy_repository."""
 
1676
        self.transport.delete_tree('repository')
 
1677
 
 
1678
    def create_workingtree(self, revision_id=None, from_branch=None,
 
1679
                           accelerator_tree=None, hardlink=False):
 
1680
        """See BzrDir.create_workingtree."""
 
1681
        return self._format.workingtree_format.initialize(
 
1682
            self, revision_id, from_branch=from_branch,
 
1683
            accelerator_tree=accelerator_tree, hardlink=hardlink)
 
1684
 
 
1685
    def destroy_workingtree(self):
 
1686
        """See BzrDir.destroy_workingtree."""
 
1687
        wt = self.open_workingtree(recommend_upgrade=False)
 
1688
        repository = wt.branch.repository
 
1689
        empty = repository.revision_tree(_mod_revision.NULL_REVISION)
 
1690
        wt.revert(old_tree=empty)
 
1691
        self.destroy_workingtree_metadata()
 
1692
 
 
1693
    def destroy_workingtree_metadata(self):
 
1694
        self.transport.delete_tree('checkout')
 
1695
 
 
1696
    def find_branch_format(self):
 
1697
        """Find the branch 'format' for this bzrdir.
 
1698
 
 
1699
        This might be a synthetic object for e.g. RemoteBranch and SVN.
 
1700
        """
 
1701
        from bzrlib.branch import BranchFormat
 
1702
        return BranchFormat.find_format(self)
 
1703
 
 
1704
    def _get_mkdir_mode(self):
 
1705
        """Figure out the mode to use when creating a bzrdir subdir."""
 
1706
        temp_control = lockable_files.LockableFiles(self.transport, '',
 
1707
                                     lockable_files.TransportLock)
 
1708
        return temp_control._dir_mode
 
1709
 
 
1710
    def get_branch_reference(self):
 
1711
        """See BzrDir.get_branch_reference()."""
 
1712
        from bzrlib.branch import BranchFormat
 
1713
        format = BranchFormat.find_format(self)
 
1714
        return format.get_reference(self)
 
1715
 
 
1716
    def get_branch_transport(self, branch_format, name=None):
 
1717
        """See BzrDir.get_branch_transport()."""
 
1718
        if name is not None:
 
1719
            raise errors.NoColocatedBranchSupport(self)
 
1720
        # XXX: this shouldn't implicitly create the directory if it's just
 
1721
        # promising to get a transport -- mbp 20090727
 
1722
        if branch_format is None:
 
1723
            return self.transport.clone('branch')
 
1724
        try:
 
1725
            branch_format.get_format_string()
 
1726
        except NotImplementedError:
 
1727
            raise errors.IncompatibleFormat(branch_format, self._format)
 
1728
        try:
 
1729
            self.transport.mkdir('branch', mode=self._get_mkdir_mode())
 
1730
        except errors.FileExists:
 
1731
            pass
 
1732
        return self.transport.clone('branch')
 
1733
 
 
1734
    def get_repository_transport(self, repository_format):
 
1735
        """See BzrDir.get_repository_transport()."""
 
1736
        if repository_format is None:
 
1737
            return self.transport.clone('repository')
 
1738
        try:
 
1739
            repository_format.get_format_string()
 
1740
        except NotImplementedError:
 
1741
            raise errors.IncompatibleFormat(repository_format, self._format)
 
1742
        try:
 
1743
            self.transport.mkdir('repository', mode=self._get_mkdir_mode())
 
1744
        except errors.FileExists:
 
1745
            pass
 
1746
        return self.transport.clone('repository')
 
1747
 
 
1748
    def get_workingtree_transport(self, workingtree_format):
 
1749
        """See BzrDir.get_workingtree_transport()."""
 
1750
        if workingtree_format is None:
 
1751
            return self.transport.clone('checkout')
 
1752
        try:
 
1753
            workingtree_format.get_format_string()
 
1754
        except NotImplementedError:
 
1755
            raise errors.IncompatibleFormat(workingtree_format, self._format)
 
1756
        try:
 
1757
            self.transport.mkdir('checkout', mode=self._get_mkdir_mode())
 
1758
        except errors.FileExists:
 
1759
            pass
 
1760
        return self.transport.clone('checkout')
 
1761
 
 
1762
    def has_workingtree(self):
 
1763
        """Tell if this bzrdir contains a working tree.
 
1764
 
 
1765
        This will still raise an exception if the bzrdir has a workingtree that
 
1766
        is remote & inaccessible.
 
1767
 
 
1768
        Note: if you're going to open the working tree, you should just go
 
1769
        ahead and try, and not ask permission first.
 
1770
        """
 
1771
        from bzrlib.workingtree import WorkingTreeFormat
 
1772
        try:
 
1773
            WorkingTreeFormat.find_format(self)
 
1774
        except errors.NoWorkingTree:
 
1775
            return False
 
1776
        return True
 
1777
 
 
1778
    def needs_format_conversion(self, format=None):
 
1779
        """See BzrDir.needs_format_conversion()."""
 
1780
        if format is None:
 
1781
            symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
 
1782
                % 'needs_format_conversion(format=None)')
 
1783
        if format is None:
 
1784
            format = BzrDirFormat.get_default_format()
 
1785
        if not isinstance(self._format, format.__class__):
 
1786
            # it is not a meta dir format, conversion is needed.
 
1787
            return True
 
1788
        # we might want to push this down to the repository?
 
1789
        try:
 
1790
            if not isinstance(self.open_repository()._format,
 
1791
                              format.repository_format.__class__):
 
1792
                # the repository needs an upgrade.
 
1793
                return True
 
1794
        except errors.NoRepositoryPresent:
 
1795
            pass
 
1796
        for branch in self.list_branches():
 
1797
            if not isinstance(branch._format,
 
1798
                              format.get_branch_format().__class__):
 
1799
                # the branch needs an upgrade.
 
1800
                return True
 
1801
        try:
 
1802
            my_wt = self.open_workingtree(recommend_upgrade=False)
 
1803
            if not isinstance(my_wt._format,
 
1804
                              format.workingtree_format.__class__):
 
1805
                # the workingtree needs an upgrade.
 
1806
                return True
 
1807
        except (errors.NoWorkingTree, errors.NotLocalUrl):
 
1808
            pass
 
1809
        return False
 
1810
 
 
1811
    def open_branch(self, name=None, unsupported=False,
 
1812
                    ignore_fallbacks=False):
 
1813
        """See BzrDir.open_branch."""
 
1814
        format = self.find_branch_format()
 
1815
        self._check_supported(format, unsupported)
 
1816
        return format.open(self, name=name,
 
1817
            _found=True, ignore_fallbacks=ignore_fallbacks)
 
1818
 
 
1819
    def open_repository(self, unsupported=False):
 
1820
        """See BzrDir.open_repository."""
 
1821
        from bzrlib.repository import RepositoryFormat
 
1822
        format = RepositoryFormat.find_format(self)
 
1823
        self._check_supported(format, unsupported)
 
1824
        return format.open(self, _found=True)
 
1825
 
 
1826
    def open_workingtree(self, unsupported=False,
 
1827
            recommend_upgrade=True):
 
1828
        """See BzrDir.open_workingtree."""
 
1829
        from bzrlib.workingtree import WorkingTreeFormat
 
1830
        format = WorkingTreeFormat.find_format(self)
 
1831
        self._check_supported(format, unsupported,
 
1832
            recommend_upgrade,
 
1833
            basedir=self.root_transport.base)
 
1834
        return format.open(self, _found=True)
 
1835
 
 
1836
    def _get_config(self):
 
1837
        return config.TransportConfig(self.transport, 'control.conf')
 
1838
 
 
1839
 
 
1840
class BzrDirFormat(object):
 
1841
    """An encapsulation of the initialization and open routines for a format.
 
1842
 
 
1843
    Formats provide three things:
 
1844
     * An initialization routine,
 
1845
     * a format string,
 
1846
     * an open routine.
 
1847
 
 
1848
    Formats are placed in a dict by their format string for reference
 
1849
    during bzrdir opening. These should be subclasses of BzrDirFormat
 
1850
    for consistency.
 
1851
 
 
1852
    Once a format is deprecated, just deprecate the initialize and open
 
1853
    methods on the format class. Do not deprecate the object, as the
 
1854
    object will be created every system load.
 
1855
 
 
1856
    :cvar colocated_branches: Whether this formats supports colocated branches.
 
1857
    """
 
1858
 
 
1859
    _default_format = None
 
1860
    """The default format used for new .bzr dirs."""
 
1861
 
 
1862
    _formats = {}
 
1863
    """The known formats."""
 
1864
 
 
1865
    _control_formats = []
 
1866
    """The registered control formats - .bzr, ....
 
1867
 
 
1868
    This is a list of BzrDirFormat objects.
 
1869
    """
 
1870
 
 
1871
    _control_server_formats = []
 
1872
    """The registered control server formats, e.g. RemoteBzrDirs.
 
1873
 
 
1874
    This is a list of BzrDirFormat objects.
 
1875
    """
 
1876
 
 
1877
    _lock_file_name = 'branch-lock'
 
1878
 
 
1879
    colocated_branches = False
 
1880
    """Whether co-located branches are supported for this control dir format.
 
1881
    """
 
1882
 
 
1883
    # _lock_class must be set in subclasses to the lock type, typ.
 
1884
    # TransportLock or LockDir
 
1885
 
 
1886
    @classmethod
 
1887
    def find_format(klass, transport, _server_formats=True):
 
1888
        """Return the format present at transport."""
 
1889
        if _server_formats:
 
1890
            formats = klass._control_server_formats + klass._control_formats
 
1891
        else:
 
1892
            formats = klass._control_formats
 
1893
        for format in formats:
 
1894
            try:
 
1895
                return format.probe_transport(transport)
 
1896
            except errors.NotBranchError:
 
1897
                # this format does not find a control dir here.
 
1898
                pass
 
1899
        raise errors.NotBranchError(path=transport.base)
 
1900
 
 
1901
    @classmethod
 
1902
    def probe_transport(klass, transport):
 
1903
        """Return the .bzrdir style format present in a directory."""
 
1904
        try:
 
1905
            format_string = transport.get_bytes(".bzr/branch-format")
 
1906
        except errors.NoSuchFile:
 
1907
            raise errors.NotBranchError(path=transport.base)
 
1908
 
 
1909
        try:
 
1910
            return klass._formats[format_string]
 
1911
        except KeyError:
 
1912
            raise errors.UnknownFormatError(format=format_string, kind='bzrdir')
 
1913
 
 
1914
    @classmethod
 
1915
    def get_default_format(klass):
 
1916
        """Return the current default format."""
 
1917
        return klass._default_format
 
1918
 
 
1919
    def get_format_string(self):
 
1920
        """Return the ASCII format string that identifies this format."""
 
1921
        raise NotImplementedError(self.get_format_string)
 
1922
 
 
1923
    def get_format_description(self):
 
1924
        """Return the short description for this format."""
 
1925
        raise NotImplementedError(self.get_format_description)
 
1926
 
 
1927
    def get_converter(self, format=None):
 
1928
        """Return the converter to use to convert bzrdirs needing converts.
 
1929
 
 
1930
        This returns a bzrlib.bzrdir.Converter object.
 
1931
 
 
1932
        This should return the best upgrader to step this format towards the
 
1933
        current default format. In the case of plugins we can/should provide
 
1934
        some means for them to extend the range of returnable converters.
 
1935
 
 
1936
        :param format: Optional format to override the default format of the
 
1937
                       library.
 
1938
        """
 
1939
        raise NotImplementedError(self.get_converter)
 
1940
 
 
1941
    def initialize(self, url, possible_transports=None):
 
1942
        """Create a bzr control dir at this url and return an opened copy.
 
1943
 
 
1944
        While not deprecated, this method is very specific and its use will
 
1945
        lead to many round trips to setup a working environment. See
 
1946
        initialize_on_transport_ex for a [nearly] all-in-one method.
 
1947
 
 
1948
        Subclasses should typically override initialize_on_transport
 
1949
        instead of this method.
 
1950
        """
 
1951
        return self.initialize_on_transport(get_transport(url,
 
1952
                                                          possible_transports))
 
1953
 
 
1954
    def initialize_on_transport(self, transport):
 
1955
        """Initialize a new bzrdir in the base directory of a Transport."""
 
1956
        try:
 
1957
            # can we hand off the request to the smart server rather than using
 
1958
            # vfs calls?
 
1959
            client_medium = transport.get_smart_medium()
 
1960
        except errors.NoSmartMedium:
 
1961
            return self._initialize_on_transport_vfs(transport)
 
1962
        else:
 
1963
            # Current RPC's only know how to create bzr metadir1 instances, so
 
1964
            # we still delegate to vfs methods if the requested format is not a
 
1965
            # metadir1
 
1966
            if type(self) != BzrDirMetaFormat1:
 
1967
                return self._initialize_on_transport_vfs(transport)
 
1968
            remote_format = RemoteBzrDirFormat()
 
1969
            self._supply_sub_formats_to(remote_format)
 
1970
            return remote_format.initialize_on_transport(transport)
 
1971
 
 
1972
    def initialize_on_transport_ex(self, transport, use_existing_dir=False,
 
1973
        create_prefix=False, force_new_repo=False, stacked_on=None,
 
1974
        stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
 
1975
        shared_repo=False, vfs_only=False):
 
1976
        """Create this format on transport.
 
1977
 
 
1978
        The directory to initialize will be created.
 
1979
 
 
1980
        :param force_new_repo: Do not use a shared repository for the target,
 
1981
                               even if one is available.
 
1982
        :param create_prefix: Create any missing directories leading up to
 
1983
            to_transport.
 
1984
        :param use_existing_dir: Use an existing directory if one exists.
 
1985
        :param stacked_on: A url to stack any created branch on, None to follow
 
1986
            any target stacking policy.
 
1987
        :param stack_on_pwd: If stack_on is relative, the location it is
 
1988
            relative to.
 
1989
        :param repo_format_name: If non-None, a repository will be
 
1990
            made-or-found. Should none be found, or if force_new_repo is True
 
1991
            the repo_format_name is used to select the format of repository to
 
1992
            create.
 
1993
        :param make_working_trees: Control the setting of make_working_trees
 
1994
            for a new shared repository when one is made. None to use whatever
 
1995
            default the format has.
 
1996
        :param shared_repo: Control whether made repositories are shared or
 
1997
            not.
 
1998
        :param vfs_only: If True do not attempt to use a smart server
 
1999
        :return: repo, bzrdir, require_stacking, repository_policy. repo is
 
2000
            None if none was created or found, bzrdir is always valid.
 
2001
            require_stacking is the result of examining the stacked_on
 
2002
            parameter and any stacking policy found for the target.
 
2003
        """
 
2004
        if not vfs_only:
 
2005
            # Try to hand off to a smart server 
 
2006
            try:
 
2007
                client_medium = transport.get_smart_medium()
 
2008
            except errors.NoSmartMedium:
 
2009
                pass
 
2010
            else:
 
2011
                # TODO: lookup the local format from a server hint.
 
2012
                remote_dir_format = RemoteBzrDirFormat()
 
2013
                remote_dir_format._network_name = self.network_name()
 
2014
                self._supply_sub_formats_to(remote_dir_format)
 
2015
                return remote_dir_format.initialize_on_transport_ex(transport,
 
2016
                    use_existing_dir=use_existing_dir, create_prefix=create_prefix,
 
2017
                    force_new_repo=force_new_repo, stacked_on=stacked_on,
 
2018
                    stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
 
2019
                    make_working_trees=make_working_trees, shared_repo=shared_repo)
 
2020
        # XXX: Refactor the create_prefix/no_create_prefix code into a
 
2021
        #      common helper function
 
2022
        # The destination may not exist - if so make it according to policy.
 
2023
        def make_directory(transport):
 
2024
            transport.mkdir('.')
 
2025
            return transport
 
2026
        def redirected(transport, e, redirection_notice):
 
2027
            note(redirection_notice)
 
2028
            return transport._redirected_to(e.source, e.target)
 
2029
        try:
 
2030
            transport = do_catching_redirections(make_directory, transport,
 
2031
                redirected)
 
2032
        except errors.FileExists:
 
2033
            if not use_existing_dir:
 
2034
                raise
 
2035
        except errors.NoSuchFile:
 
2036
            if not create_prefix:
 
2037
                raise
 
2038
            transport.create_prefix()
 
2039
 
 
2040
        require_stacking = (stacked_on is not None)
 
2041
        # Now the target directory exists, but doesn't have a .bzr
 
2042
        # directory. So we need to create it, along with any work to create
 
2043
        # all of the dependent branches, etc.
 
2044
 
 
2045
        result = self.initialize_on_transport(transport)
 
2046
        if repo_format_name:
 
2047
            try:
 
2048
                # use a custom format
 
2049
                result._format.repository_format = \
 
2050
                    repository.network_format_registry.get(repo_format_name)
 
2051
            except AttributeError:
 
2052
                # The format didn't permit it to be set.
 
2053
                pass
 
2054
            # A repository is desired, either in-place or shared.
 
2055
            repository_policy = result.determine_repository_policy(
 
2056
                force_new_repo, stacked_on, stack_on_pwd,
 
2057
                require_stacking=require_stacking)
 
2058
            result_repo, is_new_repo = repository_policy.acquire_repository(
 
2059
                make_working_trees, shared_repo)
 
2060
            if not require_stacking and repository_policy._require_stacking:
 
2061
                require_stacking = True
 
2062
                result._format.require_stacking()
 
2063
            result_repo.lock_write()
 
2064
        else:
 
2065
            result_repo = None
 
2066
            repository_policy = None
 
2067
        return result_repo, result, require_stacking, repository_policy
 
2068
 
 
2069
    def _initialize_on_transport_vfs(self, transport):
 
2070
        """Initialize a new bzrdir using VFS calls.
 
2071
 
 
2072
        :param transport: The transport to create the .bzr directory in.
 
2073
        :return: A
 
2074
        """
 
2075
        # Since we are creating a .bzr directory, inherit the
 
2076
        # mode from the root directory
 
2077
        temp_control = lockable_files.LockableFiles(transport,
 
2078
                            '', lockable_files.TransportLock)
 
2079
        temp_control._transport.mkdir('.bzr',
 
2080
                                      # FIXME: RBC 20060121 don't peek under
 
2081
                                      # the covers
 
2082
                                      mode=temp_control._dir_mode)
 
2083
        if sys.platform == 'win32' and isinstance(transport, local.LocalTransport):
 
2084
            win32utils.set_file_attr_hidden(transport._abspath('.bzr'))
 
2085
        file_mode = temp_control._file_mode
 
2086
        del temp_control
 
2087
        bzrdir_transport = transport.clone('.bzr')
 
2088
        utf8_files = [('README',
 
2089
                       "This is a Bazaar control directory.\n"
 
2090
                       "Do not change any files in this directory.\n"
 
2091
                       "See http://bazaar-vcs.org/ for more information about Bazaar.\n"),
 
2092
                      ('branch-format', self.get_format_string()),
 
2093
                      ]
 
2094
        # NB: no need to escape relative paths that are url safe.
 
2095
        control_files = lockable_files.LockableFiles(bzrdir_transport,
 
2096
            self._lock_file_name, self._lock_class)
 
2097
        control_files.create_lock()
 
2098
        control_files.lock_write()
 
2099
        try:
 
2100
            for (filename, content) in utf8_files:
 
2101
                bzrdir_transport.put_bytes(filename, content,
 
2102
                    mode=file_mode)
 
2103
        finally:
 
2104
            control_files.unlock()
 
2105
        return self.open(transport, _found=True)
 
2106
 
 
2107
    def is_supported(self):
 
2108
        """Is this format supported?
 
2109
 
 
2110
        Supported formats must be initializable and openable.
 
2111
        Unsupported formats may not support initialization or committing or
 
2112
        some other features depending on the reason for not being supported.
 
2113
        """
 
2114
        return True
 
2115
 
 
2116
    def network_name(self):
 
2117
        """A simple byte string uniquely identifying this format for RPC calls.
 
2118
 
 
2119
        Bzr control formats use thir disk format string to identify the format
 
2120
        over the wire. Its possible that other control formats have more
 
2121
        complex detection requirements, so we permit them to use any unique and
 
2122
        immutable string they desire.
 
2123
        """
 
2124
        raise NotImplementedError(self.network_name)
 
2125
 
 
2126
    def same_model(self, target_format):
 
2127
        return (self.repository_format.rich_root_data ==
 
2128
            target_format.rich_root_data)
 
2129
 
 
2130
    @classmethod
 
2131
    def known_formats(klass):
 
2132
        """Return all the known formats.
 
2133
 
 
2134
        Concrete formats should override _known_formats.
 
2135
        """
 
2136
        # There is double indirection here to make sure that control
 
2137
        # formats used by more than one dir format will only be probed
 
2138
        # once. This can otherwise be quite expensive for remote connections.
 
2139
        result = set()
 
2140
        for format in klass._control_formats:
 
2141
            result.update(format._known_formats())
 
2142
        return result
 
2143
 
 
2144
    @classmethod
 
2145
    def _known_formats(klass):
 
2146
        """Return the known format instances for this control format."""
 
2147
        return set(klass._formats.values())
 
2148
 
 
2149
    def open(self, transport, _found=False):
 
2150
        """Return an instance of this format for the dir transport points at.
 
2151
 
 
2152
        _found is a private parameter, do not use it.
 
2153
        """
 
2154
        if not _found:
 
2155
            found_format = BzrDirFormat.find_format(transport)
 
2156
            if not isinstance(found_format, self.__class__):
 
2157
                raise AssertionError("%s was asked to open %s, but it seems to need "
 
2158
                        "format %s"
 
2159
                        % (self, transport, found_format))
 
2160
            # Allow subclasses - use the found format.
 
2161
            self._supply_sub_formats_to(found_format)
 
2162
            return found_format._open(transport)
 
2163
        return self._open(transport)
 
2164
 
 
2165
    def _open(self, transport):
 
2166
        """Template method helper for opening BzrDirectories.
 
2167
 
 
2168
        This performs the actual open and any additional logic or parameter
 
2169
        passing.
 
2170
        """
 
2171
        raise NotImplementedError(self._open)
 
2172
 
 
2173
    @classmethod
 
2174
    def register_format(klass, format):
 
2175
        klass._formats[format.get_format_string()] = format
 
2176
        # bzr native formats have a network name of their format string.
 
2177
        network_format_registry.register(format.get_format_string(), format.__class__)
 
2178
 
 
2179
    @classmethod
 
2180
    def register_control_format(klass, format):
 
2181
        """Register a format that does not use '.bzr' for its control dir.
 
2182
 
 
2183
        TODO: This should be pulled up into a 'ControlDirFormat' base class
 
2184
        which BzrDirFormat can inherit from, and renamed to register_format
 
2185
        there. It has been done without that for now for simplicity of
 
2186
        implementation.
 
2187
        """
 
2188
        klass._control_formats.append(format)
 
2189
 
 
2190
    @classmethod
 
2191
    def register_control_server_format(klass, format):
 
2192
        """Register a control format for client-server environments.
 
2193
 
 
2194
        These formats will be tried before ones registered with
 
2195
        register_control_format.  This gives implementations that decide to the
 
2196
        chance to grab it before anything looks at the contents of the format
 
2197
        file.
 
2198
        """
 
2199
        klass._control_server_formats.append(format)
 
2200
 
 
2201
    @classmethod
 
2202
    def _set_default_format(klass, format):
 
2203
        """Set default format (for testing behavior of defaults only)"""
 
2204
        klass._default_format = format
 
2205
 
 
2206
    def __str__(self):
 
2207
        # Trim the newline
 
2208
        return self.get_format_description().rstrip()
 
2209
 
 
2210
    def _supply_sub_formats_to(self, other_format):
 
2211
        """Give other_format the same values for sub formats as this has.
 
2212
 
 
2213
        This method is expected to be used when parameterising a
 
2214
        RemoteBzrDirFormat instance with the parameters from a
 
2215
        BzrDirMetaFormat1 instance.
 
2216
 
 
2217
        :param other_format: other_format is a format which should be
 
2218
            compatible with whatever sub formats are supported by self.
 
2219
        :return: None.
 
2220
        """
 
2221
 
 
2222
    @classmethod
 
2223
    def unregister_format(klass, format):
 
2224
        del klass._formats[format.get_format_string()]
 
2225
 
 
2226
    @classmethod
 
2227
    def unregister_control_format(klass, format):
 
2228
        klass._control_formats.remove(format)
 
2229
 
 
2230
 
 
2231
class BzrDirFormat4(BzrDirFormat):
 
2232
    """Bzr dir format 4.
 
2233
 
 
2234
    This format is a combined format for working tree, branch and repository.
 
2235
    It has:
 
2236
     - Format 1 working trees [always]
 
2237
     - Format 4 branches [always]
 
2238
     - Format 4 repositories [always]
 
2239
 
 
2240
    This format is deprecated: it indexes texts using a text it which is
 
2241
    removed in format 5; write support for this format has been removed.
 
2242
    """
 
2243
 
 
2244
    _lock_class = lockable_files.TransportLock
 
2245
 
 
2246
    def get_format_string(self):
 
2247
        """See BzrDirFormat.get_format_string()."""
 
2248
        return "Bazaar-NG branch, format 0.0.4\n"
 
2249
 
 
2250
    def get_format_description(self):
 
2251
        """See BzrDirFormat.get_format_description()."""
 
2252
        return "All-in-one format 4"
 
2253
 
 
2254
    def get_converter(self, format=None):
 
2255
        """See BzrDirFormat.get_converter()."""
 
2256
        # there is one and only one upgrade path here.
 
2257
        return ConvertBzrDir4To5()
 
2258
 
 
2259
    def initialize_on_transport(self, transport):
 
2260
        """Format 4 branches cannot be created."""
 
2261
        raise errors.UninitializableFormat(self)
 
2262
 
 
2263
    def is_supported(self):
 
2264
        """Format 4 is not supported.
 
2265
 
 
2266
        It is not supported because the model changed from 4 to 5 and the
 
2267
        conversion logic is expensive - so doing it on the fly was not
 
2268
        feasible.
 
2269
        """
 
2270
        return False
 
2271
 
 
2272
    def network_name(self):
 
2273
        return self.get_format_string()
 
2274
 
 
2275
    def _open(self, transport):
 
2276
        """See BzrDirFormat._open."""
 
2277
        return BzrDir4(transport, self)
 
2278
 
 
2279
    def __return_repository_format(self):
 
2280
        """Circular import protection."""
 
2281
        from bzrlib.repofmt.weaverepo import RepositoryFormat4
 
2282
        return RepositoryFormat4()
 
2283
    repository_format = property(__return_repository_format)
 
2284
 
 
2285
 
 
2286
class BzrDirFormatAllInOne(BzrDirFormat):
 
2287
    """Common class for formats before meta-dirs."""
 
2288
 
 
2289
    def initialize_on_transport_ex(self, transport, use_existing_dir=False,
 
2290
        create_prefix=False, force_new_repo=False, stacked_on=None,
 
2291
        stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
 
2292
        shared_repo=False):
 
2293
        """See BzrDirFormat.initialize_on_transport_ex."""
 
2294
        require_stacking = (stacked_on is not None)
 
2295
        # Format 5 cannot stack, but we've been asked to - actually init
 
2296
        # a Meta1Dir
 
2297
        if require_stacking:
 
2298
            format = BzrDirMetaFormat1()
 
2299
            return format.initialize_on_transport_ex(transport,
 
2300
                use_existing_dir=use_existing_dir, create_prefix=create_prefix,
 
2301
                force_new_repo=force_new_repo, stacked_on=stacked_on,
 
2302
                stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
 
2303
                make_working_trees=make_working_trees, shared_repo=shared_repo)
 
2304
        return BzrDirFormat.initialize_on_transport_ex(self, transport,
 
2305
            use_existing_dir=use_existing_dir, create_prefix=create_prefix,
 
2306
            force_new_repo=force_new_repo, stacked_on=stacked_on,
 
2307
            stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
 
2308
            make_working_trees=make_working_trees, shared_repo=shared_repo)
 
2309
 
 
2310
 
 
2311
class BzrDirFormat5(BzrDirFormatAllInOne):
 
2312
    """Bzr control format 5.
 
2313
 
 
2314
    This format is a combined format for working tree, branch and repository.
 
2315
    It has:
 
2316
     - Format 2 working trees [always]
 
2317
     - Format 4 branches [always]
 
2318
     - Format 5 repositories [always]
 
2319
       Unhashed stores in the repository.
 
2320
    """
 
2321
 
 
2322
    _lock_class = lockable_files.TransportLock
 
2323
 
 
2324
    def get_format_string(self):
 
2325
        """See BzrDirFormat.get_format_string()."""
 
2326
        return "Bazaar-NG branch, format 5\n"
 
2327
 
 
2328
    def get_branch_format(self):
 
2329
        from bzrlib import branch
 
2330
        return branch.BzrBranchFormat4()
 
2331
 
 
2332
    def get_format_description(self):
 
2333
        """See BzrDirFormat.get_format_description()."""
 
2334
        return "All-in-one format 5"
 
2335
 
 
2336
    def get_converter(self, format=None):
 
2337
        """See BzrDirFormat.get_converter()."""
 
2338
        # there is one and only one upgrade path here.
 
2339
        return ConvertBzrDir5To6()
 
2340
 
 
2341
    def _initialize_for_clone(self, url):
 
2342
        return self.initialize_on_transport(get_transport(url), _cloning=True)
 
2343
 
 
2344
    def initialize_on_transport(self, transport, _cloning=False):
 
2345
        """Format 5 dirs always have working tree, branch and repository.
 
2346
 
 
2347
        Except when they are being cloned.
 
2348
        """
 
2349
        from bzrlib.branch import BzrBranchFormat4
 
2350
        from bzrlib.repofmt.weaverepo import RepositoryFormat5
 
2351
        result = (super(BzrDirFormat5, self).initialize_on_transport(transport))
 
2352
        RepositoryFormat5().initialize(result, _internal=True)
 
2353
        if not _cloning:
 
2354
            branch = BzrBranchFormat4().initialize(result)
 
2355
            result._init_workingtree()
 
2356
        return result
 
2357
 
 
2358
    def network_name(self):
 
2359
        return self.get_format_string()
 
2360
 
 
2361
    def _open(self, transport):
 
2362
        """See BzrDirFormat._open."""
 
2363
        return BzrDir5(transport, self)
 
2364
 
 
2365
    def __return_repository_format(self):
 
2366
        """Circular import protection."""
 
2367
        from bzrlib.repofmt.weaverepo import RepositoryFormat5
 
2368
        return RepositoryFormat5()
 
2369
    repository_format = property(__return_repository_format)
 
2370
 
 
2371
 
 
2372
class BzrDirFormat6(BzrDirFormatAllInOne):
 
2373
    """Bzr control format 6.
 
2374
 
 
2375
    This format is a combined format for working tree, branch and repository.
 
2376
    It has:
 
2377
     - Format 2 working trees [always]
 
2378
     - Format 4 branches [always]
 
2379
     - Format 6 repositories [always]
 
2380
    """
 
2381
 
 
2382
    _lock_class = lockable_files.TransportLock
 
2383
 
 
2384
    def get_format_string(self):
 
2385
        """See BzrDirFormat.get_format_string()."""
 
2386
        return "Bazaar-NG branch, format 6\n"
 
2387
 
 
2388
    def get_format_description(self):
 
2389
        """See BzrDirFormat.get_format_description()."""
 
2390
        return "All-in-one format 6"
 
2391
 
 
2392
    def get_branch_format(self):
 
2393
        from bzrlib import branch
 
2394
        return branch.BzrBranchFormat4()
 
2395
 
 
2396
    def get_converter(self, format=None):
 
2397
        """See BzrDirFormat.get_converter()."""
 
2398
        # there is one and only one upgrade path here.
 
2399
        return ConvertBzrDir6ToMeta()
 
2400
 
 
2401
    def _initialize_for_clone(self, url):
 
2402
        return self.initialize_on_transport(get_transport(url), _cloning=True)
 
2403
 
 
2404
    def initialize_on_transport(self, transport, _cloning=False):
 
2405
        """Format 6 dirs always have working tree, branch and repository.
 
2406
 
 
2407
        Except when they are being cloned.
 
2408
        """
 
2409
        from bzrlib.branch import BzrBranchFormat4
 
2410
        from bzrlib.repofmt.weaverepo import RepositoryFormat6
 
2411
        result = super(BzrDirFormat6, self).initialize_on_transport(transport)
 
2412
        RepositoryFormat6().initialize(result, _internal=True)
 
2413
        if not _cloning:
 
2414
            branch = BzrBranchFormat4().initialize(result)
 
2415
            result._init_workingtree()
 
2416
        return result
 
2417
 
 
2418
    def network_name(self):
 
2419
        return self.get_format_string()
 
2420
 
 
2421
    def _open(self, transport):
 
2422
        """See BzrDirFormat._open."""
 
2423
        return BzrDir6(transport, self)
 
2424
 
 
2425
    def __return_repository_format(self):
 
2426
        """Circular import protection."""
 
2427
        from bzrlib.repofmt.weaverepo import RepositoryFormat6
 
2428
        return RepositoryFormat6()
 
2429
    repository_format = property(__return_repository_format)
 
2430
 
 
2431
 
 
2432
class BzrDirMetaFormat1(BzrDirFormat):
 
2433
    """Bzr meta control format 1
 
2434
 
 
2435
    This is the first format with split out working tree, branch and repository
 
2436
    disk storage.
 
2437
    It has:
 
2438
     - Format 3 working trees [optional]
 
2439
     - Format 5 branches [optional]
 
2440
     - Format 7 repositories [optional]
 
2441
    """
 
2442
 
 
2443
    _lock_class = lockdir.LockDir
 
2444
 
 
2445
    def __init__(self):
 
2446
        self._workingtree_format = None
 
2447
        self._branch_format = None
 
2448
        self._repository_format = None
 
2449
 
 
2450
    def __eq__(self, other):
 
2451
        if other.__class__ is not self.__class__:
 
2452
            return False
 
2453
        if other.repository_format != self.repository_format:
 
2454
            return False
 
2455
        if other.workingtree_format != self.workingtree_format:
 
2456
            return False
 
2457
        return True
 
2458
 
 
2459
    def __ne__(self, other):
 
2460
        return not self == other
 
2461
 
 
2462
    def get_branch_format(self):
 
2463
        if self._branch_format is None:
 
2464
            from bzrlib.branch import BranchFormat
 
2465
            self._branch_format = BranchFormat.get_default_format()
 
2466
        return self._branch_format
 
2467
 
 
2468
    def set_branch_format(self, format):
 
2469
        self._branch_format = format
 
2470
 
 
2471
    def require_stacking(self, stack_on=None, possible_transports=None,
 
2472
            _skip_repo=False):
 
2473
        """We have a request to stack, try to ensure the formats support it.
 
2474
 
 
2475
        :param stack_on: If supplied, it is the URL to a branch that we want to
 
2476
            stack on. Check to see if that format supports stacking before
 
2477
            forcing an upgrade.
 
2478
        """
 
2479
        # Stacking is desired. requested by the target, but does the place it
 
2480
        # points at support stacking? If it doesn't then we should
 
2481
        # not implicitly upgrade. We check this here.
 
2482
        new_repo_format = None
 
2483
        new_branch_format = None
 
2484
 
 
2485
        # a bit of state for get_target_branch so that we don't try to open it
 
2486
        # 2 times, for both repo *and* branch
 
2487
        target = [None, False, None] # target_branch, checked, upgrade anyway
 
2488
        def get_target_branch():
 
2489
            if target[1]:
 
2490
                # We've checked, don't check again
 
2491
                return target
 
2492
            if stack_on is None:
 
2493
                # No target format, that means we want to force upgrading
 
2494
                target[:] = [None, True, True]
 
2495
                return target
 
2496
            try:
 
2497
                target_dir = BzrDir.open(stack_on,
 
2498
                    possible_transports=possible_transports)
 
2499
            except errors.NotBranchError:
 
2500
                # Nothing there, don't change formats
 
2501
                target[:] = [None, True, False]
 
2502
                return target
 
2503
            except errors.JailBreak:
 
2504
                # JailBreak, JFDI and upgrade anyway
 
2505
                target[:] = [None, True, True]
 
2506
                return target
 
2507
            try:
 
2508
                target_branch = target_dir.open_branch()
 
2509
            except errors.NotBranchError:
 
2510
                # No branch, don't upgrade formats
 
2511
                target[:] = [None, True, False]
 
2512
                return target
 
2513
            target[:] = [target_branch, True, False]
 
2514
            return target
 
2515
 
 
2516
        if (not _skip_repo and
 
2517
                 not self.repository_format.supports_external_lookups):
 
2518
            # We need to upgrade the Repository.
 
2519
            target_branch, _, do_upgrade = get_target_branch()
 
2520
            if target_branch is None:
 
2521
                # We don't have a target branch, should we upgrade anyway?
 
2522
                if do_upgrade:
 
2523
                    # stack_on is inaccessible, JFDI.
 
2524
                    # TODO: bad monkey, hard-coded formats...
 
2525
                    if self.repository_format.rich_root_data:
 
2526
                        new_repo_format = pack_repo.RepositoryFormatKnitPack5RichRoot()
 
2527
                    else:
 
2528
                        new_repo_format = pack_repo.RepositoryFormatKnitPack5()
 
2529
            else:
 
2530
                # If the target already supports stacking, then we know the
 
2531
                # project is already able to use stacking, so auto-upgrade
 
2532
                # for them
 
2533
                new_repo_format = target_branch.repository._format
 
2534
                if not new_repo_format.supports_external_lookups:
 
2535
                    # target doesn't, source doesn't, so don't auto upgrade
 
2536
                    # repo
 
2537
                    new_repo_format = None
 
2538
            if new_repo_format is not None:
 
2539
                self.repository_format = new_repo_format
 
2540
                note('Source repository format does not support stacking,'
 
2541
                     ' using format:\n  %s',
 
2542
                     new_repo_format.get_format_description())
 
2543
 
 
2544
        if not self.get_branch_format().supports_stacking():
 
2545
            # We just checked the repo, now lets check if we need to
 
2546
            # upgrade the branch format
 
2547
            target_branch, _, do_upgrade = get_target_branch()
 
2548
            if target_branch is None:
 
2549
                if do_upgrade:
 
2550
                    # TODO: bad monkey, hard-coded formats...
 
2551
                    new_branch_format = branch.BzrBranchFormat7()
 
2552
            else:
 
2553
                new_branch_format = target_branch._format
 
2554
                if not new_branch_format.supports_stacking():
 
2555
                    new_branch_format = None
 
2556
            if new_branch_format is not None:
 
2557
                # Does support stacking, use its format.
 
2558
                self.set_branch_format(new_branch_format)
 
2559
                note('Source branch format does not support stacking,'
 
2560
                     ' using format:\n  %s',
 
2561
                     new_branch_format.get_format_description())
 
2562
 
 
2563
    def get_converter(self, format=None):
 
2564
        """See BzrDirFormat.get_converter()."""
 
2565
        if format is None:
 
2566
            format = BzrDirFormat.get_default_format()
 
2567
        if not isinstance(self, format.__class__):
 
2568
            # converting away from metadir is not implemented
 
2569
            raise NotImplementedError(self.get_converter)
 
2570
        return ConvertMetaToMeta(format)
 
2571
 
 
2572
    def get_format_string(self):
 
2573
        """See BzrDirFormat.get_format_string()."""
 
2574
        return "Bazaar-NG meta directory, format 1\n"
 
2575
 
 
2576
    def get_format_description(self):
 
2577
        """See BzrDirFormat.get_format_description()."""
 
2578
        return "Meta directory format 1"
 
2579
 
 
2580
    def network_name(self):
 
2581
        return self.get_format_string()
 
2582
 
 
2583
    def _open(self, transport):
 
2584
        """See BzrDirFormat._open."""
 
2585
        # Create a new format instance because otherwise initialisation of new
 
2586
        # metadirs share the global default format object leading to alias
 
2587
        # problems.
 
2588
        format = BzrDirMetaFormat1()
 
2589
        self._supply_sub_formats_to(format)
 
2590
        return BzrDirMeta1(transport, format)
 
2591
 
 
2592
    def __return_repository_format(self):
 
2593
        """Circular import protection."""
 
2594
        if self._repository_format:
 
2595
            return self._repository_format
 
2596
        from bzrlib.repository import RepositoryFormat
 
2597
        return RepositoryFormat.get_default_format()
 
2598
 
 
2599
    def _set_repository_format(self, value):
 
2600
        """Allow changing the repository format for metadir formats."""
 
2601
        self._repository_format = value
 
2602
 
 
2603
    repository_format = property(__return_repository_format,
 
2604
        _set_repository_format)
 
2605
 
 
2606
    def _supply_sub_formats_to(self, other_format):
 
2607
        """Give other_format the same values for sub formats as this has.
 
2608
 
 
2609
        This method is expected to be used when parameterising a
 
2610
        RemoteBzrDirFormat instance with the parameters from a
 
2611
        BzrDirMetaFormat1 instance.
 
2612
 
 
2613
        :param other_format: other_format is a format which should be
 
2614
            compatible with whatever sub formats are supported by self.
 
2615
        :return: None.
 
2616
        """
 
2617
        if getattr(self, '_repository_format', None) is not None:
 
2618
            other_format.repository_format = self.repository_format
 
2619
        if self._branch_format is not None:
 
2620
            other_format._branch_format = self._branch_format
 
2621
        if self._workingtree_format is not None:
 
2622
            other_format.workingtree_format = self.workingtree_format
 
2623
 
 
2624
    def __get_workingtree_format(self):
 
2625
        if self._workingtree_format is None:
 
2626
            from bzrlib.workingtree import WorkingTreeFormat
 
2627
            self._workingtree_format = WorkingTreeFormat.get_default_format()
 
2628
        return self._workingtree_format
 
2629
 
 
2630
    def __set_workingtree_format(self, wt_format):
 
2631
        self._workingtree_format = wt_format
 
2632
 
 
2633
    workingtree_format = property(__get_workingtree_format,
 
2634
                                  __set_workingtree_format)
 
2635
 
 
2636
 
 
2637
network_format_registry = registry.FormatRegistry()
 
2638
"""Registry of formats indexed by their network name.
 
2639
 
 
2640
The network name for a BzrDirFormat is an identifier that can be used when
 
2641
referring to formats with smart server operations. See
 
2642
BzrDirFormat.network_name() for more detail.
 
2643
"""
 
2644
 
 
2645
 
 
2646
# Register bzr control format
 
2647
BzrDirFormat.register_control_format(BzrDirFormat)
 
2648
 
 
2649
# Register bzr formats
 
2650
BzrDirFormat.register_format(BzrDirFormat4())
 
2651
BzrDirFormat.register_format(BzrDirFormat5())
 
2652
BzrDirFormat.register_format(BzrDirFormat6())
 
2653
__default_format = BzrDirMetaFormat1()
 
2654
BzrDirFormat.register_format(__default_format)
 
2655
BzrDirFormat._default_format = __default_format
 
2656
 
 
2657
 
 
2658
class Converter(object):
 
2659
    """Converts a disk format object from one format to another."""
 
2660
 
 
2661
    def convert(self, to_convert, pb):
 
2662
        """Perform the conversion of to_convert, giving feedback via pb.
 
2663
 
 
2664
        :param to_convert: The disk object to convert.
 
2665
        :param pb: a progress bar to use for progress information.
 
2666
        """
 
2667
 
 
2668
    def step(self, message):
 
2669
        """Update the pb by a step."""
 
2670
        self.count +=1
 
2671
        self.pb.update(message, self.count, self.total)
 
2672
 
 
2673
 
 
2674
class ConvertBzrDir4To5(Converter):
 
2675
    """Converts format 4 bzr dirs to format 5."""
 
2676
 
 
2677
    def __init__(self):
 
2678
        super(ConvertBzrDir4To5, self).__init__()
 
2679
        self.converted_revs = set()
 
2680
        self.absent_revisions = set()
 
2681
        self.text_count = 0
 
2682
        self.revisions = {}
 
2683
 
 
2684
    def convert(self, to_convert, pb):
 
2685
        """See Converter.convert()."""
 
2686
        self.bzrdir = to_convert
 
2687
        if pb is not None:
 
2688
            warnings.warn("pb parameter to convert() is deprecated")
 
2689
        self.pb = ui.ui_factory.nested_progress_bar()
 
2690
        try:
 
2691
            ui.ui_factory.note('starting upgrade from format 4 to 5')
 
2692
            if isinstance(self.bzrdir.transport, local.LocalTransport):
 
2693
                self.bzrdir.get_workingtree_transport(None).delete('stat-cache')
 
2694
            self._convert_to_weaves()
 
2695
            return BzrDir.open(self.bzrdir.root_transport.base)
 
2696
        finally:
 
2697
            self.pb.finished()
 
2698
 
 
2699
    def _convert_to_weaves(self):
 
2700
        ui.ui_factory.note('note: upgrade may be faster if all store files are ungzipped first')
 
2701
        try:
 
2702
            # TODO permissions
 
2703
            stat = self.bzrdir.transport.stat('weaves')
 
2704
            if not S_ISDIR(stat.st_mode):
 
2705
                self.bzrdir.transport.delete('weaves')
 
2706
                self.bzrdir.transport.mkdir('weaves')
 
2707
        except errors.NoSuchFile:
 
2708
            self.bzrdir.transport.mkdir('weaves')
 
2709
        # deliberately not a WeaveFile as we want to build it up slowly.
 
2710
        self.inv_weave = Weave('inventory')
 
2711
        # holds in-memory weaves for all files
 
2712
        self.text_weaves = {}
 
2713
        self.bzrdir.transport.delete('branch-format')
 
2714
        self.branch = self.bzrdir.open_branch()
 
2715
        self._convert_working_inv()
 
2716
        rev_history = self.branch.revision_history()
 
2717
        # to_read is a stack holding the revisions we still need to process;
 
2718
        # appending to it adds new highest-priority revisions
 
2719
        self.known_revisions = set(rev_history)
 
2720
        self.to_read = rev_history[-1:]
 
2721
        while self.to_read:
 
2722
            rev_id = self.to_read.pop()
 
2723
            if (rev_id not in self.revisions
 
2724
                and rev_id not in self.absent_revisions):
 
2725
                self._load_one_rev(rev_id)
 
2726
        self.pb.clear()
 
2727
        to_import = self._make_order()
 
2728
        for i, rev_id in enumerate(to_import):
 
2729
            self.pb.update('converting revision', i, len(to_import))
 
2730
            self._convert_one_rev(rev_id)
 
2731
        self.pb.clear()
 
2732
        self._write_all_weaves()
 
2733
        self._write_all_revs()
 
2734
        ui.ui_factory.note('upgraded to weaves:')
 
2735
        ui.ui_factory.note('  %6d revisions and inventories' % len(self.revisions))
 
2736
        ui.ui_factory.note('  %6d revisions not present' % len(self.absent_revisions))
 
2737
        ui.ui_factory.note('  %6d texts' % self.text_count)
 
2738
        self._cleanup_spare_files_after_format4()
 
2739
        self.branch._transport.put_bytes(
 
2740
            'branch-format',
 
2741
            BzrDirFormat5().get_format_string(),
 
2742
            mode=self.bzrdir._get_file_mode())
 
2743
 
 
2744
    def _cleanup_spare_files_after_format4(self):
 
2745
        # FIXME working tree upgrade foo.
 
2746
        for n in 'merged-patches', 'pending-merged-patches':
 
2747
            try:
 
2748
                ## assert os.path.getsize(p) == 0
 
2749
                self.bzrdir.transport.delete(n)
 
2750
            except errors.NoSuchFile:
 
2751
                pass
 
2752
        self.bzrdir.transport.delete_tree('inventory-store')
 
2753
        self.bzrdir.transport.delete_tree('text-store')
 
2754
 
 
2755
    def _convert_working_inv(self):
 
2756
        inv = xml4.serializer_v4.read_inventory(
 
2757
                self.branch._transport.get('inventory'))
 
2758
        new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv, working=True)
 
2759
        self.branch._transport.put_bytes('inventory', new_inv_xml,
 
2760
            mode=self.bzrdir._get_file_mode())
 
2761
 
 
2762
    def _write_all_weaves(self):
 
2763
        controlweaves = WeaveStore(self.bzrdir.transport, prefixed=False)
 
2764
        weave_transport = self.bzrdir.transport.clone('weaves')
 
2765
        weaves = WeaveStore(weave_transport, prefixed=False)
 
2766
        transaction = WriteTransaction()
 
2767
 
 
2768
        try:
 
2769
            i = 0
 
2770
            for file_id, file_weave in self.text_weaves.items():
 
2771
                self.pb.update('writing weave', i, len(self.text_weaves))
 
2772
                weaves._put_weave(file_id, file_weave, transaction)
 
2773
                i += 1
 
2774
            self.pb.update('inventory', 0, 1)
 
2775
            controlweaves._put_weave('inventory', self.inv_weave, transaction)
 
2776
            self.pb.update('inventory', 1, 1)
 
2777
        finally:
 
2778
            self.pb.clear()
 
2779
 
 
2780
    def _write_all_revs(self):
 
2781
        """Write all revisions out in new form."""
 
2782
        self.bzrdir.transport.delete_tree('revision-store')
 
2783
        self.bzrdir.transport.mkdir('revision-store')
 
2784
        revision_transport = self.bzrdir.transport.clone('revision-store')
 
2785
        # TODO permissions
 
2786
        from bzrlib.xml5 import serializer_v5
 
2787
        from bzrlib.repofmt.weaverepo import RevisionTextStore
 
2788
        revision_store = RevisionTextStore(revision_transport,
 
2789
            serializer_v5, False, versionedfile.PrefixMapper(),
 
2790
            lambda:True, lambda:True)
 
2791
        try:
 
2792
            for i, rev_id in enumerate(self.converted_revs):
 
2793
                self.pb.update('write revision', i, len(self.converted_revs))
 
2794
                text = serializer_v5.write_revision_to_string(
 
2795
                    self.revisions[rev_id])
 
2796
                key = (rev_id,)
 
2797
                revision_store.add_lines(key, None, osutils.split_lines(text))
 
2798
        finally:
 
2799
            self.pb.clear()
 
2800
 
 
2801
    def _load_one_rev(self, rev_id):
 
2802
        """Load a revision object into memory.
 
2803
 
 
2804
        Any parents not either loaded or abandoned get queued to be
 
2805
        loaded."""
 
2806
        self.pb.update('loading revision',
 
2807
                       len(self.revisions),
 
2808
                       len(self.known_revisions))
 
2809
        if not self.branch.repository.has_revision(rev_id):
 
2810
            self.pb.clear()
 
2811
            ui.ui_factory.note('revision {%s} not present in branch; '
 
2812
                         'will be converted as a ghost' %
 
2813
                         rev_id)
 
2814
            self.absent_revisions.add(rev_id)
 
2815
        else:
 
2816
            rev = self.branch.repository.get_revision(rev_id)
 
2817
            for parent_id in rev.parent_ids:
 
2818
                self.known_revisions.add(parent_id)
 
2819
                self.to_read.append(parent_id)
 
2820
            self.revisions[rev_id] = rev
 
2821
 
 
2822
    def _load_old_inventory(self, rev_id):
 
2823
        old_inv_xml = self.branch.repository.inventory_store.get(rev_id).read()
 
2824
        inv = xml4.serializer_v4.read_inventory_from_string(old_inv_xml)
 
2825
        inv.revision_id = rev_id
 
2826
        rev = self.revisions[rev_id]
 
2827
        return inv
 
2828
 
 
2829
    def _load_updated_inventory(self, rev_id):
 
2830
        inv_xml = self.inv_weave.get_text(rev_id)
 
2831
        inv = xml5.serializer_v5.read_inventory_from_string(inv_xml, rev_id)
 
2832
        return inv
 
2833
 
 
2834
    def _convert_one_rev(self, rev_id):
 
2835
        """Convert revision and all referenced objects to new format."""
 
2836
        rev = self.revisions[rev_id]
 
2837
        inv = self._load_old_inventory(rev_id)
 
2838
        present_parents = [p for p in rev.parent_ids
 
2839
                           if p not in self.absent_revisions]
 
2840
        self._convert_revision_contents(rev, inv, present_parents)
 
2841
        self._store_new_inv(rev, inv, present_parents)
 
2842
        self.converted_revs.add(rev_id)
 
2843
 
 
2844
    def _store_new_inv(self, rev, inv, present_parents):
 
2845
        new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv)
 
2846
        new_inv_sha1 = sha_string(new_inv_xml)
 
2847
        self.inv_weave.add_lines(rev.revision_id,
 
2848
                                 present_parents,
 
2849
                                 new_inv_xml.splitlines(True))
 
2850
        rev.inventory_sha1 = new_inv_sha1
 
2851
 
 
2852
    def _convert_revision_contents(self, rev, inv, present_parents):
 
2853
        """Convert all the files within a revision.
 
2854
 
 
2855
        Also upgrade the inventory to refer to the text revision ids."""
 
2856
        rev_id = rev.revision_id
 
2857
        mutter('converting texts of revision {%s}',
 
2858
               rev_id)
 
2859
        parent_invs = map(self._load_updated_inventory, present_parents)
 
2860
        entries = inv.iter_entries()
 
2861
        entries.next()
 
2862
        for path, ie in entries:
 
2863
            self._convert_file_version(rev, ie, parent_invs)
 
2864
 
 
2865
    def _convert_file_version(self, rev, ie, parent_invs):
 
2866
        """Convert one version of one file.
 
2867
 
 
2868
        The file needs to be added into the weave if it is a merge
 
2869
        of >=2 parents or if it's changed from its parent.
 
2870
        """
 
2871
        file_id = ie.file_id
 
2872
        rev_id = rev.revision_id
 
2873
        w = self.text_weaves.get(file_id)
 
2874
        if w is None:
 
2875
            w = Weave(file_id)
 
2876
            self.text_weaves[file_id] = w
 
2877
        text_changed = False
 
2878
        parent_candiate_entries = ie.parent_candidates(parent_invs)
 
2879
        heads = graph.Graph(self).heads(parent_candiate_entries.keys())
 
2880
        # XXX: Note that this is unordered - and this is tolerable because
 
2881
        # the previous code was also unordered.
 
2882
        previous_entries = dict((head, parent_candiate_entries[head]) for head
 
2883
            in heads)
 
2884
        self.snapshot_ie(previous_entries, ie, w, rev_id)
 
2885
        del ie.text_id
 
2886
 
 
2887
    def get_parent_map(self, revision_ids):
 
2888
        """See graph.StackedParentsProvider.get_parent_map"""
 
2889
        return dict((revision_id, self.revisions[revision_id])
 
2890
                    for revision_id in revision_ids
 
2891
                     if revision_id in self.revisions)
 
2892
 
 
2893
    def snapshot_ie(self, previous_revisions, ie, w, rev_id):
 
2894
        # TODO: convert this logic, which is ~= snapshot to
 
2895
        # a call to:. This needs the path figured out. rather than a work_tree
 
2896
        # a v4 revision_tree can be given, or something that looks enough like
 
2897
        # one to give the file content to the entry if it needs it.
 
2898
        # and we need something that looks like a weave store for snapshot to
 
2899
        # save against.
 
2900
        #ie.snapshot(rev, PATH, previous_revisions, REVISION_TREE, InMemoryWeaveStore(self.text_weaves))
 
2901
        if len(previous_revisions) == 1:
 
2902
            previous_ie = previous_revisions.values()[0]
 
2903
            if ie._unchanged(previous_ie):
 
2904
                ie.revision = previous_ie.revision
 
2905
                return
 
2906
        if ie.has_text():
 
2907
            text = self.branch.repository._text_store.get(ie.text_id)
 
2908
            file_lines = text.readlines()
 
2909
            w.add_lines(rev_id, previous_revisions, file_lines)
 
2910
            self.text_count += 1
 
2911
        else:
 
2912
            w.add_lines(rev_id, previous_revisions, [])
 
2913
        ie.revision = rev_id
 
2914
 
 
2915
    def _make_order(self):
 
2916
        """Return a suitable order for importing revisions.
 
2917
 
 
2918
        The order must be such that an revision is imported after all
 
2919
        its (present) parents.
 
2920
        """
 
2921
        todo = set(self.revisions.keys())
 
2922
        done = self.absent_revisions.copy()
 
2923
        order = []
 
2924
        while todo:
 
2925
            # scan through looking for a revision whose parents
 
2926
            # are all done
 
2927
            for rev_id in sorted(list(todo)):
 
2928
                rev = self.revisions[rev_id]
 
2929
                parent_ids = set(rev.parent_ids)
 
2930
                if parent_ids.issubset(done):
 
2931
                    # can take this one now
 
2932
                    order.append(rev_id)
 
2933
                    todo.remove(rev_id)
 
2934
                    done.add(rev_id)
 
2935
        return order
 
2936
 
 
2937
 
 
2938
class ConvertBzrDir5To6(Converter):
 
2939
    """Converts format 5 bzr dirs to format 6."""
 
2940
 
 
2941
    def convert(self, to_convert, pb):
 
2942
        """See Converter.convert()."""
 
2943
        self.bzrdir = to_convert
 
2944
        pb = ui.ui_factory.nested_progress_bar()
 
2945
        try:
 
2946
            ui.ui_factory.note('starting upgrade from format 5 to 6')
 
2947
            self._convert_to_prefixed()
 
2948
            return BzrDir.open(self.bzrdir.root_transport.base)
 
2949
        finally:
 
2950
            pb.finished()
 
2951
 
 
2952
    def _convert_to_prefixed(self):
 
2953
        from bzrlib.store import TransportStore
 
2954
        self.bzrdir.transport.delete('branch-format')
 
2955
        for store_name in ["weaves", "revision-store"]:
 
2956
            ui.ui_factory.note("adding prefixes to %s" % store_name)
 
2957
            store_transport = self.bzrdir.transport.clone(store_name)
 
2958
            store = TransportStore(store_transport, prefixed=True)
 
2959
            for urlfilename in store_transport.list_dir('.'):
 
2960
                filename = urlutils.unescape(urlfilename)
 
2961
                if (filename.endswith(".weave") or
 
2962
                    filename.endswith(".gz") or
 
2963
                    filename.endswith(".sig")):
 
2964
                    file_id, suffix = os.path.splitext(filename)
 
2965
                else:
 
2966
                    file_id = filename
 
2967
                    suffix = ''
 
2968
                new_name = store._mapper.map((file_id,)) + suffix
 
2969
                # FIXME keep track of the dirs made RBC 20060121
 
2970
                try:
 
2971
                    store_transport.move(filename, new_name)
 
2972
                except errors.NoSuchFile: # catches missing dirs strangely enough
 
2973
                    store_transport.mkdir(osutils.dirname(new_name))
 
2974
                    store_transport.move(filename, new_name)
 
2975
        self.bzrdir.transport.put_bytes(
 
2976
            'branch-format',
 
2977
            BzrDirFormat6().get_format_string(),
 
2978
            mode=self.bzrdir._get_file_mode())
 
2979
 
 
2980
 
 
2981
class ConvertBzrDir6ToMeta(Converter):
 
2982
    """Converts format 6 bzr dirs to metadirs."""
 
2983
 
 
2984
    def convert(self, to_convert, pb):
 
2985
        """See Converter.convert()."""
 
2986
        from bzrlib.repofmt.weaverepo import RepositoryFormat7
 
2987
        from bzrlib.branch import BzrBranchFormat5
 
2988
        self.bzrdir = to_convert
 
2989
        self.pb = ui.ui_factory.nested_progress_bar()
 
2990
        self.count = 0
 
2991
        self.total = 20 # the steps we know about
 
2992
        self.garbage_inventories = []
 
2993
        self.dir_mode = self.bzrdir._get_dir_mode()
 
2994
        self.file_mode = self.bzrdir._get_file_mode()
 
2995
 
 
2996
        ui.ui_factory.note('starting upgrade from format 6 to metadir')
 
2997
        self.bzrdir.transport.put_bytes(
 
2998
                'branch-format',
 
2999
                "Converting to format 6",
 
3000
                mode=self.file_mode)
 
3001
        # its faster to move specific files around than to open and use the apis...
 
3002
        # first off, nuke ancestry.weave, it was never used.
 
3003
        try:
 
3004
            self.step('Removing ancestry.weave')
 
3005
            self.bzrdir.transport.delete('ancestry.weave')
 
3006
        except errors.NoSuchFile:
 
3007
            pass
 
3008
        # find out whats there
 
3009
        self.step('Finding branch files')
 
3010
        last_revision = self.bzrdir.open_branch().last_revision()
 
3011
        bzrcontents = self.bzrdir.transport.list_dir('.')
 
3012
        for name in bzrcontents:
 
3013
            if name.startswith('basis-inventory.'):
 
3014
                self.garbage_inventories.append(name)
 
3015
        # create new directories for repository, working tree and branch
 
3016
        repository_names = [('inventory.weave', True),
 
3017
                            ('revision-store', True),
 
3018
                            ('weaves', True)]
 
3019
        self.step('Upgrading repository  ')
 
3020
        self.bzrdir.transport.mkdir('repository', mode=self.dir_mode)
 
3021
        self.make_lock('repository')
 
3022
        # we hard code the formats here because we are converting into
 
3023
        # the meta format. The meta format upgrader can take this to a
 
3024
        # future format within each component.
 
3025
        self.put_format('repository', RepositoryFormat7())
 
3026
        for entry in repository_names:
 
3027
            self.move_entry('repository', entry)
 
3028
 
 
3029
        self.step('Upgrading branch      ')
 
3030
        self.bzrdir.transport.mkdir('branch', mode=self.dir_mode)
 
3031
        self.make_lock('branch')
 
3032
        self.put_format('branch', BzrBranchFormat5())
 
3033
        branch_files = [('revision-history', True),
 
3034
                        ('branch-name', True),
 
3035
                        ('parent', False)]
 
3036
        for entry in branch_files:
 
3037
            self.move_entry('branch', entry)
 
3038
 
 
3039
        checkout_files = [('pending-merges', True),
 
3040
                          ('inventory', True),
 
3041
                          ('stat-cache', False)]
 
3042
        # If a mandatory checkout file is not present, the branch does not have
 
3043
        # a functional checkout. Do not create a checkout in the converted
 
3044
        # branch.
 
3045
        for name, mandatory in checkout_files:
 
3046
            if mandatory and name not in bzrcontents:
 
3047
                has_checkout = False
 
3048
                break
 
3049
        else:
 
3050
            has_checkout = True
 
3051
        if not has_checkout:
 
3052
            ui.ui_factory.note('No working tree.')
 
3053
            # If some checkout files are there, we may as well get rid of them.
 
3054
            for name, mandatory in checkout_files:
 
3055
                if name in bzrcontents:
 
3056
                    self.bzrdir.transport.delete(name)
 
3057
        else:
 
3058
            from bzrlib.workingtree import WorkingTreeFormat3
 
3059
            self.step('Upgrading working tree')
 
3060
            self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
 
3061
            self.make_lock('checkout')
 
3062
            self.put_format(
 
3063
                'checkout', WorkingTreeFormat3())
 
3064
            self.bzrdir.transport.delete_multi(
 
3065
                self.garbage_inventories, self.pb)
 
3066
            for entry in checkout_files:
 
3067
                self.move_entry('checkout', entry)
 
3068
            if last_revision is not None:
 
3069
                self.bzrdir.transport.put_bytes(
 
3070
                    'checkout/last-revision', last_revision)
 
3071
        self.bzrdir.transport.put_bytes(
 
3072
            'branch-format',
 
3073
            BzrDirMetaFormat1().get_format_string(),
 
3074
            mode=self.file_mode)
 
3075
        self.pb.finished()
 
3076
        return BzrDir.open(self.bzrdir.root_transport.base)
 
3077
 
 
3078
    def make_lock(self, name):
 
3079
        """Make a lock for the new control dir name."""
 
3080
        self.step('Make %s lock' % name)
 
3081
        ld = lockdir.LockDir(self.bzrdir.transport,
 
3082
                             '%s/lock' % name,
 
3083
                             file_modebits=self.file_mode,
 
3084
                             dir_modebits=self.dir_mode)
 
3085
        ld.create()
 
3086
 
 
3087
    def move_entry(self, new_dir, entry):
 
3088
        """Move then entry name into new_dir."""
 
3089
        name = entry[0]
 
3090
        mandatory = entry[1]
 
3091
        self.step('Moving %s' % name)
 
3092
        try:
 
3093
            self.bzrdir.transport.move(name, '%s/%s' % (new_dir, name))
 
3094
        except errors.NoSuchFile:
 
3095
            if mandatory:
 
3096
                raise
 
3097
 
 
3098
    def put_format(self, dirname, format):
 
3099
        self.bzrdir.transport.put_bytes('%s/format' % dirname,
 
3100
            format.get_format_string(),
 
3101
            self.file_mode)
 
3102
 
 
3103
 
 
3104
class ConvertMetaToMeta(Converter):
 
3105
    """Converts the components of metadirs."""
 
3106
 
 
3107
    def __init__(self, target_format):
 
3108
        """Create a metadir to metadir converter.
 
3109
 
 
3110
        :param target_format: The final metadir format that is desired.
 
3111
        """
 
3112
        self.target_format = target_format
 
3113
 
 
3114
    def convert(self, to_convert, pb):
 
3115
        """See Converter.convert()."""
 
3116
        self.bzrdir = to_convert
 
3117
        self.pb = ui.ui_factory.nested_progress_bar()
 
3118
        self.count = 0
 
3119
        self.total = 1
 
3120
        self.step('checking repository format')
 
3121
        try:
 
3122
            repo = self.bzrdir.open_repository()
 
3123
        except errors.NoRepositoryPresent:
 
3124
            pass
 
3125
        else:
 
3126
            if not isinstance(repo._format, self.target_format.repository_format.__class__):
 
3127
                from bzrlib.repository import CopyConverter
 
3128
                ui.ui_factory.note('starting repository conversion')
 
3129
                converter = CopyConverter(self.target_format.repository_format)
 
3130
                converter.convert(repo, pb)
 
3131
        for branch in self.bzrdir.list_branches():
 
3132
            # TODO: conversions of Branch and Tree should be done by
 
3133
            # InterXFormat lookups/some sort of registry.
 
3134
            # Avoid circular imports
 
3135
            from bzrlib import branch as _mod_branch
 
3136
            old = branch._format.__class__
 
3137
            new = self.target_format.get_branch_format().__class__
 
3138
            while old != new:
 
3139
                if (old == _mod_branch.BzrBranchFormat5 and
 
3140
                    new in (_mod_branch.BzrBranchFormat6,
 
3141
                        _mod_branch.BzrBranchFormat7,
 
3142
                        _mod_branch.BzrBranchFormat8)):
 
3143
                    branch_converter = _mod_branch.Converter5to6()
 
3144
                elif (old == _mod_branch.BzrBranchFormat6 and
 
3145
                    new in (_mod_branch.BzrBranchFormat7,
 
3146
                            _mod_branch.BzrBranchFormat8)):
 
3147
                    branch_converter = _mod_branch.Converter6to7()
 
3148
                elif (old == _mod_branch.BzrBranchFormat7 and
 
3149
                      new is _mod_branch.BzrBranchFormat8):
 
3150
                    branch_converter = _mod_branch.Converter7to8()
 
3151
                else:
 
3152
                    raise errors.BadConversionTarget("No converter", new,
 
3153
                        branch._format)
 
3154
                branch_converter.convert(branch)
 
3155
                branch = self.bzrdir.open_branch()
 
3156
                old = branch._format.__class__
 
3157
        try:
 
3158
            tree = self.bzrdir.open_workingtree(recommend_upgrade=False)
 
3159
        except (errors.NoWorkingTree, errors.NotLocalUrl):
 
3160
            pass
 
3161
        else:
 
3162
            # TODO: conversions of Branch and Tree should be done by
 
3163
            # InterXFormat lookups
 
3164
            if (isinstance(tree, workingtree.WorkingTree3) and
 
3165
                not isinstance(tree, workingtree_4.DirStateWorkingTree) and
 
3166
                isinstance(self.target_format.workingtree_format,
 
3167
                    workingtree_4.DirStateWorkingTreeFormat)):
 
3168
                workingtree_4.Converter3to4().convert(tree)
 
3169
            if (isinstance(tree, workingtree_4.DirStateWorkingTree) and
 
3170
                not isinstance(tree, workingtree_4.WorkingTree5) and
 
3171
                isinstance(self.target_format.workingtree_format,
 
3172
                    workingtree_4.WorkingTreeFormat5)):
 
3173
                workingtree_4.Converter4to5().convert(tree)
 
3174
            if (isinstance(tree, workingtree_4.DirStateWorkingTree) and
 
3175
                not isinstance(tree, workingtree_4.WorkingTree6) and
 
3176
                isinstance(self.target_format.workingtree_format,
 
3177
                    workingtree_4.WorkingTreeFormat6)):
 
3178
                workingtree_4.Converter4or5to6().convert(tree)
 
3179
        self.pb.finished()
 
3180
        return to_convert
 
3181
 
 
3182
 
 
3183
# This is not in remote.py because it's relatively small, and needs to be
 
3184
# registered. Putting it in remote.py creates a circular import problem.
 
3185
# we can make it a lazy object if the control formats is turned into something
 
3186
# like a registry.
 
3187
class RemoteBzrDirFormat(BzrDirMetaFormat1):
 
3188
    """Format representing bzrdirs accessed via a smart server"""
 
3189
 
 
3190
    def __init__(self):
 
3191
        BzrDirMetaFormat1.__init__(self)
 
3192
        # XXX: It's a bit ugly that the network name is here, because we'd
 
3193
        # like to believe that format objects are stateless or at least
 
3194
        # immutable,  However, we do at least avoid mutating the name after
 
3195
        # it's returned.  See <https://bugs.edge.launchpad.net/bzr/+bug/504102>
 
3196
        self._network_name = None
 
3197
 
 
3198
    def __repr__(self):
 
3199
        return "%s(_network_name=%r)" % (self.__class__.__name__,
 
3200
            self._network_name)
 
3201
 
 
3202
    def get_format_description(self):
 
3203
        if self._network_name:
 
3204
            real_format = network_format_registry.get(self._network_name)
 
3205
            return 'Remote: ' + real_format.get_format_description()
 
3206
        return 'bzr remote bzrdir'
 
3207
 
 
3208
    def get_format_string(self):
 
3209
        raise NotImplementedError(self.get_format_string)
 
3210
 
 
3211
    def network_name(self):
 
3212
        if self._network_name:
 
3213
            return self._network_name
 
3214
        else:
 
3215
            raise AssertionError("No network name set.")
 
3216
 
 
3217
    @classmethod
 
3218
    def probe_transport(klass, transport):
 
3219
        """Return a RemoteBzrDirFormat object if it looks possible."""
 
3220
        try:
 
3221
            medium = transport.get_smart_medium()
 
3222
        except (NotImplementedError, AttributeError,
 
3223
                errors.TransportNotPossible, errors.NoSmartMedium,
 
3224
                errors.SmartProtocolError):
 
3225
            # no smart server, so not a branch for this format type.
 
3226
            raise errors.NotBranchError(path=transport.base)
 
3227
        else:
 
3228
            # Decline to open it if the server doesn't support our required
 
3229
            # version (3) so that the VFS-based transport will do it.
 
3230
            if medium.should_probe():
 
3231
                try:
 
3232
                    server_version = medium.protocol_version()
 
3233
                except errors.SmartProtocolError:
 
3234
                    # Apparently there's no usable smart server there, even though
 
3235
                    # the medium supports the smart protocol.
 
3236
                    raise errors.NotBranchError(path=transport.base)
 
3237
                if server_version != '2':
 
3238
                    raise errors.NotBranchError(path=transport.base)
 
3239
            return klass()
 
3240
 
 
3241
    def initialize_on_transport(self, transport):
 
3242
        try:
 
3243
            # hand off the request to the smart server
 
3244
            client_medium = transport.get_smart_medium()
 
3245
        except errors.NoSmartMedium:
 
3246
            # TODO: lookup the local format from a server hint.
 
3247
            local_dir_format = BzrDirMetaFormat1()
 
3248
            return local_dir_format.initialize_on_transport(transport)
 
3249
        client = _SmartClient(client_medium)
 
3250
        path = client.remote_path_from_transport(transport)
 
3251
        try:
 
3252
            response = client.call('BzrDirFormat.initialize', path)
 
3253
        except errors.ErrorFromSmartServer, err:
 
3254
            remote._translate_error(err, path=path)
 
3255
        if response[0] != 'ok':
 
3256
            raise errors.SmartProtocolError('unexpected response code %s' % (response,))
 
3257
        format = RemoteBzrDirFormat()
 
3258
        self._supply_sub_formats_to(format)
 
3259
        return remote.RemoteBzrDir(transport, format)
 
3260
 
 
3261
    def parse_NoneTrueFalse(self, arg):
 
3262
        if not arg:
 
3263
            return None
 
3264
        if arg == 'False':
 
3265
            return False
 
3266
        if arg == 'True':
 
3267
            return True
 
3268
        raise AssertionError("invalid arg %r" % arg)
 
3269
 
 
3270
    def _serialize_NoneTrueFalse(self, arg):
 
3271
        if arg is False:
 
3272
            return 'False'
 
3273
        if arg:
 
3274
            return 'True'
 
3275
        return ''
 
3276
 
 
3277
    def _serialize_NoneString(self, arg):
 
3278
        return arg or ''
 
3279
 
 
3280
    def initialize_on_transport_ex(self, transport, use_existing_dir=False,
 
3281
        create_prefix=False, force_new_repo=False, stacked_on=None,
 
3282
        stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
 
3283
        shared_repo=False):
 
3284
        try:
 
3285
            # hand off the request to the smart server
 
3286
            client_medium = transport.get_smart_medium()
 
3287
        except errors.NoSmartMedium:
 
3288
            do_vfs = True
 
3289
        else:
 
3290
            # Decline to open it if the server doesn't support our required
 
3291
            # version (3) so that the VFS-based transport will do it.
 
3292
            if client_medium.should_probe():
 
3293
                try:
 
3294
                    server_version = client_medium.protocol_version()
 
3295
                    if server_version != '2':
 
3296
                        do_vfs = True
 
3297
                    else:
 
3298
                        do_vfs = False
 
3299
                except errors.SmartProtocolError:
 
3300
                    # Apparently there's no usable smart server there, even though
 
3301
                    # the medium supports the smart protocol.
 
3302
                    do_vfs = True
 
3303
            else:
 
3304
                do_vfs = False
 
3305
        if not do_vfs:
 
3306
            client = _SmartClient(client_medium)
 
3307
            path = client.remote_path_from_transport(transport)
 
3308
            if client_medium._is_remote_before((1, 16)):
 
3309
                do_vfs = True
 
3310
        if do_vfs:
 
3311
            # TODO: lookup the local format from a server hint.
 
3312
            local_dir_format = BzrDirMetaFormat1()
 
3313
            self._supply_sub_formats_to(local_dir_format)
 
3314
            return local_dir_format.initialize_on_transport_ex(transport,
 
3315
                use_existing_dir=use_existing_dir, create_prefix=create_prefix,
 
3316
                force_new_repo=force_new_repo, stacked_on=stacked_on,
 
3317
                stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
 
3318
                make_working_trees=make_working_trees, shared_repo=shared_repo,
 
3319
                vfs_only=True)
 
3320
        return self._initialize_on_transport_ex_rpc(client, path, transport,
 
3321
            use_existing_dir, create_prefix, force_new_repo, stacked_on,
 
3322
            stack_on_pwd, repo_format_name, make_working_trees, shared_repo)
 
3323
 
 
3324
    def _initialize_on_transport_ex_rpc(self, client, path, transport,
 
3325
        use_existing_dir, create_prefix, force_new_repo, stacked_on,
 
3326
        stack_on_pwd, repo_format_name, make_working_trees, shared_repo):
 
3327
        args = []
 
3328
        args.append(self._serialize_NoneTrueFalse(use_existing_dir))
 
3329
        args.append(self._serialize_NoneTrueFalse(create_prefix))
 
3330
        args.append(self._serialize_NoneTrueFalse(force_new_repo))
 
3331
        args.append(self._serialize_NoneString(stacked_on))
 
3332
        # stack_on_pwd is often/usually our transport
 
3333
        if stack_on_pwd:
 
3334
            try:
 
3335
                stack_on_pwd = transport.relpath(stack_on_pwd)
 
3336
                if not stack_on_pwd:
 
3337
                    stack_on_pwd = '.'
 
3338
            except errors.PathNotChild:
 
3339
                pass
 
3340
        args.append(self._serialize_NoneString(stack_on_pwd))
 
3341
        args.append(self._serialize_NoneString(repo_format_name))
 
3342
        args.append(self._serialize_NoneTrueFalse(make_working_trees))
 
3343
        args.append(self._serialize_NoneTrueFalse(shared_repo))
 
3344
        request_network_name = self._network_name or \
 
3345
            BzrDirFormat.get_default_format().network_name()
 
3346
        try:
 
3347
            response = client.call('BzrDirFormat.initialize_ex_1.16',
 
3348
                request_network_name, path, *args)
 
3349
        except errors.UnknownSmartMethod:
 
3350
            client._medium._remember_remote_is_before((1,16))
 
3351
            local_dir_format = BzrDirMetaFormat1()
 
3352
            self._supply_sub_formats_to(local_dir_format)
 
3353
            return local_dir_format.initialize_on_transport_ex(transport,
 
3354
                use_existing_dir=use_existing_dir, create_prefix=create_prefix,
 
3355
                force_new_repo=force_new_repo, stacked_on=stacked_on,
 
3356
                stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
 
3357
                make_working_trees=make_working_trees, shared_repo=shared_repo,
 
3358
                vfs_only=True)
 
3359
        except errors.ErrorFromSmartServer, err:
 
3360
            remote._translate_error(err, path=path)
 
3361
        repo_path = response[0]
 
3362
        bzrdir_name = response[6]
 
3363
        require_stacking = response[7]
 
3364
        require_stacking = self.parse_NoneTrueFalse(require_stacking)
 
3365
        format = RemoteBzrDirFormat()
 
3366
        format._network_name = bzrdir_name
 
3367
        self._supply_sub_formats_to(format)
 
3368
        bzrdir = remote.RemoteBzrDir(transport, format, _client=client)
 
3369
        if repo_path:
 
3370
            repo_format = remote.response_tuple_to_repo_format(response[1:])
 
3371
            if repo_path == '.':
 
3372
                repo_path = ''
 
3373
            if repo_path:
 
3374
                repo_bzrdir_format = RemoteBzrDirFormat()
 
3375
                repo_bzrdir_format._network_name = response[5]
 
3376
                repo_bzr = remote.RemoteBzrDir(transport.clone(repo_path),
 
3377
                    repo_bzrdir_format)
 
3378
            else:
 
3379
                repo_bzr = bzrdir
 
3380
            final_stack = response[8] or None
 
3381
            final_stack_pwd = response[9] or None
 
3382
            if final_stack_pwd:
 
3383
                final_stack_pwd = urlutils.join(
 
3384
                    transport.base, final_stack_pwd)
 
3385
            remote_repo = remote.RemoteRepository(repo_bzr, repo_format)
 
3386
            if len(response) > 10:
 
3387
                # Updated server verb that locks remotely.
 
3388
                repo_lock_token = response[10] or None
 
3389
                remote_repo.lock_write(repo_lock_token, _skip_rpc=True)
 
3390
                if repo_lock_token:
 
3391
                    remote_repo.dont_leave_lock_in_place()
 
3392
            else:
 
3393
                remote_repo.lock_write()
 
3394
            policy = UseExistingRepository(remote_repo, final_stack,
 
3395
                final_stack_pwd, require_stacking)
 
3396
            policy.acquire_repository()
 
3397
        else:
 
3398
            remote_repo = None
 
3399
            policy = None
 
3400
        bzrdir._format.set_branch_format(self.get_branch_format())
 
3401
        if require_stacking:
 
3402
            # The repo has already been created, but we need to make sure that
 
3403
            # we'll make a stackable branch.
 
3404
            bzrdir._format.require_stacking(_skip_repo=True)
 
3405
        return remote_repo, bzrdir, require_stacking, policy
 
3406
 
 
3407
    def _open(self, transport):
 
3408
        return remote.RemoteBzrDir(transport, self)
 
3409
 
 
3410
    def __eq__(self, other):
 
3411
        if not isinstance(other, RemoteBzrDirFormat):
 
3412
            return False
 
3413
        return self.get_format_description() == other.get_format_description()
 
3414
 
 
3415
    def __return_repository_format(self):
 
3416
        # Always return a RemoteRepositoryFormat object, but if a specific bzr
 
3417
        # repository format has been asked for, tell the RemoteRepositoryFormat
 
3418
        # that it should use that for init() etc.
 
3419
        result = remote.RemoteRepositoryFormat()
 
3420
        custom_format = getattr(self, '_repository_format', None)
 
3421
        if custom_format:
 
3422
            if isinstance(custom_format, remote.RemoteRepositoryFormat):
 
3423
                return custom_format
 
3424
            else:
 
3425
                # We will use the custom format to create repositories over the
 
3426
                # wire; expose its details like rich_root_data for code to
 
3427
                # query
 
3428
                result._custom_format = custom_format
 
3429
        return result
 
3430
 
 
3431
    def get_branch_format(self):
 
3432
        result = BzrDirMetaFormat1.get_branch_format(self)
 
3433
        if not isinstance(result, remote.RemoteBranchFormat):
 
3434
            new_result = remote.RemoteBranchFormat()
 
3435
            new_result._custom_format = result
 
3436
            # cache the result
 
3437
            self.set_branch_format(new_result)
 
3438
            result = new_result
 
3439
        return result
 
3440
 
 
3441
    repository_format = property(__return_repository_format,
 
3442
        BzrDirMetaFormat1._set_repository_format) #.im_func)
 
3443
 
 
3444
 
 
3445
BzrDirFormat.register_control_server_format(RemoteBzrDirFormat)
 
3446
 
 
3447
 
 
3448
class BzrDirFormatInfo(object):
 
3449
 
 
3450
    def __init__(self, native, deprecated, hidden, experimental):
 
3451
        self.deprecated = deprecated
 
3452
        self.native = native
 
3453
        self.hidden = hidden
 
3454
        self.experimental = experimental
 
3455
 
 
3456
 
 
3457
class BzrDirFormatRegistry(registry.Registry):
 
3458
    """Registry of user-selectable BzrDir subformats.
 
3459
 
 
3460
    Differs from BzrDirFormat._control_formats in that it provides sub-formats,
 
3461
    e.g. BzrDirMeta1 with weave repository.  Also, it's more user-oriented.
 
3462
    """
 
3463
 
 
3464
    def __init__(self):
 
3465
        """Create a BzrDirFormatRegistry."""
 
3466
        self._aliases = set()
 
3467
        self._registration_order = list()
 
3468
        super(BzrDirFormatRegistry, self).__init__()
 
3469
 
 
3470
    def aliases(self):
 
3471
        """Return a set of the format names which are aliases."""
 
3472
        return frozenset(self._aliases)
 
3473
 
 
3474
    def register_metadir(self, key,
 
3475
             repository_format, help, native=True, deprecated=False,
 
3476
             branch_format=None,
 
3477
             tree_format=None,
 
3478
             hidden=False,
 
3479
             experimental=False,
 
3480
             alias=False):
 
3481
        """Register a metadir subformat.
 
3482
 
 
3483
        These all use a BzrDirMetaFormat1 bzrdir, but can be parameterized
 
3484
        by the Repository/Branch/WorkingTreeformats.
 
3485
 
 
3486
        :param repository_format: The fully-qualified repository format class
 
3487
            name as a string.
 
3488
        :param branch_format: Fully-qualified branch format class name as
 
3489
            a string.
 
3490
        :param tree_format: Fully-qualified tree format class name as
 
3491
            a string.
 
3492
        """
 
3493
        # This should be expanded to support setting WorkingTree and Branch
 
3494
        # formats, once BzrDirMetaFormat1 supports that.
 
3495
        def _load(full_name):
 
3496
            mod_name, factory_name = full_name.rsplit('.', 1)
 
3497
            try:
 
3498
                mod = __import__(mod_name, globals(), locals(),
 
3499
                        [factory_name])
 
3500
            except ImportError, e:
 
3501
                raise ImportError('failed to load %s: %s' % (full_name, e))
 
3502
            try:
 
3503
                factory = getattr(mod, factory_name)
 
3504
            except AttributeError:
 
3505
                raise AttributeError('no factory %s in module %r'
 
3506
                    % (full_name, mod))
 
3507
            return factory()
 
3508
 
 
3509
        def helper():
 
3510
            bd = BzrDirMetaFormat1()
 
3511
            if branch_format is not None:
 
3512
                bd.set_branch_format(_load(branch_format))
 
3513
            if tree_format is not None:
 
3514
                bd.workingtree_format = _load(tree_format)
 
3515
            if repository_format is not None:
 
3516
                bd.repository_format = _load(repository_format)
 
3517
            return bd
 
3518
        self.register(key, helper, help, native, deprecated, hidden,
 
3519
            experimental, alias)
 
3520
 
 
3521
    def register(self, key, factory, help, native=True, deprecated=False,
 
3522
                 hidden=False, experimental=False, alias=False):
 
3523
        """Register a BzrDirFormat factory.
 
3524
 
 
3525
        The factory must be a callable that takes one parameter: the key.
 
3526
        It must produce an instance of the BzrDirFormat when called.
 
3527
 
 
3528
        This function mainly exists to prevent the info object from being
 
3529
        supplied directly.
 
3530
        """
 
3531
        registry.Registry.register(self, key, factory, help,
 
3532
            BzrDirFormatInfo(native, deprecated, hidden, experimental))
 
3533
        if alias:
 
3534
            self._aliases.add(key)
 
3535
        self._registration_order.append(key)
 
3536
 
 
3537
    def register_lazy(self, key, module_name, member_name, help, native=True,
 
3538
        deprecated=False, hidden=False, experimental=False, alias=False):
 
3539
        registry.Registry.register_lazy(self, key, module_name, member_name,
 
3540
            help, BzrDirFormatInfo(native, deprecated, hidden, experimental))
 
3541
        if alias:
 
3542
            self._aliases.add(key)
 
3543
        self._registration_order.append(key)
 
3544
 
 
3545
    def set_default(self, key):
 
3546
        """Set the 'default' key to be a clone of the supplied key.
 
3547
 
 
3548
        This method must be called once and only once.
 
3549
        """
 
3550
        registry.Registry.register(self, 'default', self.get(key),
 
3551
            self.get_help(key), info=self.get_info(key))
 
3552
        self._aliases.add('default')
 
3553
 
 
3554
    def set_default_repository(self, key):
 
3555
        """Set the FormatRegistry default and Repository default.
 
3556
 
 
3557
        This is a transitional method while Repository.set_default_format
 
3558
        is deprecated.
 
3559
        """
 
3560
        if 'default' in self:
 
3561
            self.remove('default')
 
3562
        self.set_default(key)
 
3563
        format = self.get('default')()
 
3564
 
 
3565
    def make_bzrdir(self, key):
 
3566
        return self.get(key)()
 
3567
 
 
3568
    def help_topic(self, topic):
 
3569
        output = ""
 
3570
        default_realkey = None
 
3571
        default_help = self.get_help('default')
 
3572
        help_pairs = []
 
3573
        for key in self._registration_order:
 
3574
            if key == 'default':
 
3575
                continue
 
3576
            help = self.get_help(key)
 
3577
            if help == default_help:
 
3578
                default_realkey = key
 
3579
            else:
 
3580
                help_pairs.append((key, help))
 
3581
 
 
3582
        def wrapped(key, help, info):
 
3583
            if info.native:
 
3584
                help = '(native) ' + help
 
3585
            return ':%s:\n%s\n\n' % (key,
 
3586
                textwrap.fill(help, initial_indent='    ',
 
3587
                    subsequent_indent='    ',
 
3588
                    break_long_words=False))
 
3589
        if default_realkey is not None:
 
3590
            output += wrapped(default_realkey, '(default) %s' % default_help,
 
3591
                              self.get_info('default'))
 
3592
        deprecated_pairs = []
 
3593
        experimental_pairs = []
 
3594
        for key, help in help_pairs:
 
3595
            info = self.get_info(key)
 
3596
            if info.hidden:
 
3597
                continue
 
3598
            elif info.deprecated:
 
3599
                deprecated_pairs.append((key, help))
 
3600
            elif info.experimental:
 
3601
                experimental_pairs.append((key, help))
 
3602
            else:
 
3603
                output += wrapped(key, help, info)
 
3604
        output += "\nSee :doc:`formats-help` for more about storage formats."
 
3605
        other_output = ""
 
3606
        if len(experimental_pairs) > 0:
 
3607
            other_output += "Experimental formats are shown below.\n\n"
 
3608
            for key, help in experimental_pairs:
 
3609
                info = self.get_info(key)
 
3610
                other_output += wrapped(key, help, info)
 
3611
        else:
 
3612
            other_output += \
 
3613
                "No experimental formats are available.\n\n"
 
3614
        if len(deprecated_pairs) > 0:
 
3615
            other_output += "\nDeprecated formats are shown below.\n\n"
 
3616
            for key, help in deprecated_pairs:
 
3617
                info = self.get_info(key)
 
3618
                other_output += wrapped(key, help, info)
 
3619
        else:
 
3620
            other_output += \
 
3621
                "\nNo deprecated formats are available.\n\n"
 
3622
        other_output += \
 
3623
                "\nSee :doc:`formats-help` for more about storage formats."
 
3624
 
 
3625
        if topic == 'other-formats':
 
3626
            return other_output
 
3627
        else:
 
3628
            return output
 
3629
 
 
3630
 
 
3631
class RepositoryAcquisitionPolicy(object):
 
3632
    """Abstract base class for repository acquisition policies.
 
3633
 
 
3634
    A repository acquisition policy decides how a BzrDir acquires a repository
 
3635
    for a branch that is being created.  The most basic policy decision is
 
3636
    whether to create a new repository or use an existing one.
 
3637
    """
 
3638
    def __init__(self, stack_on, stack_on_pwd, require_stacking):
 
3639
        """Constructor.
 
3640
 
 
3641
        :param stack_on: A location to stack on
 
3642
        :param stack_on_pwd: If stack_on is relative, the location it is
 
3643
            relative to.
 
3644
        :param require_stacking: If True, it is a failure to not stack.
 
3645
        """
 
3646
        self._stack_on = stack_on
 
3647
        self._stack_on_pwd = stack_on_pwd
 
3648
        self._require_stacking = require_stacking
 
3649
 
 
3650
    def configure_branch(self, branch):
 
3651
        """Apply any configuration data from this policy to the branch.
 
3652
 
 
3653
        Default implementation sets repository stacking.
 
3654
        """
 
3655
        if self._stack_on is None:
 
3656
            return
 
3657
        if self._stack_on_pwd is None:
 
3658
            stack_on = self._stack_on
 
3659
        else:
 
3660
            try:
 
3661
                stack_on = urlutils.rebase_url(self._stack_on,
 
3662
                    self._stack_on_pwd,
 
3663
                    branch.bzrdir.root_transport.base)
 
3664
            except errors.InvalidRebaseURLs:
 
3665
                stack_on = self._get_full_stack_on()
 
3666
        try:
 
3667
            branch.set_stacked_on_url(stack_on)
 
3668
        except (errors.UnstackableBranchFormat,
 
3669
                errors.UnstackableRepositoryFormat):
 
3670
            if self._require_stacking:
 
3671
                raise
 
3672
 
 
3673
    def requires_stacking(self):
 
3674
        """Return True if this policy requires stacking."""
 
3675
        return self._stack_on is not None and self._require_stacking
 
3676
 
 
3677
    def _get_full_stack_on(self):
 
3678
        """Get a fully-qualified URL for the stack_on location."""
 
3679
        if self._stack_on is None:
 
3680
            return None
 
3681
        if self._stack_on_pwd is None:
 
3682
            return self._stack_on
 
3683
        else:
 
3684
            return urlutils.join(self._stack_on_pwd, self._stack_on)
 
3685
 
 
3686
    def _add_fallback(self, repository, possible_transports=None):
 
3687
        """Add a fallback to the supplied repository, if stacking is set."""
 
3688
        stack_on = self._get_full_stack_on()
 
3689
        if stack_on is None:
 
3690
            return
 
3691
        try:
 
3692
            stacked_dir = BzrDir.open(stack_on,
 
3693
                                      possible_transports=possible_transports)
 
3694
        except errors.JailBreak:
 
3695
            # We keep the stacking details, but we are in the server code so
 
3696
            # actually stacking is not needed.
 
3697
            return
 
3698
        try:
 
3699
            stacked_repo = stacked_dir.open_branch().repository
 
3700
        except errors.NotBranchError:
 
3701
            stacked_repo = stacked_dir.open_repository()
 
3702
        try:
 
3703
            repository.add_fallback_repository(stacked_repo)
 
3704
        except errors.UnstackableRepositoryFormat:
 
3705
            if self._require_stacking:
 
3706
                raise
 
3707
        else:
 
3708
            self._require_stacking = True
 
3709
 
 
3710
    def acquire_repository(self, make_working_trees=None, shared=False):
 
3711
        """Acquire a repository for this bzrdir.
 
3712
 
 
3713
        Implementations may create a new repository or use a pre-exising
 
3714
        repository.
 
3715
        :param make_working_trees: If creating a repository, set
 
3716
            make_working_trees to this value (if non-None)
 
3717
        :param shared: If creating a repository, make it shared if True
 
3718
        :return: A repository, is_new_flag (True if the repository was
 
3719
            created).
 
3720
        """
 
3721
        raise NotImplemented(RepositoryAcquisitionPolicy.acquire_repository)
 
3722
 
 
3723
 
 
3724
class CreateRepository(RepositoryAcquisitionPolicy):
 
3725
    """A policy of creating a new repository"""
 
3726
 
 
3727
    def __init__(self, bzrdir, stack_on=None, stack_on_pwd=None,
 
3728
                 require_stacking=False):
 
3729
        """
 
3730
        Constructor.
 
3731
        :param bzrdir: The bzrdir to create the repository on.
 
3732
        :param stack_on: A location to stack on
 
3733
        :param stack_on_pwd: If stack_on is relative, the location it is
 
3734
            relative to.
 
3735
        """
 
3736
        RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
 
3737
                                             require_stacking)
 
3738
        self._bzrdir = bzrdir
 
3739
 
 
3740
    def acquire_repository(self, make_working_trees=None, shared=False):
 
3741
        """Implementation of RepositoryAcquisitionPolicy.acquire_repository
 
3742
 
 
3743
        Creates the desired repository in the bzrdir we already have.
 
3744
        """
 
3745
        stack_on = self._get_full_stack_on()
 
3746
        if stack_on:
 
3747
            format = self._bzrdir._format
 
3748
            format.require_stacking(stack_on=stack_on,
 
3749
                                    possible_transports=[self._bzrdir.root_transport])
 
3750
            if not self._require_stacking:
 
3751
                # We have picked up automatic stacking somewhere.
 
3752
                note('Using default stacking branch %s at %s', self._stack_on,
 
3753
                    self._stack_on_pwd)
 
3754
        repository = self._bzrdir.create_repository(shared=shared)
 
3755
        self._add_fallback(repository,
 
3756
                           possible_transports=[self._bzrdir.transport])
 
3757
        if make_working_trees is not None:
 
3758
            repository.set_make_working_trees(make_working_trees)
 
3759
        return repository, True
 
3760
 
 
3761
 
 
3762
class UseExistingRepository(RepositoryAcquisitionPolicy):
 
3763
    """A policy of reusing an existing repository"""
 
3764
 
 
3765
    def __init__(self, repository, stack_on=None, stack_on_pwd=None,
 
3766
                 require_stacking=False):
 
3767
        """Constructor.
 
3768
 
 
3769
        :param repository: The repository to use.
 
3770
        :param stack_on: A location to stack on
 
3771
        :param stack_on_pwd: If stack_on is relative, the location it is
 
3772
            relative to.
 
3773
        """
 
3774
        RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
 
3775
                                             require_stacking)
 
3776
        self._repository = repository
 
3777
 
 
3778
    def acquire_repository(self, make_working_trees=None, shared=False):
 
3779
        """Implementation of RepositoryAcquisitionPolicy.acquire_repository
 
3780
 
 
3781
        Returns an existing repository to use.
 
3782
        """
 
3783
        self._add_fallback(self._repository,
 
3784
                       possible_transports=[self._repository.bzrdir.transport])
 
3785
        return self._repository, False
 
3786
 
 
3787
 
 
3788
# Please register new formats after old formats so that formats
 
3789
# appear in chronological order and format descriptions can build
 
3790
# on previous ones.
 
3791
format_registry = BzrDirFormatRegistry()
 
3792
# The pre-0.8 formats have their repository format network name registered in
 
3793
# repository.py. MetaDir formats have their repository format network name
 
3794
# inferred from their disk format string.
 
3795
format_registry.register('weave', BzrDirFormat6,
 
3796
    'Pre-0.8 format.  Slower than knit and does not'
 
3797
    ' support checkouts or shared repositories.',
 
3798
    hidden=True,
 
3799
    deprecated=True)
 
3800
format_registry.register_metadir('metaweave',
 
3801
    'bzrlib.repofmt.weaverepo.RepositoryFormat7',
 
3802
    'Transitional format in 0.8.  Slower than knit.',
 
3803
    branch_format='bzrlib.branch.BzrBranchFormat5',
 
3804
    tree_format='bzrlib.workingtree.WorkingTreeFormat3',
 
3805
    hidden=True,
 
3806
    deprecated=True)
 
3807
format_registry.register_metadir('knit',
 
3808
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
 
3809
    'Format using knits.  Recommended for interoperation with bzr <= 0.14.',
 
3810
    branch_format='bzrlib.branch.BzrBranchFormat5',
 
3811
    tree_format='bzrlib.workingtree.WorkingTreeFormat3',
 
3812
    hidden=True,
 
3813
    deprecated=True)
 
3814
format_registry.register_metadir('dirstate',
 
3815
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
 
3816
    help='New in 0.15: Fast local operations. Compatible with bzr 0.8 and '
 
3817
        'above when accessed over the network.',
 
3818
    branch_format='bzrlib.branch.BzrBranchFormat5',
 
3819
    # this uses bzrlib.workingtree.WorkingTreeFormat4 because importing
 
3820
    # directly from workingtree_4 triggers a circular import.
 
3821
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
 
3822
    hidden=True,
 
3823
    deprecated=True)
 
3824
format_registry.register_metadir('dirstate-tags',
 
3825
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
 
3826
    help='New in 0.15: Fast local operations and improved scaling for '
 
3827
        'network operations. Additionally adds support for tags.'
 
3828
        ' Incompatible with bzr < 0.15.',
 
3829
    branch_format='bzrlib.branch.BzrBranchFormat6',
 
3830
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
 
3831
    hidden=True,
 
3832
    deprecated=True)
 
3833
format_registry.register_metadir('rich-root',
 
3834
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit4',
 
3835
    help='New in 1.0.  Better handling of tree roots.  Incompatible with'
 
3836
        ' bzr < 1.0.',
 
3837
    branch_format='bzrlib.branch.BzrBranchFormat6',
 
3838
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
 
3839
    hidden=True,
 
3840
    deprecated=True)
 
3841
format_registry.register_metadir('dirstate-with-subtree',
 
3842
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
 
3843
    help='New in 0.15: Fast local operations and improved scaling for '
 
3844
        'network operations. Additionally adds support for versioning nested '
 
3845
        'bzr branches. Incompatible with bzr < 0.15.',
 
3846
    branch_format='bzrlib.branch.BzrBranchFormat6',
 
3847
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
 
3848
    experimental=True,
 
3849
    hidden=True,
 
3850
    )
 
3851
format_registry.register_metadir('pack-0.92',
 
3852
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack1',
 
3853
    help='New in 0.92: Pack-based format with data compatible with '
 
3854
        'dirstate-tags format repositories. Interoperates with '
 
3855
        'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
 
3856
        ,
 
3857
    branch_format='bzrlib.branch.BzrBranchFormat6',
 
3858
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
 
3859
    )
 
3860
format_registry.register_metadir('pack-0.92-subtree',
 
3861
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack3',
 
3862
    help='New in 0.92: Pack-based format with data compatible with '
 
3863
        'dirstate-with-subtree format repositories. Interoperates with '
 
3864
        'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
 
3865
        ,
 
3866
    branch_format='bzrlib.branch.BzrBranchFormat6',
 
3867
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
 
3868
    hidden=True,
 
3869
    experimental=True,
 
3870
    )
 
3871
format_registry.register_metadir('rich-root-pack',
 
3872
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack4',
 
3873
    help='New in 1.0: A variant of pack-0.92 that supports rich-root data '
 
3874
         '(needed for bzr-svn and bzr-git).',
 
3875
    branch_format='bzrlib.branch.BzrBranchFormat6',
 
3876
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
 
3877
    hidden=True,
 
3878
    )
 
3879
format_registry.register_metadir('1.6',
 
3880
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack5',
 
3881
    help='A format that allows a branch to indicate that there is another '
 
3882
         '(stacked) repository that should be used to access data that is '
 
3883
         'not present locally.',
 
3884
    branch_format='bzrlib.branch.BzrBranchFormat7',
 
3885
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
 
3886
    hidden=True,
 
3887
    )
 
3888
format_registry.register_metadir('1.6.1-rich-root',
 
3889
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack5RichRoot',
 
3890
    help='A variant of 1.6 that supports rich-root data '
 
3891
         '(needed for bzr-svn and bzr-git).',
 
3892
    branch_format='bzrlib.branch.BzrBranchFormat7',
 
3893
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
 
3894
    hidden=True,
 
3895
    )
 
3896
format_registry.register_metadir('1.9',
 
3897
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6',
 
3898
    help='A repository format using B+tree indexes. These indexes '
 
3899
         'are smaller in size, have smarter caching and provide faster '
 
3900
         'performance for most operations.',
 
3901
    branch_format='bzrlib.branch.BzrBranchFormat7',
 
3902
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
 
3903
    hidden=True,
 
3904
    )
 
3905
format_registry.register_metadir('1.9-rich-root',
 
3906
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6RichRoot',
 
3907
    help='A variant of 1.9 that supports rich-root data '
 
3908
         '(needed for bzr-svn and bzr-git).',
 
3909
    branch_format='bzrlib.branch.BzrBranchFormat7',
 
3910
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
 
3911
    hidden=True,
 
3912
    )
 
3913
format_registry.register_metadir('1.14',
 
3914
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6',
 
3915
    help='A working-tree format that supports content filtering.',
 
3916
    branch_format='bzrlib.branch.BzrBranchFormat7',
 
3917
    tree_format='bzrlib.workingtree.WorkingTreeFormat5',
 
3918
    )
 
3919
format_registry.register_metadir('1.14-rich-root',
 
3920
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6RichRoot',
 
3921
    help='A variant of 1.14 that supports rich-root data '
 
3922
         '(needed for bzr-svn and bzr-git).',
 
3923
    branch_format='bzrlib.branch.BzrBranchFormat7',
 
3924
    tree_format='bzrlib.workingtree.WorkingTreeFormat5',
 
3925
    )
 
3926
# The following un-numbered 'development' formats should always just be aliases.
 
3927
format_registry.register_metadir('development-rich-root',
 
3928
    'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK1',
 
3929
    help='Current development format. Supports rich roots. Can convert data '
 
3930
        'to and from rich-root-pack (and anything compatible with '
 
3931
        'rich-root-pack) format repositories. Repositories and branches in '
 
3932
        'this format can only be read by bzr.dev. Please read '
 
3933
        'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
 
3934
        'before use.',
 
3935
    branch_format='bzrlib.branch.BzrBranchFormat7',
 
3936
    tree_format='bzrlib.workingtree.WorkingTreeFormat6',
 
3937
    experimental=True,
 
3938
    alias=True,
 
3939
    hidden=True,
 
3940
    )
 
3941
format_registry.register_metadir('development-subtree',
 
3942
    'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2Subtree',
 
3943
    help='Current development format, subtree variant. Can convert data to and '
 
3944
        'from pack-0.92-subtree (and anything compatible with '
 
3945
        'pack-0.92-subtree) format repositories. Repositories and branches in '
 
3946
        'this format can only be read by bzr.dev. Please read '
 
3947
        'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
 
3948
        'before use.',
 
3949
    branch_format='bzrlib.branch.BzrBranchFormat7',
 
3950
    tree_format='bzrlib.workingtree.WorkingTreeFormat6',
 
3951
    experimental=True,
 
3952
    hidden=True,
 
3953
    alias=False, # Restore to being an alias when an actual development subtree format is added
 
3954
                 # This current non-alias status is simply because we did not introduce a
 
3955
                 # chk based subtree format.
 
3956
    )
 
3957
 
 
3958
# And the development formats above will have aliased one of the following:
 
3959
format_registry.register_metadir('development6-rich-root',
 
3960
    'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK1',
 
3961
    help='pack-1.9 with 255-way hashed CHK inv, group compress, rich roots '
 
3962
        'Please read '
 
3963
        'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
 
3964
        'before use.',
 
3965
    branch_format='bzrlib.branch.BzrBranchFormat7',
 
3966
    tree_format='bzrlib.workingtree.WorkingTreeFormat6',
 
3967
    hidden=True,
 
3968
    experimental=True,
 
3969
    )
 
3970
 
 
3971
format_registry.register_metadir('development7-rich-root',
 
3972
    'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK2',
 
3973
    help='pack-1.9 with 255-way hashed CHK inv, bencode revision, group compress, '
 
3974
        'rich roots. Please read '
 
3975
        'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
 
3976
        'before use.',
 
3977
    branch_format='bzrlib.branch.BzrBranchFormat7',
 
3978
    tree_format='bzrlib.workingtree.WorkingTreeFormat6',
 
3979
    hidden=True,
 
3980
    experimental=True,
 
3981
    )
 
3982
 
 
3983
format_registry.register_metadir('2a',
 
3984
    'bzrlib.repofmt.groupcompress_repo.RepositoryFormat2a',
 
3985
    help='First format for bzr 2.0 series.\n'
 
3986
        'Uses group-compress storage.\n'
 
3987
        'Provides rich roots which are a one-way transition.\n',
 
3988
        # 'storage in packs, 255-way hashed CHK inventory, bencode revision, group compress, '
 
3989
        # 'rich roots. Supported by bzr 1.16 and later.',
 
3990
    branch_format='bzrlib.branch.BzrBranchFormat7',
 
3991
    tree_format='bzrlib.workingtree.WorkingTreeFormat6',
 
3992
    experimental=True,
 
3993
    )
 
3994
 
 
3995
# The following format should be an alias for the rich root equivalent 
 
3996
# of the default format
 
3997
format_registry.register_metadir('default-rich-root',
 
3998
    'bzrlib.repofmt.groupcompress_repo.RepositoryFormat2a',
 
3999
    branch_format='bzrlib.branch.BzrBranchFormat7',
 
4000
    tree_format='bzrlib.workingtree.WorkingTreeFormat6',
 
4001
    alias=True,
 
4002
    hidden=True,
 
4003
    help='Same as 2a.')
 
4004
 
 
4005
# The current format that is made on 'bzr init'.
 
4006
format_registry.set_default('2a')