/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 brzlib/bzrdir.py

  • Committer: Jelmer Vernooij
  • Date: 2017-05-21 12:41:27 UTC
  • mto: This revision was merged to the branch mainline in revision 6623.
  • Revision ID: jelmer@jelmer.uk-20170521124127-iv8etg0vwymyai6y
s/bzr/brz/ in apport config.

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
objects returned.
26
26
"""
27
27
 
 
28
from __future__ import absolute_import
 
29
 
28
30
import sys
29
31
 
30
 
from ..lazy_import import lazy_import
 
32
from brzlib.lazy_import import lazy_import
31
33
lazy_import(globals(), """
32
 
import contextlib
33
 
 
34
 
from breezy import (
 
34
import brzlib
 
35
from brzlib import (
35
36
    branch as _mod_branch,
 
37
    cleanup,
 
38
    errors,
 
39
    fetch,
 
40
    graph,
36
41
    lockable_files,
37
42
    lockdir,
38
43
    osutils,
 
44
    pyutils,
 
45
    remote,
39
46
    repository,
40
47
    revision as _mod_revision,
41
48
    transport as _mod_transport,
42
49
    ui,
43
50
    urlutils,
 
51
    vf_search,
44
52
    win32utils,
45
 
    )
46
 
from breezy.bzr import (
47
 
    branch as _mod_bzrbranch,
48
 
    fetch,
49
 
    remote,
50
 
    vf_search,
51
53
    workingtree_3,
52
54
    workingtree_4,
53
55
    )
54
 
from breezy.bzr import fullhistory as fullhistorybranch
55
 
from breezy.bzr import knitpack_repo
56
 
from breezy.transport import (
 
56
from brzlib.branchfmt import fullhistory as fullhistorybranch
 
57
from brzlib.repofmt import knitpack_repo
 
58
from brzlib.transport import (
57
59
    do_catching_redirections,
58
60
    local,
59
61
    )
60
 
from breezy.i18n import gettext
 
62
from brzlib.i18n import gettext
61
63
""")
62
64
 
63
 
from ..trace import (
 
65
from brzlib.trace import (
64
66
    mutter,
65
67
    note,
66
 
    warning,
67
68
    )
68
69
 
69
 
from .. import (
 
70
from brzlib import (
70
71
    config,
71
72
    controldir,
72
 
    errors,
73
 
    )
74
 
 
75
 
 
76
 
class MissingFeature(errors.BzrError):
77
 
 
78
 
    _fmt = ("Missing feature %(feature)s not provided by this "
79
 
            "version of Bazaar or any plugin.")
80
 
 
81
 
    def __init__(self, feature):
82
 
        self.feature = feature
83
 
 
84
 
 
85
 
class FeatureAlreadyRegistered(errors.BzrError):
86
 
 
87
 
    _fmt = 'The feature %(feature)s has already been registered.'
88
 
 
89
 
    def __init__(self, feature):
90
 
        self.feature = feature
 
73
    registry,
 
74
    )
 
75
from brzlib.symbol_versioning import (
 
76
    deprecated_in,
 
77
    deprecated_method,
 
78
    )
91
79
 
92
80
 
93
81
class BzrDir(controldir.ControlDir):
129
117
 
130
118
    def check_conversion_target(self, target_format):
131
119
        """Check that a bzrdir as a whole can be converted to a new format."""
132
 
        # The only current restriction is that the repository content can be
 
120
        # The only current restriction is that the repository content can be 
133
121
        # fetched compatibly with the target.
134
122
        target_repo_format = target_format.repository_format
135
123
        try:
140
128
            pass
141
129
 
142
130
    def clone_on_transport(self, transport, revision_id=None,
143
 
                           force_new_repo=False, preserve_stacking=False, stacked_on=None,
144
 
                           create_prefix=False, use_existing_dir=True, no_tree=False):
 
131
        force_new_repo=False, preserve_stacking=False, stacked_on=None,
 
132
        create_prefix=False, use_existing_dir=True, no_tree=False):
145
133
        """Clone this bzrdir and its contents to transport verbatim.
146
134
 
147
135
        :param transport: The transport for the location to produce the clone
182
170
            if preserve_stacking:
183
171
                try:
184
172
                    stacked_on = local_branch.get_stacked_on_url()
185
 
                except (_mod_branch.UnstackableBranchFormat,
 
173
                except (errors.UnstackableBranchFormat,
186
174
                        errors.UnstackableRepositoryFormat,
187
175
                        errors.NotStacked):
188
176
                    pass
190
178
        # we should look up the policy needs first, or just use it as a hint,
191
179
        # or something.
192
180
        if local_repo:
193
 
            make_working_trees = (local_repo.make_working_trees() and
194
 
                                  not no_tree)
 
181
            make_working_trees = local_repo.make_working_trees() and not no_tree
195
182
            want_shared = local_repo.is_shared()
196
183
            repo_format_name = format.repository_format.network_name()
197
184
        else:
200
187
            repo_format_name = None
201
188
 
202
189
        result_repo, result, require_stacking, repository_policy = \
203
 
            format.initialize_on_transport_ex(
204
 
                transport, use_existing_dir=use_existing_dir,
205
 
                create_prefix=create_prefix, force_new_repo=force_new_repo,
206
 
                stacked_on=stacked_on, stack_on_pwd=self.root_transport.base,
207
 
                repo_format_name=repo_format_name,
208
 
                make_working_trees=make_working_trees, shared_repo=want_shared)
 
190
            format.initialize_on_transport_ex(transport,
 
191
            use_existing_dir=use_existing_dir, create_prefix=create_prefix,
 
192
            force_new_repo=force_new_repo, stacked_on=stacked_on,
 
193
            stack_on_pwd=self.root_transport.base,
 
194
            repo_format_name=repo_format_name,
 
195
            make_working_trees=make_working_trees, shared_repo=want_shared)
209
196
        if repo_format_name:
210
197
            try:
211
198
                # If the result repository is in the same place as the
215
202
                # revision_id then we can use the pending-ancestry-result which
216
203
                # does not require traversing all of history to describe it.
217
204
                if (result_repo.user_url == result.user_url
218
 
                    and not require_stacking
219
 
                        and revision_id is not None):
 
205
                    and not require_stacking and
 
206
                    revision_id is not None):
220
207
                    fetch_spec = vf_search.PendingAncestryResult(
221
208
                        [revision_id], local_repo)
222
209
                    result_repo.fetch(local_repo, fetch_spec=fetch_spec)
231
218
        #   make sure its content is available in the target repository
232
219
        #   clone it.
233
220
        if local_branch is not None:
234
 
            local_branch.clone(
235
 
                result, revision_id=revision_id,
 
221
            result_branch = local_branch.clone(result, revision_id=revision_id,
236
222
                repository_policy=repository_policy)
237
223
        try:
238
224
            # Cheaper to check if the target is not local, than to try making
280
266
            except errors.NoRepositoryPresent:
281
267
                repository = None
282
268
            else:
283
 
                if (found_bzrdir.user_url != self.user_url and
284
 
                        not repository.is_shared()):
 
269
                if (found_bzrdir.user_url != self.user_url 
 
270
                    and not repository.is_shared()):
285
271
                    # Don't look higher, can't use a higher shared repo.
286
272
                    repository = None
287
273
                    stop = True
290
276
            if not stop:
291
277
                return None, False
292
278
            if repository:
293
 
                return UseExistingRepository(
294
 
                    repository, stack_on, stack_on_pwd,
295
 
                    require_stacking=require_stacking), True
 
279
                return UseExistingRepository(repository, stack_on,
 
280
                    stack_on_pwd, require_stacking=require_stacking), True
296
281
            else:
297
 
                return CreateRepository(
298
 
                    self, stack_on, stack_on_pwd,
 
282
                return CreateRepository(self, stack_on, stack_on_pwd,
299
283
                    require_stacking=require_stacking), True
300
284
 
301
285
        if not force_new_repo:
305
289
                    return policy
306
290
            else:
307
291
                try:
308
 
                    return UseExistingRepository(
309
 
                        self.open_repository(), stack_on, stack_on_pwd,
 
292
                    return UseExistingRepository(self.open_repository(),
 
293
                        stack_on, stack_on_pwd,
310
294
                        require_stacking=require_stacking)
311
295
                except errors.NoRepositoryPresent:
312
296
                    pass
318
302
        policy = self.determine_repository_policy(force_new_repo)
319
303
        return policy.acquire_repository()[0]
320
304
 
321
 
    def _find_source_repo(self, exit_stack, source_branch):
 
305
    def _find_source_repo(self, add_cleanup, source_branch):
322
306
        """Find the source branch and repo for a sprout operation.
323
 
 
 
307
        
324
308
        This is helper intended for use by _sprout.
325
309
 
326
310
        :returns: (source_branch, source_repository).  Either or both may be
327
311
            None.  If not None, they will be read-locked (and their unlock(s)
328
 
            scheduled via the exit_stack param).
 
312
            scheduled via the add_cleanup param).
329
313
        """
330
314
        if source_branch is not None:
331
 
            exit_stack.enter_context(source_branch.lock_read())
 
315
            add_cleanup(source_branch.lock_read().unlock)
332
316
            return source_branch, source_branch.repository
333
317
        try:
334
318
            source_branch = self.open_branch()
340
324
            except errors.NoRepositoryPresent:
341
325
                source_repository = None
342
326
            else:
343
 
                exit_stack.enter_context(source_repository.lock_read())
 
327
                add_cleanup(source_repository.lock_read().unlock)
344
328
        else:
345
 
            exit_stack.enter_context(source_branch.lock_read())
 
329
            add_cleanup(source_branch.lock_read().unlock)
346
330
        return source_branch, source_repository
347
331
 
348
332
    def sprout(self, url, revision_id=None, force_new_repo=False,
349
333
               recurse='down', possible_transports=None,
350
334
               accelerator_tree=None, hardlink=False, stacked=False,
351
 
               source_branch=None, create_tree_if_local=True,
352
 
               lossy=False):
 
335
               source_branch=None, create_tree_if_local=True):
353
336
        """Create a copy of this controldir prepared for use as a new line of
354
337
        development.
355
338
 
375
358
            when working locally.
376
359
        :return: The created control directory
377
360
        """
378
 
        with contextlib.ExitStack() as stack:
379
 
            fetch_spec_factory = fetch.FetchSpecFactory()
380
 
            if revision_id is not None:
381
 
                fetch_spec_factory.add_revision_ids([revision_id])
382
 
                fetch_spec_factory.source_branch_stop_revision_id = revision_id
383
 
            if possible_transports is None:
384
 
                possible_transports = []
385
 
            else:
386
 
                possible_transports = list(possible_transports) + [
387
 
                    self.root_transport]
388
 
            target_transport = _mod_transport.get_transport(url,
389
 
                                                            possible_transports)
390
 
            target_transport.ensure_base()
391
 
            cloning_format = self.cloning_metadir(stacked)
392
 
            # Create/update the result branch
 
361
        operation = cleanup.OperationWithCleanups(self._sprout)
 
362
        return operation.run(url, revision_id=revision_id,
 
363
            force_new_repo=force_new_repo, recurse=recurse,
 
364
            possible_transports=possible_transports,
 
365
            accelerator_tree=accelerator_tree, hardlink=hardlink,
 
366
            stacked=stacked, source_branch=source_branch,
 
367
            create_tree_if_local=create_tree_if_local)
 
368
 
 
369
    def _sprout(self, op, url, revision_id=None, force_new_repo=False,
 
370
               recurse='down', possible_transports=None,
 
371
               accelerator_tree=None, hardlink=False, stacked=False,
 
372
               source_branch=None, create_tree_if_local=True):
 
373
        add_cleanup = op.add_cleanup
 
374
        fetch_spec_factory = fetch.FetchSpecFactory()
 
375
        if revision_id is not None:
 
376
            fetch_spec_factory.add_revision_ids([revision_id])
 
377
            fetch_spec_factory.source_branch_stop_revision_id = revision_id
 
378
        if possible_transports is None:
 
379
            possible_transports = []
 
380
        else:
 
381
            possible_transports = list(possible_transports) + [
 
382
                self.root_transport]
 
383
        target_transport = _mod_transport.get_transport(url,
 
384
            possible_transports)
 
385
        target_transport.ensure_base()
 
386
        cloning_format = self.cloning_metadir(stacked)
 
387
        # Create/update the result branch
 
388
        try:
 
389
            result = controldir.ControlDir.open_from_transport(target_transport)
 
390
        except errors.NotBranchError:
 
391
            result = cloning_format.initialize_on_transport(target_transport)
 
392
        source_branch, source_repository = self._find_source_repo(
 
393
            add_cleanup, source_branch)
 
394
        fetch_spec_factory.source_branch = source_branch
 
395
        # if a stacked branch wasn't requested, we don't create one
 
396
        # even if the origin was stacked
 
397
        if stacked and source_branch is not None:
 
398
            stacked_branch_url = self.root_transport.base
 
399
        else:
 
400
            stacked_branch_url = None
 
401
        repository_policy = result.determine_repository_policy(
 
402
            force_new_repo, stacked_branch_url, require_stacking=stacked)
 
403
        result_repo, is_new_repo = repository_policy.acquire_repository(
 
404
            possible_transports=possible_transports)
 
405
        add_cleanup(result_repo.lock_write().unlock)
 
406
        fetch_spec_factory.source_repo = source_repository
 
407
        fetch_spec_factory.target_repo = result_repo
 
408
        if stacked or (len(result_repo._fallback_repositories) != 0):
 
409
            target_repo_kind = fetch.TargetRepoKinds.STACKED
 
410
        elif is_new_repo:
 
411
            target_repo_kind = fetch.TargetRepoKinds.EMPTY
 
412
        else:
 
413
            target_repo_kind = fetch.TargetRepoKinds.PREEXISTING
 
414
        fetch_spec_factory.target_repo_kind = target_repo_kind
 
415
        if source_repository is not None:
 
416
            fetch_spec = fetch_spec_factory.make_fetch_spec()
 
417
            result_repo.fetch(source_repository, fetch_spec=fetch_spec)
 
418
 
 
419
        if source_branch is None:
 
420
            # this is for sprouting a controldir without a branch; is that
 
421
            # actually useful?
 
422
            # Not especially, but it's part of the contract.
 
423
            result_branch = result.create_branch()
 
424
        else:
 
425
            result_branch = source_branch.sprout(result,
 
426
                revision_id=revision_id, repository_policy=repository_policy,
 
427
                repository=result_repo)
 
428
        mutter("created new branch %r" % (result_branch,))
 
429
 
 
430
        # Create/update the result working tree
 
431
        if (create_tree_if_local and not result.has_workingtree() and
 
432
            isinstance(target_transport, local.LocalTransport) and
 
433
            (result_repo is None or result_repo.make_working_trees())):
 
434
            wt = result.create_workingtree(accelerator_tree=accelerator_tree,
 
435
                hardlink=hardlink, from_branch=result_branch)
 
436
            wt.lock_write()
393
437
            try:
394
 
                result = controldir.ControlDir.open_from_transport(
395
 
                    target_transport)
396
 
            except errors.NotBranchError:
397
 
                result = cloning_format.initialize_on_transport(target_transport)
398
 
            source_branch, source_repository = self._find_source_repo(
399
 
                stack, source_branch)
400
 
            fetch_spec_factory.source_branch = source_branch
401
 
            # if a stacked branch wasn't requested, we don't create one
402
 
            # even if the origin was stacked
403
 
            if stacked and source_branch is not None:
404
 
                stacked_branch_url = self.root_transport.base
405
 
            else:
406
 
                stacked_branch_url = None
407
 
            repository_policy = result.determine_repository_policy(
408
 
                force_new_repo, stacked_branch_url, require_stacking=stacked)
409
 
            result_repo, is_new_repo = repository_policy.acquire_repository(
410
 
                possible_transports=possible_transports)
411
 
            stack.enter_context(result_repo.lock_write())
412
 
            fetch_spec_factory.source_repo = source_repository
413
 
            fetch_spec_factory.target_repo = result_repo
414
 
            if stacked or (len(result_repo._fallback_repositories) != 0):
415
 
                target_repo_kind = fetch.TargetRepoKinds.STACKED
416
 
            elif is_new_repo:
417
 
                target_repo_kind = fetch.TargetRepoKinds.EMPTY
418
 
            else:
419
 
                target_repo_kind = fetch.TargetRepoKinds.PREEXISTING
420
 
            fetch_spec_factory.target_repo_kind = target_repo_kind
421
 
            if source_repository is not None:
422
 
                fetch_spec = fetch_spec_factory.make_fetch_spec()
423
 
                result_repo.fetch(source_repository, fetch_spec=fetch_spec)
424
 
 
425
 
            if source_branch is None:
426
 
                # this is for sprouting a controldir without a branch; is that
427
 
                # actually useful?
428
 
                # Not especially, but it's part of the contract.
429
 
                result_branch = result.create_branch()
430
 
            else:
431
 
                result_branch = source_branch.sprout(
432
 
                    result, revision_id=revision_id,
433
 
                    repository_policy=repository_policy, repository=result_repo)
434
 
            mutter("created new branch %r" % (result_branch,))
435
 
 
436
 
            # Create/update the result working tree
437
 
            if (create_tree_if_local and not result.has_workingtree()
438
 
                    and isinstance(target_transport, local.LocalTransport)
439
 
                    and (result_repo is None or result_repo.make_working_trees())
440
 
                    and result.open_branch(
441
 
                        name="",
442
 
                        possible_transports=possible_transports).name == result_branch.name):
443
 
                wt = result.create_workingtree(
444
 
                    accelerator_tree=accelerator_tree, hardlink=hardlink,
445
 
                    from_branch=result_branch)
446
 
                with wt.lock_write():
447
 
                    if not wt.is_versioned(''):
448
 
                        try:
449
 
                            wt.set_root_id(self.open_workingtree.path2id(''))
450
 
                        except errors.NoWorkingTree:
451
 
                            pass
452
 
            else:
453
 
                wt = None
454
 
            if recurse == 'down':
455
 
                tree = None
456
 
                if wt is not None:
457
 
                    tree = wt
458
 
                    basis = tree.basis_tree()
459
 
                    stack.enter_context(basis.lock_read())
460
 
                elif result_branch is not None:
461
 
                    basis = tree = result_branch.basis_tree()
462
 
                elif source_branch is not None:
463
 
                    basis = tree = source_branch.basis_tree()
464
 
                if tree is not None:
465
 
                    stack.enter_context(tree.lock_read())
466
 
                    subtrees = tree.iter_references()
467
 
                else:
468
 
                    subtrees = []
469
 
                for path in subtrees:
470
 
                    target = urlutils.join(url, urlutils.escape(path))
471
 
                    sublocation = tree.reference_parent(
472
 
                        path, branch=result_branch,
473
 
                        possible_transports=possible_transports)
474
 
                    if sublocation is None:
475
 
                        warning(
476
 
                            'Ignoring nested tree %s, parent location unknown.',
477
 
                            path)
478
 
                        continue
479
 
                    sublocation.controldir.sprout(
480
 
                        target, basis.get_reference_revision(path),
481
 
                        force_new_repo=force_new_repo, recurse=recurse,
482
 
                        stacked=stacked)
483
 
            return result
 
438
                if wt.path2id('') is None:
 
439
                    try:
 
440
                        wt.set_root_id(self.open_workingtree.get_root_id())
 
441
                    except errors.NoWorkingTree:
 
442
                        pass
 
443
            finally:
 
444
                wt.unlock()
 
445
        else:
 
446
            wt = None
 
447
        if recurse == 'down':
 
448
            basis = None
 
449
            if wt is not None:
 
450
                basis = wt.basis_tree()
 
451
            elif result_branch is not None:
 
452
                basis = result_branch.basis_tree()
 
453
            elif source_branch is not None:
 
454
                basis = source_branch.basis_tree()
 
455
            if basis is not None:
 
456
                add_cleanup(basis.lock_read().unlock)
 
457
                subtrees = basis.iter_references()
 
458
            else:
 
459
                subtrees = []
 
460
            for path, file_id in subtrees:
 
461
                target = urlutils.join(url, urlutils.escape(path))
 
462
                sublocation = source_branch.reference_parent(file_id, path)
 
463
                sublocation.bzrdir.sprout(target,
 
464
                    basis.get_reference_revision(file_id, path),
 
465
                    force_new_repo=force_new_repo, recurse=recurse,
 
466
                    stacked=stacked)
 
467
        return result
484
468
 
485
469
    def _available_backup_name(self, base):
486
470
        """Find a non-existing backup file name based on base.
487
471
 
488
 
        See breezy.osutils.available_backup_name about race conditions.
 
472
        See brzlib.osutils.available_backup_name about race conditions.
489
473
        """
490
474
        return osutils.available_backup_name(base, self.root_transport.has)
491
475
 
495
479
        :return: Tuple with old path name and new path name
496
480
        """
497
481
 
498
 
        with ui.ui_factory.nested_progress_bar():
 
482
        pb = ui.ui_factory.nested_progress_bar()
 
483
        try:
499
484
            old_path = self.root_transport.abspath('.bzr')
500
485
            backup_dir = self._available_backup_name('backup.bzr')
501
486
            new_path = self.root_transport.abspath(backup_dir)
502
 
            ui.ui_factory.note(
503
 
                gettext('making backup of {0}\n  to {1}').format(
504
 
                    urlutils.unescape_for_display(old_path, 'utf-8'),
505
 
                    urlutils.unescape_for_display(new_path, 'utf-8')))
 
487
            ui.ui_factory.note(gettext('making backup of {0}\n  to {1}').format(
 
488
                urlutils.unescape_for_display(old_path, 'utf-8'),
 
489
                urlutils.unescape_for_display(new_path, 'utf-8')))
506
490
            self.root_transport.copy_tree('.bzr', backup_dir)
507
491
            return (old_path, new_path)
 
492
        finally:
 
493
            pb.finished()
508
494
 
509
495
    def retire_bzrdir(self, limit=10000):
510
496
        """Permanently disable the bzrdir.
516
502
        in use.
517
503
        :param limit: number of times to retry
518
504
        """
519
 
        i = 0
 
505
        i  = 0
520
506
        while True:
521
507
            try:
522
508
                to_path = '.bzr.retired.%d' % i
606
592
            # directories and files are read-write for this user. This is
607
593
            # mostly a workaround for filesystems which lie about being able to
608
594
            # write to a directory (cygwin & win32)
609
 
            if (st.st_mode & 0o7777 == 00000):
 
595
            if (st.st_mode & 07777 == 00000):
610
596
                # FTP allows stat but does not return dir/file modes
611
597
                self._dir_mode = None
612
598
                self._file_mode = None
613
599
            else:
614
 
                self._dir_mode = (st.st_mode & 0o7777) | 0o0700
 
600
                self._dir_mode = (st.st_mode & 07777) | 00700
615
601
                # Remove the sticky and execute bits for files
616
 
                self._file_mode = self._dir_mode & ~0o7111
 
602
                self._file_mode = self._dir_mode & ~07111
617
603
 
618
604
    def _get_file_mode(self):
619
605
        """Return Unix mode for newly created files, or None.
647
633
        :param _transport: the transport this dir is based at.
648
634
        """
649
635
        self._format = _format
650
 
        # these are also under the more standard names of
 
636
        # these are also under the more standard names of 
651
637
        # control_transport and user_transport
652
638
        self.transport = _transport.clone('.bzr')
653
639
        self.root_transport = _transport
654
640
        self._mode_check_done = False
655
641
 
656
 
    @property
 
642
    @property 
657
643
    def user_transport(self):
658
644
        return self.root_transport
659
645
 
661
647
    def control_transport(self):
662
648
        return self.transport
663
649
 
 
650
    def is_control_filename(self, filename):
 
651
        """True if filename is the name of a path which is reserved for bzrdir's.
 
652
 
 
653
        :param filename: A filename within the root transport of this bzrdir.
 
654
 
 
655
        This is true IF and ONLY IF the filename is part of the namespace reserved
 
656
        for bzr control dirs. Currently this is the '.bzr' directory in the root
 
657
        of the root_transport. 
 
658
        """
 
659
        # this might be better on the BzrDirFormat class because it refers to
 
660
        # all the possible bzrdir disk formats.
 
661
        # This method is tested via the workingtree is_control_filename tests-
 
662
        # it was extracted from WorkingTree.is_control_filename. If the method's
 
663
        # contract is extended beyond the current trivial implementation, please
 
664
        # add new tests for it to the appropriate place.
 
665
        return filename == '.bzr' or filename.startswith('.bzr/')
 
666
 
664
667
    def _cloning_metadir(self):
665
668
        """Produce a metadir suitable for cloning with.
666
669
 
673
676
                source_repository = branch.repository
674
677
                result_format._branch_format = branch._format
675
678
            except errors.NotBranchError:
 
679
                source_branch = None
676
680
                source_repository = self.open_repository()
677
681
        except errors.NoRepositoryPresent:
678
682
            source_repository = None
717
721
                return format
718
722
            # We have a repository, so set a working tree? (Why? This seems to
719
723
            # contradict the stated return value in the docstring).
720
 
            tree_format = (
721
 
                repository._format._matchingcontroldir.workingtree_format)
 
724
            tree_format = repository._format._matchingbzrdir.workingtree_format
722
725
            format.workingtree_format = tree_format.__class__()
723
726
        if require_stacking:
724
727
            format.require_stacking()
774
777
        """
775
778
        if cls is not BzrDir:
776
779
            raise AssertionError("BzrDir.create always creates the "
777
 
                                 "default format, not one of %r" % cls)
778
 
        return controldir.ControlDir.create(
779
 
            base, format=format, possible_transports=possible_transports)
 
780
                "default format, not one of %r" % cls)
 
781
        return controldir.ControlDir.create(base, format=format,
 
782
                possible_transports=possible_transports)
780
783
 
781
784
    def __repr__(self):
782
785
        return "<%s at %r>" % (self.__class__.__name__, self.user_url)
816
819
        """
817
820
        if name == "":
818
821
            return 'branch'
819
 
        return urlutils.join('branches', urlutils.escape(name))
 
822
        return urlutils.join('branches', name.encode("utf-8"))
820
823
 
821
824
    def _read_branch_list(self):
822
825
        """Read the branch list.
823
826
 
824
 
        :return: List of branch names.
 
827
        :return: List of utf-8 encoded branch names.
825
828
        """
826
829
        try:
827
830
            f = self.control_transport.get('branch-list')
831
834
        ret = []
832
835
        try:
833
836
            for name in f:
834
 
                ret.append(name.rstrip(b"\n").decode('utf-8'))
 
837
                ret.append(name.rstrip("\n"))
835
838
        finally:
836
839
            f.close()
837
840
        return ret
841
844
 
842
845
        :param branches: List of utf-8 branch names to write
843
846
        """
844
 
        self.transport.put_bytes(
845
 
            'branch-list',
846
 
            b"".join([name.encode('utf-8') + b"\n" for name in branches]))
 
847
        self.transport.put_bytes('branch-list',
 
848
            "".join([name+"\n" for name in branches]))
847
849
 
848
850
    def __init__(self, _transport, _format):
849
851
        super(BzrDirMeta1, self).__init__(_transport, _format)
856
858
        return True
857
859
 
858
860
    def create_branch(self, name=None, repository=None,
859
 
                      append_revisions_only=None):
 
861
            append_revisions_only=None):
860
862
        """See ControlDir.create_branch."""
861
863
        if name is None:
862
864
            name = self._get_selected_branch()
863
 
        return self._format.get_branch_format().initialize(
864
 
            self, name=name, repository=repository,
865
 
            append_revisions_only=append_revisions_only)
 
865
        return self._format.get_branch_format().initialize(self, name=name,
 
866
                repository=repository,
 
867
                append_revisions_only=append_revisions_only)
866
868
 
867
869
    def destroy_branch(self, name=None):
868
870
        """See ControlDir.destroy_branch."""
869
871
        if name is None:
870
872
            name = self._get_selected_branch()
871
873
        path = self._get_branch_path(name)
872
 
        if name != u"":
 
874
        if name != "":
873
875
            self.control_files.lock_write()
874
876
            try:
875
877
                branches = self._read_branch_list()
876
878
                try:
877
 
                    branches.remove(name)
 
879
                    branches.remove(name.encode("utf-8"))
878
880
                except ValueError:
879
881
                    raise errors.NotBranchError(name)
880
882
                self._write_branch_list(branches)
883
885
        try:
884
886
            self.transport.delete_tree(path)
885
887
        except errors.NoSuchFile:
886
 
            raise errors.NotBranchError(
887
 
                path=urlutils.join(self.transport.base, path), controldir=self)
 
888
            raise errors.NotBranchError(path=urlutils.join(self.transport.base,
 
889
                path), bzrdir=self)
888
890
 
889
891
    def create_repository(self, shared=False):
890
892
        """See BzrDir.create_repository."""
912
914
        # We ignore the conflicts returned by wt.revert since we're about to
913
915
        # delete the wt metadata anyway, all that should be left here are
914
916
        # detritus. But see bug #634470 about subtree .bzr dirs.
915
 
        wt.revert(old_tree=empty)
 
917
        conflicts = wt.revert(old_tree=empty)
916
918
        self.destroy_workingtree_metadata()
917
919
 
918
920
    def destroy_workingtree_metadata(self):
923
925
 
924
926
        This might be a synthetic object for e.g. RemoteBranch and SVN.
925
927
        """
926
 
        from .branch import BranchFormatMetadir
 
928
        from brzlib.branch import BranchFormatMetadir
927
929
        return BranchFormatMetadir.find_format(self, name=name)
928
930
 
929
931
    def _get_mkdir_mode(self):
930
932
        """Figure out the mode to use when creating a bzrdir subdir."""
931
 
        temp_control = lockable_files.LockableFiles(
932
 
            self.transport, '', lockable_files.TransportLock)
 
933
        temp_control = lockable_files.LockableFiles(self.transport, '',
 
934
                                     lockable_files.TransportLock)
933
935
        return temp_control._dir_mode
934
936
 
935
937
    def get_branch_reference(self, name=None):
936
938
        """See BzrDir.get_branch_reference()."""
937
 
        from .branch import BranchFormatMetadir
 
939
        from brzlib.branch import BranchFormatMetadir
938
940
        format = BranchFormatMetadir.find_format(self, name=name)
939
941
        return format.get_reference(self, name=name)
940
942
 
941
943
    def set_branch_reference(self, target_branch, name=None):
942
 
        format = _mod_bzrbranch.BranchReferenceFormat()
943
 
        if (self.control_url == target_branch.controldir.control_url
944
 
                and name == target_branch.name):
945
 
            raise controldir.BranchReferenceLoop(target_branch)
 
944
        format = _mod_branch.BranchReferenceFormat()
946
945
        return format.initialize(self, target_branch=target_branch, name=name)
947
946
 
948
947
    def get_branch_transport(self, branch_format, name=None):
960
959
            raise errors.IncompatibleFormat(branch_format, self._format)
961
960
        if name != "":
962
961
            branches = self._read_branch_list()
963
 
            if name not in branches:
 
962
            utf8_name = name.encode("utf-8")
 
963
            if not utf8_name in branches:
964
964
                self.control_files.lock_write()
965
965
                try:
966
966
                    branches = self._read_branch_list()
967
 
                    dirname = urlutils.dirname(name)
968
 
                    if dirname != u"" and dirname in branches:
 
967
                    dirname = urlutils.dirname(utf8_name)
 
968
                    if dirname != "" and dirname in branches:
969
969
                        raise errors.ParentBranchExists(name)
970
970
                    child_branches = [
971
 
                        b.startswith(name + u"/") for b in branches]
 
971
                        b.startswith(utf8_name+"/") for b in branches]
972
972
                    if any(child_branches):
973
973
                        raise errors.AlreadyBranchError(name)
974
 
                    branches.append(name)
 
974
                    branches.append(utf8_name)
975
975
                    self._write_branch_list(branches)
976
976
                finally:
977
977
                    self.control_files.unlock()
1021
1021
            pass
1022
1022
 
1023
1023
        for name in self._read_branch_list():
1024
 
            ret[name] = self.open_branch(name=name)
 
1024
            ret[name] = self.open_branch(name=name.decode('utf-8'))
1025
1025
 
1026
1026
        return ret
1027
1027
 
1031
1031
        Note: if you're going to open the working tree, you should just go
1032
1032
        ahead and try, and not ask permission first.
1033
1033
        """
1034
 
        from .workingtree import WorkingTreeFormatMetaDir
 
1034
        from brzlib.workingtree import WorkingTreeFormatMetaDir
1035
1035
        try:
1036
1036
            WorkingTreeFormatMetaDir.find_format_string(self)
1037
1037
        except errors.NoWorkingTree:
1040
1040
 
1041
1041
    def needs_format_conversion(self, format):
1042
1042
        """See BzrDir.needs_format_conversion()."""
1043
 
        if (not isinstance(self._format, format.__class__)
1044
 
                or self._format.get_format_string() != format.get_format_string()):
 
1043
        if (not isinstance(self._format, format.__class__) or
 
1044
            self._format.get_format_string() != format.get_format_string()):
1045
1045
            # it is not a meta dir format, conversion is needed.
1046
1046
            return True
1047
1047
        # we might want to push this down to the repository?
1074
1074
            name = self._get_selected_branch()
1075
1075
        format = self.find_branch_format(name=name)
1076
1076
        format.check_support_status(unsupported)
1077
 
        if possible_transports is None:
1078
 
            possible_transports = []
1079
 
        else:
1080
 
            possible_transports = list(possible_transports)
1081
 
        possible_transports.append(self.root_transport)
1082
1077
        return format.open(self, name=name,
1083
 
                           _found=True, ignore_fallbacks=ignore_fallbacks,
1084
 
                           possible_transports=possible_transports)
 
1078
            _found=True, ignore_fallbacks=ignore_fallbacks,
 
1079
            possible_transports=possible_transports)
1085
1080
 
1086
1081
    def open_repository(self, unsupported=False):
1087
1082
        """See BzrDir.open_repository."""
1088
 
        from .repository import RepositoryFormatMetaDir
 
1083
        from brzlib.repository import RepositoryFormatMetaDir
1089
1084
        format = RepositoryFormatMetaDir.find_format(self)
1090
1085
        format.check_support_status(unsupported)
1091
1086
        return format.open(self, _found=True)
1092
1087
 
1093
1088
    def open_workingtree(self, unsupported=False,
1094
 
                         recommend_upgrade=True):
 
1089
            recommend_upgrade=True):
1095
1090
        """See BzrDir.open_workingtree."""
1096
 
        from .workingtree import WorkingTreeFormatMetaDir
 
1091
        from brzlib.workingtree import WorkingTreeFormatMetaDir
1097
1092
        format = WorkingTreeFormatMetaDir.find_format(self)
1098
1093
        format.check_support_status(unsupported, recommend_upgrade,
1099
 
                                    basedir=self.root_transport.base)
 
1094
            basedir=self.root_transport.base)
1100
1095
        return format.open(self, _found=True)
1101
1096
 
1102
1097
    def _get_config(self):
1136
1131
 
1137
1132
        :param name: Name of the feature
1138
1133
        """
1139
 
        if b" " in name:
 
1134
        if " " in name:
1140
1135
            raise ValueError("spaces are not allowed in feature names")
1141
1136
        if name in cls._present_features:
1142
 
            raise FeatureAlreadyRegistered(name)
 
1137
            raise errors.FeatureAlreadyRegistered(name)
1143
1138
        cls._present_features.add(name)
1144
1139
 
1145
1140
    @classmethod
1148
1143
        cls._present_features.remove(name)
1149
1144
 
1150
1145
    def check_support_status(self, allow_unsupported, recommend_upgrade=True,
1151
 
                             basedir=None):
1152
 
        for name, necessity in self.features.items():
 
1146
            basedir=None):
 
1147
        for name, necessity in self.features.iteritems():
1153
1148
            if name in self._present_features:
1154
1149
                continue
1155
 
            if necessity == b"optional":
 
1150
            if necessity == "optional":
1156
1151
                mutter("ignoring optional missing feature %s", name)
1157
1152
                continue
1158
 
            elif necessity == b"required":
1159
 
                raise MissingFeature(name)
 
1153
            elif necessity == "required":
 
1154
                raise errors.MissingFeature(name)
1160
1155
            else:
1161
1156
                mutter("treating unknown necessity as require for %s",
1162
1157
                       name)
1163
 
                raise MissingFeature(name)
 
1158
                raise errors.MissingFeature(name)
1164
1159
 
1165
1160
    @classmethod
1166
1161
    def get_format_string(cls):
1171
1166
    def from_string(cls, text):
1172
1167
        format_string = cls.get_format_string()
1173
1168
        if not text.startswith(format_string):
1174
 
            raise AssertionError(
1175
 
                "Invalid format header %r for %r" % (text, cls))
 
1169
            raise AssertionError("Invalid format header %r for %r" % (text, cls))
1176
1170
        lines = text[len(format_string):].splitlines()
1177
1171
        ret = cls()
1178
1172
        for lineno, line in enumerate(lines):
1179
1173
            try:
1180
 
                (necessity, feature) = line.split(b" ", 1)
 
1174
                (necessity, feature) = line.split(" ", 1)
1181
1175
            except ValueError:
1182
 
                raise errors.ParseFormatError(format=cls, lineno=lineno + 2,
1183
 
                                              line=line, text=text)
 
1176
                raise errors.ParseFormatError(format=cls, lineno=lineno+2,
 
1177
                    line=line, text=text)
1184
1178
            ret.features[feature] = necessity
1185
1179
        return ret
1186
1180
 
1188
1182
        """Return the string representation of this format.
1189
1183
        """
1190
1184
        lines = [self.get_format_string()]
1191
 
        lines.extend([(item[1] + b" " + item[0] + b"\n")
1192
 
                      for item in sorted(self.features.items())])
1193
 
        return b"".join(lines)
 
1185
        lines.extend([("%s %s\n" % (item[1], item[0])) for item in
 
1186
            self.features.iteritems()])
 
1187
        return "".join(lines)
1194
1188
 
1195
1189
    @classmethod
1196
1190
    def _find_format(klass, registry, kind, format_string):
1197
1191
        try:
1198
 
            first_line = format_string[:format_string.index(b"\n") + 1]
 
1192
            first_line = format_string[:format_string.index("\n")+1]
1199
1193
        except ValueError:
1200
1194
            first_line = format_string
1201
1195
        try:
1212
1206
        return self.as_string()
1213
1207
 
1214
1208
    def __eq__(self, other):
1215
 
        return (self.__class__ is other.__class__
1216
 
                and self.features == other.features)
 
1209
        return (self.__class__ is other.__class__ and
 
1210
                self.features == other.features)
1217
1211
 
1218
1212
    def _update_feature_flags(self, updated_flags):
1219
1213
        """Update the feature flags in this format.
1220
1214
 
1221
1215
        :param updated_flags: Updated feature flags
1222
1216
        """
1223
 
        for name, necessity in updated_flags.items():
 
1217
        for name, necessity in updated_flags.iteritems():
1224
1218
            if necessity is None:
1225
1219
                try:
1226
1220
                    del self.features[name]
1230
1224
                self.features[name] = necessity
1231
1225
 
1232
1226
 
 
1227
class BzrProber(controldir.Prober):
 
1228
    """Prober for formats that use a .bzr/ control directory."""
 
1229
 
 
1230
    formats = registry.FormatRegistry(controldir.network_format_registry)
 
1231
    """The known .bzr formats."""
 
1232
 
 
1233
    @classmethod
 
1234
    def probe_transport(klass, transport):
 
1235
        """Return the .bzrdir style format present in a directory."""
 
1236
        try:
 
1237
            format_string = transport.get_bytes(".bzr/branch-format")
 
1238
        except errors.NoSuchFile:
 
1239
            raise errors.NotBranchError(path=transport.base)
 
1240
        try:
 
1241
            first_line = format_string[:format_string.index("\n")+1]
 
1242
        except ValueError:
 
1243
            first_line = format_string
 
1244
        try:
 
1245
            cls = klass.formats.get(first_line)
 
1246
        except KeyError:
 
1247
            raise errors.UnknownFormatError(format=first_line, kind='bzrdir')
 
1248
        return cls.from_string(format_string)
 
1249
 
 
1250
    @classmethod
 
1251
    def known_formats(cls):
 
1252
        result = set()
 
1253
        for name, format in cls.formats.iteritems():
 
1254
            if callable(format):
 
1255
                format = format()
 
1256
            result.add(format)
 
1257
        return result
 
1258
 
 
1259
 
 
1260
controldir.ControlDirFormat.register_prober(BzrProber)
 
1261
 
 
1262
 
 
1263
class RemoteBzrProber(controldir.Prober):
 
1264
    """Prober for remote servers that provide a Bazaar smart server."""
 
1265
 
 
1266
    @classmethod
 
1267
    def probe_transport(klass, transport):
 
1268
        """Return a RemoteBzrDirFormat object if it looks possible."""
 
1269
        try:
 
1270
            medium = transport.get_smart_medium()
 
1271
        except (NotImplementedError, AttributeError,
 
1272
                errors.TransportNotPossible, errors.NoSmartMedium,
 
1273
                errors.SmartProtocolError):
 
1274
            # no smart server, so not a branch for this format type.
 
1275
            raise errors.NotBranchError(path=transport.base)
 
1276
        else:
 
1277
            # Decline to open it if the server doesn't support our required
 
1278
            # version (3) so that the VFS-based transport will do it.
 
1279
            if medium.should_probe():
 
1280
                try:
 
1281
                    server_version = medium.protocol_version()
 
1282
                except errors.SmartProtocolError:
 
1283
                    # Apparently there's no usable smart server there, even though
 
1284
                    # the medium supports the smart protocol.
 
1285
                    raise errors.NotBranchError(path=transport.base)
 
1286
                if server_version != '2':
 
1287
                    raise errors.NotBranchError(path=transport.base)
 
1288
            from brzlib.remote import RemoteBzrDirFormat
 
1289
            return RemoteBzrDirFormat()
 
1290
 
 
1291
    @classmethod
 
1292
    def known_formats(cls):
 
1293
        from brzlib.remote import RemoteBzrDirFormat
 
1294
        return set([RemoteBzrDirFormat()])
 
1295
 
 
1296
 
1233
1297
class BzrDirFormat(BzrFormat, controldir.ControlDirFormat):
1234
1298
    """ControlDirFormat base class for .bzr/ directories.
1235
1299
 
1259
1323
            # Current RPC's only know how to create bzr metadir1 instances, so
1260
1324
            # we still delegate to vfs methods if the requested format is not a
1261
1325
            # metadir1
1262
 
            if not isinstance(self, BzrDirMetaFormat1):
 
1326
            if type(self) != BzrDirMetaFormat1:
1263
1327
                return self._initialize_on_transport_vfs(transport)
1264
 
            from .remote import RemoteBzrDirFormat
 
1328
            from brzlib.remote import RemoteBzrDirFormat
1265
1329
            remote_format = RemoteBzrDirFormat()
1266
1330
            self._supply_sub_formats_to(remote_format)
1267
1331
            return remote_format.initialize_on_transport(transport)
1268
1332
 
1269
1333
    def initialize_on_transport_ex(self, transport, use_existing_dir=False,
1270
 
                                   create_prefix=False, force_new_repo=False, stacked_on=None,
1271
 
                                   stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
1272
 
                                   shared_repo=False, vfs_only=False):
 
1334
        create_prefix=False, force_new_repo=False, stacked_on=None,
 
1335
        stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
 
1336
        shared_repo=False, vfs_only=False):
1273
1337
        """Create this format on transport.
1274
1338
 
1275
1339
        The directory to initialize will be created.
1299
1363
            parameter and any stacking policy found for the target.
1300
1364
        """
1301
1365
        if not vfs_only:
1302
 
            # Try to hand off to a smart server
 
1366
            # Try to hand off to a smart server 
1303
1367
            try:
1304
1368
                client_medium = transport.get_smart_medium()
1305
1369
            except errors.NoSmartMedium:
1306
1370
                pass
1307
1371
            else:
1308
 
                from .remote import RemoteBzrDirFormat
 
1372
                from brzlib.remote import RemoteBzrDirFormat
1309
1373
                # TODO: lookup the local format from a server hint.
1310
1374
                remote_dir_format = RemoteBzrDirFormat()
1311
1375
                remote_dir_format._network_name = self.network_name()
1312
1376
                self._supply_sub_formats_to(remote_dir_format)
1313
1377
                return remote_dir_format.initialize_on_transport_ex(transport,
1314
 
                                                                    use_existing_dir=use_existing_dir, create_prefix=create_prefix,
1315
 
                                                                    force_new_repo=force_new_repo, stacked_on=stacked_on,
1316
 
                                                                    stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
1317
 
                                                                    make_working_trees=make_working_trees, shared_repo=shared_repo)
 
1378
                    use_existing_dir=use_existing_dir, create_prefix=create_prefix,
 
1379
                    force_new_repo=force_new_repo, stacked_on=stacked_on,
 
1380
                    stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
 
1381
                    make_working_trees=make_working_trees, shared_repo=shared_repo)
1318
1382
        # XXX: Refactor the create_prefix/no_create_prefix code into a
1319
1383
        #      common helper function
1320
1384
        # The destination may not exist - if so make it according to policy.
1321
 
 
1322
1385
        def make_directory(transport):
1323
1386
            transport.mkdir('.')
1324
1387
            return transport
1325
 
 
1326
1388
        def redirected(transport, e, redirection_notice):
1327
1389
            note(redirection_notice)
1328
1390
            return transport._redirected_to(e.source, e.target)
1329
1391
        try:
1330
1392
            transport = do_catching_redirections(make_directory, transport,
1331
 
                                                 redirected)
 
1393
                redirected)
1332
1394
        except errors.FileExists:
1333
1395
            if not use_existing_dir:
1334
1396
                raise
1375
1437
        # Since we are creating a .bzr directory, inherit the
1376
1438
        # mode from the root directory
1377
1439
        temp_control = lockable_files.LockableFiles(transport,
1378
 
                                                    '', lockable_files.TransportLock)
 
1440
                            '', lockable_files.TransportLock)
1379
1441
        try:
1380
1442
            temp_control._transport.mkdir('.bzr',
1381
 
                                          # FIXME: RBC 20060121 don't peek under
1382
 
                                          # the covers
1383
 
                                          mode=temp_control._dir_mode)
 
1443
                # FIXME: RBC 20060121 don't peek under
 
1444
                # the covers
 
1445
                mode=temp_control._dir_mode)
1384
1446
        except errors.FileExists:
1385
1447
            raise errors.AlreadyControlDirError(transport.base)
1386
1448
        if sys.platform == 'win32' and isinstance(transport, local.LocalTransport):
1389
1451
        del temp_control
1390
1452
        bzrdir_transport = transport.clone('.bzr')
1391
1453
        utf8_files = [('README',
1392
 
                       b"This is a Bazaar control directory.\n"
1393
 
                       b"Do not change any files in this directory.\n"
1394
 
                       b"See http://bazaar.canonical.com/ for more information about Bazaar.\n"),
 
1454
                       "This is a Bazaar control directory.\n"
 
1455
                       "Do not change any files in this directory.\n"
 
1456
                       "See http://bazaar.canonical.com/ for more information about Bazaar.\n"),
1395
1457
                      ('branch-format', self.as_string()),
1396
1458
                      ]
1397
1459
        # NB: no need to escape relative paths that are url safe.
1398
1460
        control_files = lockable_files.LockableFiles(bzrdir_transport,
1399
 
                                                     self._lock_file_name, self._lock_class)
 
1461
            self._lock_file_name, self._lock_class)
1400
1462
        control_files.create_lock()
1401
1463
        control_files.lock_write()
1402
1464
        try:
1403
1465
            for (filename, content) in utf8_files:
1404
1466
                bzrdir_transport.put_bytes(filename, content,
1405
 
                                           mode=file_mode)
 
1467
                    mode=file_mode)
1406
1468
        finally:
1407
1469
            control_files.unlock()
1408
1470
        return self.open(transport, _found=True)
1416
1478
            found_format = controldir.ControlDirFormat.find_format(transport)
1417
1479
            if not isinstance(found_format, self.__class__):
1418
1480
                raise AssertionError("%s was asked to open %s, but it seems to need "
1419
 
                                     "format %s"
1420
 
                                     % (self, transport, found_format))
 
1481
                        "format %s"
 
1482
                        % (self, transport, found_format))
1421
1483
            # Allow subclasses - use the found format.
1422
1484
            self._supply_sub_formats_to(found_format)
1423
1485
            return found_format._open(transport)
1449
1511
        return True
1450
1512
 
1451
1513
    def check_support_status(self, allow_unsupported, recommend_upgrade=True,
1452
 
                             basedir=None):
 
1514
            basedir=None):
1453
1515
        controldir.ControlDirFormat.check_support_status(self,
1454
 
                                                         allow_unsupported=allow_unsupported, recommend_upgrade=recommend_upgrade,
1455
 
                                                         basedir=basedir)
 
1516
            allow_unsupported=allow_unsupported, recommend_upgrade=recommend_upgrade,
 
1517
            basedir=basedir)
1456
1518
        BzrFormat.check_support_status(self, allow_unsupported=allow_unsupported,
1457
 
                                       recommend_upgrade=recommend_upgrade, basedir=basedir)
1458
 
 
1459
 
    @classmethod
1460
 
    def is_control_filename(klass, filename):
1461
 
        """True if filename is the name of a path which is reserved for bzrdir's.
1462
 
 
1463
 
        :param filename: A filename within the root transport of this bzrdir.
1464
 
 
1465
 
        This is true IF and ONLY IF the filename is part of the namespace
1466
 
        reserved for bzr control dirs. Currently this is the '.bzr' directory
1467
 
        in the root of the root_transport.
1468
 
        """
1469
 
        # this might be better on the BzrDirFormat class because it refers to
1470
 
        # all the possible bzrdir disk formats.
1471
 
        # This method is tested via the workingtree is_control_filename tests-
1472
 
        # it was extracted from WorkingTree.is_control_filename. If the
1473
 
        # method's contract is extended beyond the current trivial
1474
 
        # implementation, please add new tests for it to the appropriate place.
1475
 
        return filename == '.bzr' or filename.startswith('.bzr/')
 
1519
            recommend_upgrade=recommend_upgrade, basedir=basedir)
1476
1520
 
1477
1521
 
1478
1522
class BzrDirMetaFormat1(BzrDirFormat):
1516
1560
 
1517
1561
    def get_branch_format(self):
1518
1562
        if self._branch_format is None:
1519
 
            from .branch import format_registry as branch_format_registry
 
1563
            from brzlib.branch import format_registry as branch_format_registry
1520
1564
            self._branch_format = branch_format_registry.get_default()
1521
1565
        return self._branch_format
1522
1566
 
1524
1568
        self._branch_format = format
1525
1569
 
1526
1570
    def require_stacking(self, stack_on=None, possible_transports=None,
1527
 
                         _skip_repo=False):
 
1571
            _skip_repo=False):
1528
1572
        """We have a request to stack, try to ensure the formats support it.
1529
1573
 
1530
1574
        :param stack_on: If supplied, it is the URL to a branch that we want to
1539
1583
 
1540
1584
        # a bit of state for get_target_branch so that we don't try to open it
1541
1585
        # 2 times, for both repo *and* branch
1542
 
        target = [None, False, None]  # target_branch, checked, upgrade anyway
1543
 
 
 
1586
        target = [None, False, None] # target_branch, checked, upgrade anyway
1544
1587
        def get_target_branch():
1545
1588
            if target[1]:
1546
1589
                # We've checked, don't check again
1551
1594
                return target
1552
1595
            try:
1553
1596
                target_dir = BzrDir.open(stack_on,
1554
 
                                         possible_transports=possible_transports)
 
1597
                    possible_transports=possible_transports)
1555
1598
            except errors.NotBranchError:
1556
1599
                # Nothing there, don't change formats
1557
1600
                target[:] = [None, True, False]
1569
1612
            target[:] = [target_branch, True, False]
1570
1613
            return target
1571
1614
 
1572
 
        if (not _skip_repo
1573
 
                and not self.repository_format.supports_external_lookups):
 
1615
        if (not _skip_repo and
 
1616
                 not self.repository_format.supports_external_lookups):
1574
1617
            # We need to upgrade the Repository.
1575
1618
            target_branch, _, do_upgrade = get_target_branch()
1576
1619
            if target_branch is None:
1594
1637
            if new_repo_format is not None:
1595
1638
                self.repository_format = new_repo_format
1596
1639
                note(gettext('Source repository format does not support stacking,'
1597
 
                             ' using format:\n  %s'),
 
1640
                     ' using format:\n  %s'),
1598
1641
                     new_repo_format.get_format_description())
1599
1642
 
1600
1643
        if not self.get_branch_format().supports_stacking():
1604
1647
            if target_branch is None:
1605
1648
                if do_upgrade:
1606
1649
                    # TODO: bad monkey, hard-coded formats...
1607
 
                    from .branch import BzrBranchFormat7
 
1650
                    from brzlib.branch import BzrBranchFormat7
1608
1651
                    new_branch_format = BzrBranchFormat7()
1609
1652
            else:
1610
1653
                new_branch_format = target_branch._format
1614
1657
                # Does support stacking, use its format.
1615
1658
                self.set_branch_format(new_branch_format)
1616
1659
                note(gettext('Source branch format does not support stacking,'
1617
 
                             ' using format:\n  %s'),
 
1660
                     ' using format:\n  %s'),
1618
1661
                     new_branch_format.get_format_description())
1619
1662
 
1620
1663
    def get_converter(self, format=None):
1621
1664
        """See BzrDirFormat.get_converter()."""
1622
1665
        if format is None:
1623
1666
            format = BzrDirFormat.get_default_format()
1624
 
        if (isinstance(self, BzrDirMetaFormat1)
1625
 
                and isinstance(format, BzrDirMetaFormat1Colo)):
 
1667
        if (type(self) is BzrDirMetaFormat1 and
 
1668
            type(format) is BzrDirMetaFormat1Colo):
1626
1669
            return ConvertMetaToColo(format)
1627
 
        if (isinstance(self, BzrDirMetaFormat1Colo)
1628
 
                and isinstance(format, BzrDirMetaFormat1)):
 
1670
        if (type(self) is BzrDirMetaFormat1Colo and
 
1671
            type(format) is BzrDirMetaFormat1):
1629
1672
            return ConvertMetaToColo(format)
1630
1673
        if not isinstance(self, format.__class__):
1631
1674
            # converting away from metadir is not implemented
1635
1678
    @classmethod
1636
1679
    def get_format_string(cls):
1637
1680
        """See BzrDirFormat.get_format_string()."""
1638
 
        return b"Bazaar-NG meta directory, format 1\n"
 
1681
        return "Bazaar-NG meta directory, format 1\n"
1639
1682
 
1640
1683
    def get_format_description(self):
1641
1684
        """See BzrDirFormat.get_format_description()."""
1654
1697
        """Circular import protection."""
1655
1698
        if self._repository_format:
1656
1699
            return self._repository_format
1657
 
        from .repository import format_registry
 
1700
        from brzlib.repository import format_registry
1658
1701
        return format_registry.get_default()
1659
1702
 
1660
1703
    def _set_repository_format(self, value):
1662
1705
        self._repository_format = value
1663
1706
 
1664
1707
    repository_format = property(__return_repository_format,
1665
 
                                 _set_repository_format)
 
1708
        _set_repository_format)
1666
1709
 
1667
1710
    def _supply_sub_formats_to(self, other_format):
1668
1711
        """Give other_format the same values for sub formats as this has.
1685
1728
 
1686
1729
    def __get_workingtree_format(self):
1687
1730
        if self._workingtree_format is None:
1688
 
            from .workingtree import (
 
1731
            from brzlib.workingtree import (
1689
1732
                format_registry as wt_format_registry,
1690
1733
                )
1691
1734
            self._workingtree_format = wt_format_registry.get_default()
1701
1744
                                  __set_workingtree_format)
1702
1745
 
1703
1746
 
 
1747
# Register bzr formats
 
1748
BzrProber.formats.register(BzrDirMetaFormat1.get_format_string(),
 
1749
    BzrDirMetaFormat1)
 
1750
controldir.ControlDirFormat._default_format = BzrDirMetaFormat1()
 
1751
 
 
1752
 
1704
1753
class BzrDirMetaFormat1Colo(BzrDirMetaFormat1):
1705
1754
    """BzrDirMeta1 format with support for colocated branches."""
1706
1755
 
1709
1758
    @classmethod
1710
1759
    def get_format_string(cls):
1711
1760
        """See BzrDirFormat.get_format_string()."""
1712
 
        return b"Bazaar meta directory, format 1 (with colocated branches)\n"
 
1761
        return "Bazaar meta directory, format 1 (with colocated branches)\n"
1713
1762
 
1714
1763
    def get_format_description(self):
1715
1764
        """See BzrDirFormat.get_format_description()."""
1725
1774
        return BzrDirMeta1(transport, format)
1726
1775
 
1727
1776
 
 
1777
BzrProber.formats.register(BzrDirMetaFormat1Colo.get_format_string(),
 
1778
    BzrDirMetaFormat1Colo)
 
1779
 
 
1780
 
1728
1781
class ConvertMetaToMeta(controldir.Converter):
1729
1782
    """Converts the components of metadirs."""
1730
1783
 
1737
1790
 
1738
1791
    def convert(self, to_convert, pb):
1739
1792
        """See Converter.convert()."""
1740
 
        self.controldir = to_convert
1741
 
        with ui.ui_factory.nested_progress_bar() as self.pb:
1742
 
            self.count = 0
1743
 
            self.total = 1
1744
 
            self.step('checking repository format')
1745
 
            try:
1746
 
                repo = self.controldir.open_repository()
1747
 
            except errors.NoRepositoryPresent:
1748
 
                pass
1749
 
            else:
1750
 
                repo_fmt = self.target_format.repository_format
1751
 
                if not isinstance(repo._format, repo_fmt.__class__):
1752
 
                    from ..repository import CopyConverter
1753
 
                    ui.ui_factory.note(gettext('starting repository conversion'))
1754
 
                    if not repo_fmt.supports_overriding_transport:
1755
 
                        raise AssertionError(
1756
 
                            "Repository in metadir does not support "
1757
 
                            "overriding transport")
1758
 
                    converter = CopyConverter(self.target_format.repository_format)
1759
 
                    converter.convert(repo, pb)
1760
 
            for branch in self.controldir.list_branches():
1761
 
                # TODO: conversions of Branch and Tree should be done by
1762
 
                # InterXFormat lookups/some sort of registry.
1763
 
                # Avoid circular imports
 
1793
        self.bzrdir = to_convert
 
1794
        self.pb = ui.ui_factory.nested_progress_bar()
 
1795
        self.count = 0
 
1796
        self.total = 1
 
1797
        self.step('checking repository format')
 
1798
        try:
 
1799
            repo = self.bzrdir.open_repository()
 
1800
        except errors.NoRepositoryPresent:
 
1801
            pass
 
1802
        else:
 
1803
            if not isinstance(repo._format, self.target_format.repository_format.__class__):
 
1804
                from brzlib.repository import CopyConverter
 
1805
                ui.ui_factory.note(gettext('starting repository conversion'))
 
1806
                converter = CopyConverter(self.target_format.repository_format)
 
1807
                converter.convert(repo, pb)
 
1808
        for branch in self.bzrdir.list_branches():
 
1809
            # TODO: conversions of Branch and Tree should be done by
 
1810
            # InterXFormat lookups/some sort of registry.
 
1811
            # Avoid circular imports
 
1812
            old = branch._format.__class__
 
1813
            new = self.target_format.get_branch_format().__class__
 
1814
            while old != new:
 
1815
                if (old == fullhistorybranch.BzrBranchFormat5 and
 
1816
                    new in (_mod_branch.BzrBranchFormat6,
 
1817
                        _mod_branch.BzrBranchFormat7,
 
1818
                        _mod_branch.BzrBranchFormat8)):
 
1819
                    branch_converter = _mod_branch.Converter5to6()
 
1820
                elif (old == _mod_branch.BzrBranchFormat6 and
 
1821
                    new in (_mod_branch.BzrBranchFormat7,
 
1822
                            _mod_branch.BzrBranchFormat8)):
 
1823
                    branch_converter = _mod_branch.Converter6to7()
 
1824
                elif (old == _mod_branch.BzrBranchFormat7 and
 
1825
                      new is _mod_branch.BzrBranchFormat8):
 
1826
                    branch_converter = _mod_branch.Converter7to8()
 
1827
                else:
 
1828
                    raise errors.BadConversionTarget("No converter", new,
 
1829
                        branch._format)
 
1830
                branch_converter.convert(branch)
 
1831
                branch = self.bzrdir.open_branch()
1764
1832
                old = branch._format.__class__
1765
 
                new = self.target_format.get_branch_format().__class__
1766
 
                while old != new:
1767
 
                    if (old == fullhistorybranch.BzrBranchFormat5
1768
 
                        and new in (_mod_bzrbranch.BzrBranchFormat6,
1769
 
                                    _mod_bzrbranch.BzrBranchFormat7,
1770
 
                                    _mod_bzrbranch.BzrBranchFormat8)):
1771
 
                        branch_converter = _mod_bzrbranch.Converter5to6()
1772
 
                    elif (old == _mod_bzrbranch.BzrBranchFormat6
1773
 
                          and new in (_mod_bzrbranch.BzrBranchFormat7,
1774
 
                                      _mod_bzrbranch.BzrBranchFormat8)):
1775
 
                        branch_converter = _mod_bzrbranch.Converter6to7()
1776
 
                    elif (old == _mod_bzrbranch.BzrBranchFormat7
1777
 
                          and new is _mod_bzrbranch.BzrBranchFormat8):
1778
 
                        branch_converter = _mod_bzrbranch.Converter7to8()
1779
 
                    else:
1780
 
                        raise errors.BadConversionTarget("No converter", new,
1781
 
                                                         branch._format)
1782
 
                    branch_converter.convert(branch)
1783
 
                    branch = self.controldir.open_branch()
1784
 
                    old = branch._format.__class__
1785
 
            try:
1786
 
                tree = self.controldir.open_workingtree(recommend_upgrade=False)
1787
 
            except (errors.NoWorkingTree, errors.NotLocalUrl):
1788
 
                pass
1789
 
            else:
1790
 
                # TODO: conversions of Branch and Tree should be done by
1791
 
                # InterXFormat lookups
1792
 
                if (isinstance(tree, workingtree_3.WorkingTree3)
1793
 
                    and not isinstance(tree, workingtree_4.DirStateWorkingTree)
1794
 
                    and isinstance(self.target_format.workingtree_format,
1795
 
                                   workingtree_4.DirStateWorkingTreeFormat)):
1796
 
                    workingtree_4.Converter3to4().convert(tree)
1797
 
                if (isinstance(tree, workingtree_4.DirStateWorkingTree)
1798
 
                    and not isinstance(tree, workingtree_4.WorkingTree5)
1799
 
                    and isinstance(self.target_format.workingtree_format,
1800
 
                                   workingtree_4.WorkingTreeFormat5)):
1801
 
                    workingtree_4.Converter4to5().convert(tree)
1802
 
                if (isinstance(tree, workingtree_4.DirStateWorkingTree)
1803
 
                    and not isinstance(tree, workingtree_4.WorkingTree6)
1804
 
                    and isinstance(self.target_format.workingtree_format,
1805
 
                                   workingtree_4.WorkingTreeFormat6)):
1806
 
                    workingtree_4.Converter4or5to6().convert(tree)
 
1833
        try:
 
1834
            tree = self.bzrdir.open_workingtree(recommend_upgrade=False)
 
1835
        except (errors.NoWorkingTree, errors.NotLocalUrl):
 
1836
            pass
 
1837
        else:
 
1838
            # TODO: conversions of Branch and Tree should be done by
 
1839
            # InterXFormat lookups
 
1840
            if (isinstance(tree, workingtree_3.WorkingTree3) and
 
1841
                not isinstance(tree, workingtree_4.DirStateWorkingTree) and
 
1842
                isinstance(self.target_format.workingtree_format,
 
1843
                    workingtree_4.DirStateWorkingTreeFormat)):
 
1844
                workingtree_4.Converter3to4().convert(tree)
 
1845
            if (isinstance(tree, workingtree_4.DirStateWorkingTree) and
 
1846
                not isinstance(tree, workingtree_4.WorkingTree5) and
 
1847
                isinstance(self.target_format.workingtree_format,
 
1848
                    workingtree_4.WorkingTreeFormat5)):
 
1849
                workingtree_4.Converter4to5().convert(tree)
 
1850
            if (isinstance(tree, workingtree_4.DirStateWorkingTree) and
 
1851
                not isinstance(tree, workingtree_4.WorkingTree6) and
 
1852
                isinstance(self.target_format.workingtree_format,
 
1853
                    workingtree_4.WorkingTreeFormat6)):
 
1854
                workingtree_4.Converter4or5to6().convert(tree)
 
1855
        self.pb.finished()
1807
1856
        return to_convert
1808
1857
 
1809
1858
 
1820
1869
    def convert(self, to_convert, pb):
1821
1870
        """See Converter.convert()."""
1822
1871
        to_convert.transport.put_bytes('branch-format',
1823
 
                                       self.target_format.as_string())
 
1872
            self.target_format.as_string())
1824
1873
        return BzrDir.open_from_transport(to_convert.root_transport)
1825
1874
 
1826
1875
 
1838
1887
    def convert(self, to_convert, pb):
1839
1888
        """See Converter.convert()."""
1840
1889
        to_convert.transport.put_bytes('branch-format',
1841
 
                                       self.target_format.as_string())
 
1890
            self.target_format.as_string())
1842
1891
        return BzrDir.open_from_transport(to_convert.root_transport)
1843
1892
 
1844
1893
 
1845
 
class CreateRepository(controldir.RepositoryAcquisitionPolicy):
 
1894
controldir.ControlDirFormat.register_server_prober(RemoteBzrProber)
 
1895
 
 
1896
 
 
1897
class RepositoryAcquisitionPolicy(object):
 
1898
    """Abstract base class for repository acquisition policies.
 
1899
 
 
1900
    A repository acquisition policy decides how a BzrDir acquires a repository
 
1901
    for a branch that is being created.  The most basic policy decision is
 
1902
    whether to create a new repository or use an existing one.
 
1903
    """
 
1904
    def __init__(self, stack_on, stack_on_pwd, require_stacking):
 
1905
        """Constructor.
 
1906
 
 
1907
        :param stack_on: A location to stack on
 
1908
        :param stack_on_pwd: If stack_on is relative, the location it is
 
1909
            relative to.
 
1910
        :param require_stacking: If True, it is a failure to not stack.
 
1911
        """
 
1912
        self._stack_on = stack_on
 
1913
        self._stack_on_pwd = stack_on_pwd
 
1914
        self._require_stacking = require_stacking
 
1915
 
 
1916
    def configure_branch(self, branch):
 
1917
        """Apply any configuration data from this policy to the branch.
 
1918
 
 
1919
        Default implementation sets repository stacking.
 
1920
        """
 
1921
        if self._stack_on is None:
 
1922
            return
 
1923
        if self._stack_on_pwd is None:
 
1924
            stack_on = self._stack_on
 
1925
        else:
 
1926
            try:
 
1927
                stack_on = urlutils.rebase_url(self._stack_on,
 
1928
                    self._stack_on_pwd,
 
1929
                    branch.user_url)
 
1930
            except errors.InvalidRebaseURLs:
 
1931
                stack_on = self._get_full_stack_on()
 
1932
        try:
 
1933
            branch.set_stacked_on_url(stack_on)
 
1934
        except (errors.UnstackableBranchFormat,
 
1935
                errors.UnstackableRepositoryFormat):
 
1936
            if self._require_stacking:
 
1937
                raise
 
1938
 
 
1939
    def requires_stacking(self):
 
1940
        """Return True if this policy requires stacking."""
 
1941
        return self._stack_on is not None and self._require_stacking
 
1942
 
 
1943
    def _get_full_stack_on(self):
 
1944
        """Get a fully-qualified URL for the stack_on location."""
 
1945
        if self._stack_on is None:
 
1946
            return None
 
1947
        if self._stack_on_pwd is None:
 
1948
            return self._stack_on
 
1949
        else:
 
1950
            return urlutils.join(self._stack_on_pwd, self._stack_on)
 
1951
 
 
1952
    def _add_fallback(self, repository, possible_transports=None):
 
1953
        """Add a fallback to the supplied repository, if stacking is set."""
 
1954
        stack_on = self._get_full_stack_on()
 
1955
        if stack_on is None:
 
1956
            return
 
1957
        try:
 
1958
            stacked_dir = BzrDir.open(stack_on,
 
1959
                                      possible_transports=possible_transports)
 
1960
        except errors.JailBreak:
 
1961
            # We keep the stacking details, but we are in the server code so
 
1962
            # actually stacking is not needed.
 
1963
            return
 
1964
        try:
 
1965
            stacked_repo = stacked_dir.open_branch().repository
 
1966
        except errors.NotBranchError:
 
1967
            stacked_repo = stacked_dir.open_repository()
 
1968
        try:
 
1969
            repository.add_fallback_repository(stacked_repo)
 
1970
        except errors.UnstackableRepositoryFormat:
 
1971
            if self._require_stacking:
 
1972
                raise
 
1973
        else:
 
1974
            self._require_stacking = True
 
1975
 
 
1976
    def acquire_repository(self, make_working_trees=None, shared=False,
 
1977
            possible_transports=None):
 
1978
        """Acquire a repository for this bzrdir.
 
1979
 
 
1980
        Implementations may create a new repository or use a pre-exising
 
1981
        repository.
 
1982
 
 
1983
        :param make_working_trees: If creating a repository, set
 
1984
            make_working_trees to this value (if non-None)
 
1985
        :param shared: If creating a repository, make it shared if True
 
1986
        :return: A repository, is_new_flag (True if the repository was
 
1987
            created).
 
1988
        """
 
1989
        raise NotImplementedError(RepositoryAcquisitionPolicy.acquire_repository)
 
1990
 
 
1991
 
 
1992
class CreateRepository(RepositoryAcquisitionPolicy):
1846
1993
    """A policy of creating a new repository"""
1847
1994
 
1848
 
    def __init__(self, controldir, stack_on=None, stack_on_pwd=None,
 
1995
    def __init__(self, bzrdir, stack_on=None, stack_on_pwd=None,
1849
1996
                 require_stacking=False):
1850
1997
        """Constructor.
1851
1998
 
1852
 
        :param controldir: The controldir to create the repository on.
 
1999
        :param bzrdir: The bzrdir to create the repository on.
1853
2000
        :param stack_on: A location to stack on
1854
2001
        :param stack_on_pwd: If stack_on is relative, the location it is
1855
2002
            relative to.
1856
2003
        """
1857
 
        super(CreateRepository, self).__init__(
1858
 
            stack_on, stack_on_pwd, require_stacking)
1859
 
        self._controldir = controldir
 
2004
        RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
 
2005
                                             require_stacking)
 
2006
        self._bzrdir = bzrdir
1860
2007
 
1861
2008
    def acquire_repository(self, make_working_trees=None, shared=False,
1862
 
                           possible_transports=None):
 
2009
            possible_transports=None):
1863
2010
        """Implementation of RepositoryAcquisitionPolicy.acquire_repository
1864
2011
 
1865
 
        Creates the desired repository in the controldir we already have.
 
2012
        Creates the desired repository in the bzrdir we already have.
1866
2013
        """
1867
2014
        if possible_transports is None:
1868
2015
            possible_transports = []
1869
2016
        else:
1870
2017
            possible_transports = list(possible_transports)
1871
 
        possible_transports.append(self._controldir.root_transport)
 
2018
        possible_transports.append(self._bzrdir.root_transport)
1872
2019
        stack_on = self._get_full_stack_on()
1873
2020
        if stack_on:
1874
 
            format = self._controldir._format
 
2021
            format = self._bzrdir._format
1875
2022
            format.require_stacking(stack_on=stack_on,
1876
2023
                                    possible_transports=possible_transports)
1877
2024
            if not self._require_stacking:
1878
2025
                # We have picked up automatic stacking somewhere.
1879
2026
                note(gettext('Using default stacking branch {0} at {1}').format(
1880
2027
                    self._stack_on, self._stack_on_pwd))
1881
 
        repository = self._controldir.create_repository(shared=shared)
 
2028
        repository = self._bzrdir.create_repository(shared=shared)
1882
2029
        self._add_fallback(repository,
1883
2030
                           possible_transports=possible_transports)
1884
2031
        if make_working_trees is not None:
1886
2033
        return repository, True
1887
2034
 
1888
2035
 
1889
 
class UseExistingRepository(controldir.RepositoryAcquisitionPolicy):
 
2036
class UseExistingRepository(RepositoryAcquisitionPolicy):
1890
2037
    """A policy of reusing an existing repository"""
1891
2038
 
1892
2039
    def __init__(self, repository, stack_on=None, stack_on_pwd=None,
1898
2045
        :param stack_on_pwd: If stack_on is relative, the location it is
1899
2046
            relative to.
1900
2047
        """
1901
 
        super(UseExistingRepository, self).__init__(
1902
 
            stack_on, stack_on_pwd, require_stacking)
 
2048
        RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
 
2049
                                             require_stacking)
1903
2050
        self._repository = repository
1904
2051
 
1905
2052
    def acquire_repository(self, make_working_trees=None, shared=False,
1906
 
                           possible_transports=None):
 
2053
            possible_transports=None):
1907
2054
        """Implementation of RepositoryAcquisitionPolicy.acquire_repository
1908
2055
 
1909
2056
        Returns an existing repository to use.
1912
2059
            possible_transports = []
1913
2060
        else:
1914
2061
            possible_transports = list(possible_transports)
1915
 
        possible_transports.append(self._repository.controldir.transport)
 
2062
        possible_transports.append(self._repository.bzrdir.transport)
1916
2063
        self._add_fallback(self._repository,
1917
 
                           possible_transports=possible_transports)
 
2064
                       possible_transports=possible_transports)
1918
2065
        return self._repository, False
1919
2066
 
1920
2067
 
1921
 
controldir.ControlDirFormat._default_format = BzrDirMetaFormat1()
 
2068
def register_metadir(registry, key,
 
2069
         repository_format, help, native=True, deprecated=False,
 
2070
         branch_format=None,
 
2071
         tree_format=None,
 
2072
         hidden=False,
 
2073
         experimental=False,
 
2074
         alias=False, bzrdir_format=None):
 
2075
    """Register a metadir subformat.
 
2076
 
 
2077
    These all use a meta bzrdir, but can be parameterized by the
 
2078
    Repository/Branch/WorkingTreeformats.
 
2079
 
 
2080
    :param repository_format: The fully-qualified repository format class
 
2081
        name as a string.
 
2082
    :param branch_format: Fully-qualified branch format class name as
 
2083
        a string.
 
2084
    :param tree_format: Fully-qualified tree format class name as
 
2085
        a string.
 
2086
    """
 
2087
    if bzrdir_format is None:
 
2088
        bzrdir_format = BzrDirMetaFormat1
 
2089
    # This should be expanded to support setting WorkingTree and Branch
 
2090
    # formats, once the API supports that.
 
2091
    def _load(full_name):
 
2092
        mod_name, factory_name = full_name.rsplit('.', 1)
 
2093
        try:
 
2094
            factory = pyutils.get_named_object(mod_name, factory_name)
 
2095
        except ImportError, e:
 
2096
            raise ImportError('failed to load %s: %s' % (full_name, e))
 
2097
        except AttributeError:
 
2098
            raise AttributeError('no factory %s in module %r'
 
2099
                % (full_name, sys.modules[mod_name]))
 
2100
        return factory()
 
2101
 
 
2102
    def helper():
 
2103
        bd = bzrdir_format()
 
2104
        if branch_format is not None:
 
2105
            bd.set_branch_format(_load(branch_format))
 
2106
        if tree_format is not None:
 
2107
            bd.workingtree_format = _load(tree_format)
 
2108
        if repository_format is not None:
 
2109
            bd.repository_format = _load(repository_format)
 
2110
        return bd
 
2111
    registry.register(key, helper, help, native, deprecated, hidden,
 
2112
        experimental, alias)
 
2113
 
 
2114
register_metadir(controldir.format_registry, 'knit',
 
2115
    'brzlib.repofmt.knitrepo.RepositoryFormatKnit1',
 
2116
    'Format using knits.  Recommended for interoperation with bzr <= 0.14.',
 
2117
    branch_format='brzlib.branchfmt.fullhistory.BzrBranchFormat5',
 
2118
    tree_format='brzlib.workingtree_3.WorkingTreeFormat3',
 
2119
    hidden=True,
 
2120
    deprecated=True)
 
2121
register_metadir(controldir.format_registry, 'dirstate',
 
2122
    'brzlib.repofmt.knitrepo.RepositoryFormatKnit1',
 
2123
    help='Format using dirstate for working trees. '
 
2124
        'Compatible with bzr 0.8 and '
 
2125
        'above when accessed over the network. Introduced in bzr 0.15.',
 
2126
    branch_format='brzlib.branchfmt.fullhistory.BzrBranchFormat5',
 
2127
    tree_format='brzlib.workingtree_4.WorkingTreeFormat4',
 
2128
    hidden=True,
 
2129
    deprecated=True)
 
2130
register_metadir(controldir.format_registry, 'dirstate-tags',
 
2131
    'brzlib.repofmt.knitrepo.RepositoryFormatKnit1',
 
2132
    help='Variant of dirstate with support for tags. '
 
2133
        'Introduced in bzr 0.15.',
 
2134
    branch_format='brzlib.branch.BzrBranchFormat6',
 
2135
    tree_format='brzlib.workingtree_4.WorkingTreeFormat4',
 
2136
    hidden=True,
 
2137
    deprecated=True)
 
2138
register_metadir(controldir.format_registry, 'rich-root',
 
2139
    'brzlib.repofmt.knitrepo.RepositoryFormatKnit4',
 
2140
    help='Variant of dirstate with better handling of tree roots. '
 
2141
        'Introduced in bzr 1.0',
 
2142
    branch_format='brzlib.branch.BzrBranchFormat6',
 
2143
    tree_format='brzlib.workingtree_4.WorkingTreeFormat4',
 
2144
    hidden=True,
 
2145
    deprecated=True)
 
2146
register_metadir(controldir.format_registry, 'dirstate-with-subtree',
 
2147
    'brzlib.repofmt.knitrepo.RepositoryFormatKnit3',
 
2148
    help='Variant of dirstate with support for nested trees. '
 
2149
         'Introduced in 0.15.',
 
2150
    branch_format='brzlib.branch.BzrBranchFormat6',
 
2151
    tree_format='brzlib.workingtree_4.WorkingTreeFormat4',
 
2152
    experimental=True,
 
2153
    hidden=True,
 
2154
    )
 
2155
register_metadir(controldir.format_registry, 'pack-0.92',
 
2156
    'brzlib.repofmt.knitpack_repo.RepositoryFormatKnitPack1',
 
2157
    help='Pack-based format used in 1.x series. Introduced in 0.92. '
 
2158
        'Interoperates with bzr repositories before 0.92 but cannot be '
 
2159
        'read by bzr < 0.92. '
 
2160
        ,
 
2161
    branch_format='brzlib.branch.BzrBranchFormat6',
 
2162
    tree_format='brzlib.workingtree_4.WorkingTreeFormat4',
 
2163
    deprecated=True,
 
2164
    )
 
2165
register_metadir(controldir.format_registry, 'pack-0.92-subtree',
 
2166
    'brzlib.repofmt.knitpack_repo.RepositoryFormatKnitPack3',
 
2167
    help='Pack-based format used in 1.x series, with subtree support. '
 
2168
        'Introduced in 0.92. Interoperates with '
 
2169
        'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
 
2170
        ,
 
2171
    branch_format='brzlib.branch.BzrBranchFormat6',
 
2172
    tree_format='brzlib.workingtree_4.WorkingTreeFormat4',
 
2173
    hidden=True,
 
2174
    deprecated=True,
 
2175
    experimental=True,
 
2176
    )
 
2177
register_metadir(controldir.format_registry, 'rich-root-pack',
 
2178
    'brzlib.repofmt.knitpack_repo.RepositoryFormatKnitPack4',
 
2179
    help='A variant of pack-0.92 that supports rich-root data '
 
2180
         '(needed for bzr-svn and bzr-git). Introduced in 1.0.',
 
2181
    branch_format='brzlib.branch.BzrBranchFormat6',
 
2182
    tree_format='brzlib.workingtree_4.WorkingTreeFormat4',
 
2183
    hidden=True,
 
2184
    deprecated=True,
 
2185
    )
 
2186
register_metadir(controldir.format_registry, '1.6',
 
2187
    'brzlib.repofmt.knitpack_repo.RepositoryFormatKnitPack5',
 
2188
    help='A format that allows a branch to indicate that there is another '
 
2189
         '(stacked) repository that should be used to access data that is '
 
2190
         'not present locally.',
 
2191
    branch_format='brzlib.branch.BzrBranchFormat7',
 
2192
    tree_format='brzlib.workingtree_4.WorkingTreeFormat4',
 
2193
    hidden=True,
 
2194
    deprecated=True,
 
2195
    )
 
2196
register_metadir(controldir.format_registry, '1.6.1-rich-root',
 
2197
    'brzlib.repofmt.knitpack_repo.RepositoryFormatKnitPack5RichRoot',
 
2198
    help='A variant of 1.6 that supports rich-root data '
 
2199
         '(needed for bzr-svn and bzr-git).',
 
2200
    branch_format='brzlib.branch.BzrBranchFormat7',
 
2201
    tree_format='brzlib.workingtree_4.WorkingTreeFormat4',
 
2202
    hidden=True,
 
2203
    deprecated=True,
 
2204
    )
 
2205
register_metadir(controldir.format_registry, '1.9',
 
2206
    'brzlib.repofmt.knitpack_repo.RepositoryFormatKnitPack6',
 
2207
    help='A repository format using B+tree indexes. These indexes '
 
2208
         'are smaller in size, have smarter caching and provide faster '
 
2209
         'performance for most operations.',
 
2210
    branch_format='brzlib.branch.BzrBranchFormat7',
 
2211
    tree_format='brzlib.workingtree_4.WorkingTreeFormat4',
 
2212
    hidden=True,
 
2213
    deprecated=True,
 
2214
    )
 
2215
register_metadir(controldir.format_registry, '1.9-rich-root',
 
2216
    'brzlib.repofmt.knitpack_repo.RepositoryFormatKnitPack6RichRoot',
 
2217
    help='A variant of 1.9 that supports rich-root data '
 
2218
         '(needed for bzr-svn and bzr-git).',
 
2219
    branch_format='brzlib.branch.BzrBranchFormat7',
 
2220
    tree_format='brzlib.workingtree_4.WorkingTreeFormat4',
 
2221
    hidden=True,
 
2222
    deprecated=True,
 
2223
    )
 
2224
register_metadir(controldir.format_registry, '1.14',
 
2225
    'brzlib.repofmt.knitpack_repo.RepositoryFormatKnitPack6',
 
2226
    help='A working-tree format that supports content filtering.',
 
2227
    branch_format='brzlib.branch.BzrBranchFormat7',
 
2228
    tree_format='brzlib.workingtree_4.WorkingTreeFormat5',
 
2229
    hidden=True,
 
2230
    deprecated=True,
 
2231
    )
 
2232
register_metadir(controldir.format_registry, '1.14-rich-root',
 
2233
    'brzlib.repofmt.knitpack_repo.RepositoryFormatKnitPack6RichRoot',
 
2234
    help='A variant of 1.14 that supports rich-root data '
 
2235
         '(needed for bzr-svn and bzr-git).',
 
2236
    branch_format='brzlib.branch.BzrBranchFormat7',
 
2237
    tree_format='brzlib.workingtree_4.WorkingTreeFormat5',
 
2238
    hidden=True,
 
2239
    deprecated=True,
 
2240
    )
 
2241
# The following un-numbered 'development' formats should always just be aliases.
 
2242
register_metadir(controldir.format_registry, 'development-subtree',
 
2243
    'brzlib.repofmt.groupcompress_repo.RepositoryFormat2aSubtree',
 
2244
    help='Current development format, subtree variant. Can convert data to and '
 
2245
        'from pack-0.92-subtree (and anything compatible with '
 
2246
        'pack-0.92-subtree) format repositories. Repositories and branches in '
 
2247
        'this format can only be read by bzr.dev. Please read '
 
2248
        'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
 
2249
        'before use.',
 
2250
    branch_format='brzlib.branch.BzrBranchFormat7',
 
2251
    tree_format='brzlib.workingtree_4.WorkingTreeFormat6',
 
2252
    experimental=True,
 
2253
    hidden=True,
 
2254
    alias=False, # Restore to being an alias when an actual development subtree format is added
 
2255
                 # This current non-alias status is simply because we did not introduce a
 
2256
                 # chk based subtree format.
 
2257
    )
 
2258
register_metadir(controldir.format_registry, 'development5-subtree',
 
2259
    'brzlib.repofmt.knitpack_repo.RepositoryFormatPackDevelopment2Subtree',
 
2260
    help='Development format, subtree variant. Can convert data to and '
 
2261
        'from pack-0.92-subtree (and anything compatible with '
 
2262
        'pack-0.92-subtree) format repositories. Repositories and branches in '
 
2263
        'this format can only be read by bzr.dev. Please read '
 
2264
        'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
 
2265
        'before use.',
 
2266
    branch_format='brzlib.branch.BzrBranchFormat7',
 
2267
    tree_format='brzlib.workingtree_4.WorkingTreeFormat6',
 
2268
    experimental=True,
 
2269
    hidden=True,
 
2270
    alias=False,
 
2271
    )
 
2272
 
 
2273
register_metadir(controldir.format_registry, 'development-colo',
 
2274
    'brzlib.repofmt.groupcompress_repo.RepositoryFormat2a',
 
2275
    help='The 2a format with experimental support for colocated branches.\n',
 
2276
    branch_format='brzlib.branch.BzrBranchFormat7',
 
2277
    tree_format='brzlib.workingtree_4.WorkingTreeFormat6',
 
2278
    experimental=True,
 
2279
    bzrdir_format=BzrDirMetaFormat1Colo,
 
2280
    )
 
2281
 
 
2282
 
 
2283
# And the development formats above will have aliased one of the following:
 
2284
 
 
2285
# Finally, the current format.
 
2286
register_metadir(controldir.format_registry, '2a',
 
2287
    'brzlib.repofmt.groupcompress_repo.RepositoryFormat2a',
 
2288
    help='Format for the bzr 2.0 series.\n'
 
2289
        'Uses group-compress storage.\n'
 
2290
        'Provides rich roots which are a one-way transition.\n',
 
2291
        # 'storage in packs, 255-way hashed CHK inventory, bencode revision, group compress, '
 
2292
        # 'rich roots. Supported by bzr 1.16 and later.',
 
2293
    branch_format='brzlib.branch.BzrBranchFormat7',
 
2294
    tree_format='brzlib.workingtree_4.WorkingTreeFormat6',
 
2295
    experimental=False,
 
2296
    )
 
2297
 
 
2298
# The following format should be an alias for the rich root equivalent 
 
2299
# of the default format
 
2300
register_metadir(controldir.format_registry, 'default-rich-root',
 
2301
    'brzlib.repofmt.groupcompress_repo.RepositoryFormat2a',
 
2302
    branch_format='brzlib.branch.BzrBranchFormat7',
 
2303
    tree_format='brzlib.workingtree_4.WorkingTreeFormat6',
 
2304
    alias=True,
 
2305
    hidden=True,
 
2306
    help='Same as 2a.')
 
2307
 
 
2308
# The current format that is made on 'bzr init'.
 
2309
format_name = config.GlobalStack().get('default_format')
 
2310
controldir.format_registry.set_default(format_name)
 
2311
 
 
2312
# XXX 2010-08-20 JRV: There is still a lot of code relying on
 
2313
# brzlib.bzrdir.format_registry existing. When BzrDir.create/BzrDir.open/etc
 
2314
# get changed to ControlDir.create/ControlDir.open/etc this should be removed.
 
2315
format_registry = controldir.format_registry