/brz/remove-bazaar

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

« back to all changes in this revision

Viewing changes to bzrlib/bzrdir.py

  • Committer: John Arbash Meinel
  • Date: 2011-04-22 14:12:22 UTC
  • mfrom: (5809 +trunk)
  • mto: This revision was merged to the branch mainline in revision 5836.
  • Revision ID: john@arbash-meinel.com-20110422141222-nx2j0hbkihcb8j16
Merge newer bzr.dev and resolve conflicts.
Try to write some documentation about how the _dirblock_state works.
Fix up the tests so that they pass again.

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
 
28
28
import sys
29
29
 
30
 
from ..lazy_import import lazy_import
 
30
from bzrlib.lazy_import import lazy_import
31
31
lazy_import(globals(), """
32
 
import contextlib
33
 
 
34
 
from breezy import (
 
32
import bzrlib
 
33
from bzrlib import (
35
34
    branch as _mod_branch,
 
35
    cleanup,
 
36
    config,
 
37
    controldir,
 
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,
44
51
    win32utils,
45
 
    )
46
 
from breezy.bzr import (
47
 
    branch as _mod_bzrbranch,
48
 
    fetch,
49
 
    remote,
50
 
    vf_search,
51
 
    workingtree_3,
 
52
    workingtree,
52
53
    workingtree_4,
53
54
    )
54
 
from breezy.bzr import fullhistory as fullhistorybranch
55
 
from breezy.bzr import knitpack_repo
56
 
from breezy.transport import (
 
55
from bzrlib.repofmt import knitpack_repo
 
56
from bzrlib.transport import (
57
57
    do_catching_redirections,
58
58
    local,
59
59
    )
60
 
from breezy.i18n import gettext
61
60
""")
62
61
 
63
 
from ..trace import (
 
62
from bzrlib.trace import (
64
63
    mutter,
65
64
    note,
66
 
    warning,
67
 
    )
68
 
 
69
 
from .. import (
70
 
    config,
71
 
    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
 
65
    )
 
66
 
 
67
from bzrlib import (
 
68
    hooks,
 
69
    registry,
 
70
    )
 
71
from bzrlib.symbol_versioning import (
 
72
    deprecated_in,
 
73
    deprecated_method,
 
74
    )
91
75
 
92
76
 
93
77
class BzrDir(controldir.ControlDir):
129
113
 
130
114
    def check_conversion_target(self, target_format):
131
115
        """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
 
116
        # The only current restriction is that the repository content can be 
133
117
        # fetched compatibly with the target.
134
118
        target_repo_format = target_format.repository_format
135
119
        try:
140
124
            pass
141
125
 
142
126
    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,
145
 
                           tag_selector=None):
 
127
        force_new_repo=False, preserve_stacking=False, stacked_on=None,
 
128
        create_prefix=False, use_existing_dir=True, no_tree=False):
146
129
        """Clone this bzrdir and its contents to transport verbatim.
147
130
 
148
131
        :param transport: The transport for the location to produce the clone
172
155
            local_repo = self.find_repository()
173
156
        except errors.NoRepositoryPresent:
174
157
            local_repo = None
175
 
        local_branches = self.get_branches()
176
158
        try:
177
 
            local_active_branch = local_branches['']
178
 
        except KeyError:
179
 
            pass
 
159
            local_branch = self.open_branch()
 
160
        except errors.NotBranchError:
 
161
            local_branch = None
180
162
        else:
181
163
            # enable fallbacks when branch is not a branch reference
182
 
            if local_active_branch.repository.has_same_location(local_repo):
183
 
                local_repo = local_active_branch.repository
 
164
            if local_branch.repository.has_same_location(local_repo):
 
165
                local_repo = local_branch.repository
184
166
            if preserve_stacking:
185
167
                try:
186
 
                    stacked_on = local_active_branch.get_stacked_on_url()
187
 
                except (_mod_branch.UnstackableBranchFormat,
 
168
                    stacked_on = local_branch.get_stacked_on_url()
 
169
                except (errors.UnstackableBranchFormat,
188
170
                        errors.UnstackableRepositoryFormat,
189
171
                        errors.NotStacked):
190
172
                    pass
192
174
        # we should look up the policy needs first, or just use it as a hint,
193
175
        # or something.
194
176
        if local_repo:
195
 
            make_working_trees = (local_repo.make_working_trees() and
196
 
                                  not no_tree)
 
177
            make_working_trees = local_repo.make_working_trees() and not no_tree
197
178
            want_shared = local_repo.is_shared()
198
179
            repo_format_name = format.repository_format.network_name()
199
180
        else:
202
183
            repo_format_name = None
203
184
 
204
185
        result_repo, result, require_stacking, repository_policy = \
205
 
            format.initialize_on_transport_ex(
206
 
                transport, use_existing_dir=use_existing_dir,
207
 
                create_prefix=create_prefix, force_new_repo=force_new_repo,
208
 
                stacked_on=stacked_on, stack_on_pwd=self.root_transport.base,
209
 
                repo_format_name=repo_format_name,
210
 
                make_working_trees=make_working_trees, shared_repo=want_shared)
 
186
            format.initialize_on_transport_ex(transport,
 
187
            use_existing_dir=use_existing_dir, create_prefix=create_prefix,
 
188
            force_new_repo=force_new_repo, stacked_on=stacked_on,
 
189
            stack_on_pwd=self.root_transport.base,
 
190
            repo_format_name=repo_format_name,
 
191
            make_working_trees=make_working_trees, shared_repo=want_shared)
211
192
        if repo_format_name:
212
193
            try:
213
194
                # If the result repository is in the same place as the
217
198
                # revision_id then we can use the pending-ancestry-result which
218
199
                # does not require traversing all of history to describe it.
219
200
                if (result_repo.user_url == result.user_url
220
 
                    and not require_stacking
221
 
                        and revision_id is not None):
222
 
                    fetch_spec = vf_search.PendingAncestryResult(
 
201
                    and not require_stacking and
 
202
                    revision_id is not None):
 
203
                    fetch_spec = graph.PendingAncestryResult(
223
204
                        [revision_id], local_repo)
224
205
                    result_repo.fetch(local_repo, fetch_spec=fetch_spec)
225
206
                else:
232
213
        # 1 if there is a branch present
233
214
        #   make sure its content is available in the target repository
234
215
        #   clone it.
235
 
        for name, local_branch in local_branches.items():
236
 
            local_branch.clone(
237
 
                result, revision_id=(None if name != '' else revision_id),
238
 
                repository_policy=repository_policy,
239
 
                name=name, tag_selector=tag_selector)
 
216
        if local_branch is not None:
 
217
            result_branch = local_branch.clone(result, revision_id=revision_id,
 
218
                repository_policy=repository_policy)
240
219
        try:
241
220
            # Cheaper to check if the target is not local, than to try making
242
221
            # the tree and fail.
243
222
            result.root_transport.local_abspath('.')
244
223
            if result_repo is None or result_repo.make_working_trees():
245
 
                self.open_workingtree().clone(result, revision_id=revision_id)
 
224
                self.open_workingtree().clone(result)
246
225
        except (errors.NoWorkingTree, errors.NotLocalUrl):
247
226
            pass
248
227
        return result
253
232
        t = _mod_transport.get_transport(url)
254
233
        t.ensure_base()
255
234
 
 
235
    @staticmethod
 
236
    def find_bzrdirs(transport, evaluate=None, list_current=None):
 
237
        """Find bzrdirs recursively from current location.
 
238
 
 
239
        This is intended primarily as a building block for more sophisticated
 
240
        functionality, like finding trees under a directory, or finding
 
241
        branches that use a given repository.
 
242
        :param evaluate: An optional callable that yields recurse, value,
 
243
            where recurse controls whether this bzrdir is recursed into
 
244
            and value is the value to yield.  By default, all bzrdirs
 
245
            are recursed into, and the return value is the bzrdir.
 
246
        :param list_current: if supplied, use this function to list the current
 
247
            directory, instead of Transport.list_dir
 
248
        :return: a generator of found bzrdirs, or whatever evaluate returns.
 
249
        """
 
250
        if list_current is None:
 
251
            def list_current(transport):
 
252
                return transport.list_dir('')
 
253
        if evaluate is None:
 
254
            def evaluate(bzrdir):
 
255
                return True, bzrdir
 
256
 
 
257
        pending = [transport]
 
258
        while len(pending) > 0:
 
259
            current_transport = pending.pop()
 
260
            recurse = True
 
261
            try:
 
262
                bzrdir = BzrDir.open_from_transport(current_transport)
 
263
            except (errors.NotBranchError, errors.PermissionDenied):
 
264
                pass
 
265
            else:
 
266
                recurse, value = evaluate(bzrdir)
 
267
                yield value
 
268
            try:
 
269
                subdirs = list_current(current_transport)
 
270
            except (errors.NoSuchFile, errors.PermissionDenied):
 
271
                continue
 
272
            if recurse:
 
273
                for subdir in sorted(subdirs, reverse=True):
 
274
                    pending.append(current_transport.clone(subdir))
 
275
 
 
276
    @staticmethod
 
277
    def find_branches(transport):
 
278
        """Find all branches under a transport.
 
279
 
 
280
        This will find all branches below the transport, including branches
 
281
        inside other branches.  Where possible, it will use
 
282
        Repository.find_branches.
 
283
 
 
284
        To list all the branches that use a particular Repository, see
 
285
        Repository.find_branches
 
286
        """
 
287
        def evaluate(bzrdir):
 
288
            try:
 
289
                repository = bzrdir.open_repository()
 
290
            except errors.NoRepositoryPresent:
 
291
                pass
 
292
            else:
 
293
                return False, ([], repository)
 
294
            return True, (bzrdir.list_branches(), None)
 
295
        ret = []
 
296
        for branches, repo in BzrDir.find_bzrdirs(transport,
 
297
                                                  evaluate=evaluate):
 
298
            if repo is not None:
 
299
                ret.extend(repo.find_branches())
 
300
            if branches is not None:
 
301
                ret.extend(branches)
 
302
        return ret
 
303
 
 
304
    @staticmethod
 
305
    def create_branch_and_repo(base, force_new_repo=False, format=None):
 
306
        """Create a new BzrDir, Branch and Repository at the url 'base'.
 
307
 
 
308
        This will use the current default BzrDirFormat unless one is
 
309
        specified, and use whatever
 
310
        repository format that that uses via bzrdir.create_branch and
 
311
        create_repository. If a shared repository is available that is used
 
312
        preferentially.
 
313
 
 
314
        The created Branch object is returned.
 
315
 
 
316
        :param base: The URL to create the branch at.
 
317
        :param force_new_repo: If True a new repository is always created.
 
318
        :param format: If supplied, the format of branch to create.  If not
 
319
            supplied, the default is used.
 
320
        """
 
321
        bzrdir = BzrDir.create(base, format)
 
322
        bzrdir._find_or_create_repository(force_new_repo)
 
323
        return bzrdir.create_branch()
 
324
 
256
325
    def determine_repository_policy(self, force_new_repo=False, stack_on=None,
257
326
                                    stack_on_pwd=None, require_stacking=False):
258
327
        """Return an object representing a policy to use.
283
352
            except errors.NoRepositoryPresent:
284
353
                repository = None
285
354
            else:
286
 
                if (found_bzrdir.user_url != self.user_url and
287
 
                        not repository.is_shared()):
 
355
                if (found_bzrdir.user_url != self.user_url 
 
356
                    and not repository.is_shared()):
288
357
                    # Don't look higher, can't use a higher shared repo.
289
358
                    repository = None
290
359
                    stop = True
293
362
            if not stop:
294
363
                return None, False
295
364
            if repository:
296
 
                return UseExistingRepository(
297
 
                    repository, stack_on, stack_on_pwd,
298
 
                    require_stacking=require_stacking), True
 
365
                return UseExistingRepository(repository, stack_on,
 
366
                    stack_on_pwd, require_stacking=require_stacking), True
299
367
            else:
300
 
                return CreateRepository(
301
 
                    self, stack_on, stack_on_pwd,
 
368
                return CreateRepository(self, stack_on, stack_on_pwd,
302
369
                    require_stacking=require_stacking), True
303
370
 
304
371
        if not force_new_repo:
308
375
                    return policy
309
376
            else:
310
377
                try:
311
 
                    return UseExistingRepository(
312
 
                        self.open_repository(), stack_on, stack_on_pwd,
 
378
                    return UseExistingRepository(self.open_repository(),
 
379
                        stack_on, stack_on_pwd,
313
380
                        require_stacking=require_stacking)
314
381
                except errors.NoRepositoryPresent:
315
382
                    pass
321
388
        policy = self.determine_repository_policy(force_new_repo)
322
389
        return policy.acquire_repository()[0]
323
390
 
324
 
    def _find_source_repo(self, exit_stack, source_branch):
 
391
    def _find_source_repo(self, add_cleanup, source_branch):
325
392
        """Find the source branch and repo for a sprout operation.
326
 
 
 
393
        
327
394
        This is helper intended for use by _sprout.
328
395
 
329
396
        :returns: (source_branch, source_repository).  Either or both may be
330
397
            None.  If not None, they will be read-locked (and their unlock(s)
331
 
            scheduled via the exit_stack param).
 
398
            scheduled via the add_cleanup param).
332
399
        """
333
400
        if source_branch is not None:
334
 
            exit_stack.enter_context(source_branch.lock_read())
 
401
            add_cleanup(source_branch.lock_read().unlock)
335
402
            return source_branch, source_branch.repository
336
403
        try:
337
404
            source_branch = self.open_branch()
343
410
            except errors.NoRepositoryPresent:
344
411
                source_repository = None
345
412
            else:
346
 
                exit_stack.enter_context(source_repository.lock_read())
 
413
                add_cleanup(source_repository.lock_read().unlock)
347
414
        else:
348
 
            exit_stack.enter_context(source_branch.lock_read())
 
415
            add_cleanup(source_branch.lock_read().unlock)
349
416
        return source_branch, source_repository
350
417
 
351
418
    def sprout(self, url, revision_id=None, force_new_repo=False,
352
419
               recurse='down', possible_transports=None,
353
420
               accelerator_tree=None, hardlink=False, stacked=False,
354
 
               source_branch=None, create_tree_if_local=True,
355
 
               lossy=False):
 
421
               source_branch=None, create_tree_if_local=True):
356
422
        """Create a copy of this controldir prepared for use as a new line of
357
423
        development.
358
424
 
365
431
 
366
432
        if revision_id is not None, then the clone operation may tune
367
433
            itself to download less data.
368
 
 
369
434
        :param accelerator_tree: A tree which can be used for retrieving file
370
435
            contents more quickly than the revision tree, i.e. a workingtree.
371
436
            The revision tree will be used for cases where accelerator_tree's
376
441
            location of this control directory.
377
442
        :param create_tree_if_local: If true, a working-tree will be created
378
443
            when working locally.
379
 
        :return: The created control directory
380
 
        """
381
 
        with contextlib.ExitStack() as stack:
382
 
            fetch_spec_factory = fetch.FetchSpecFactory()
383
 
            if revision_id is not None:
384
 
                fetch_spec_factory.add_revision_ids([revision_id])
385
 
                fetch_spec_factory.source_branch_stop_revision_id = revision_id
386
 
            if possible_transports is None:
387
 
                possible_transports = []
388
 
            else:
389
 
                possible_transports = list(possible_transports) + [
390
 
                    self.root_transport]
391
 
            target_transport = _mod_transport.get_transport(url,
392
 
                                                            possible_transports)
393
 
            target_transport.ensure_base()
394
 
            cloning_format = self.cloning_metadir(stacked)
395
 
            # Create/update the result branch
396
 
            try:
397
 
                result = controldir.ControlDir.open_from_transport(
398
 
                    target_transport)
399
 
            except errors.NotBranchError:
400
 
                result = cloning_format.initialize_on_transport(target_transport)
401
 
            source_branch, source_repository = self._find_source_repo(
402
 
                stack, source_branch)
403
 
            fetch_spec_factory.source_branch = source_branch
404
 
            # if a stacked branch wasn't requested, we don't create one
405
 
            # even if the origin was stacked
406
 
            if stacked and source_branch is not None:
407
 
                stacked_branch_url = self.root_transport.base
408
 
            else:
409
 
                stacked_branch_url = None
410
 
            repository_policy = result.determine_repository_policy(
411
 
                force_new_repo, stacked_branch_url, require_stacking=stacked)
412
 
            result_repo, is_new_repo = repository_policy.acquire_repository(
413
 
                possible_transports=possible_transports)
414
 
            stack.enter_context(result_repo.lock_write())
415
 
            fetch_spec_factory.source_repo = source_repository
416
 
            fetch_spec_factory.target_repo = result_repo
417
 
            if stacked or (len(result_repo._fallback_repositories) != 0):
418
 
                target_repo_kind = fetch.TargetRepoKinds.STACKED
419
 
            elif is_new_repo:
420
 
                target_repo_kind = fetch.TargetRepoKinds.EMPTY
421
 
            else:
422
 
                target_repo_kind = fetch.TargetRepoKinds.PREEXISTING
423
 
            fetch_spec_factory.target_repo_kind = target_repo_kind
424
 
            if source_repository is not None:
425
 
                fetch_spec = fetch_spec_factory.make_fetch_spec()
426
 
                result_repo.fetch(source_repository, fetch_spec=fetch_spec)
427
 
 
428
 
            if source_branch is None:
429
 
                # this is for sprouting a controldir without a branch; is that
430
 
                # actually useful?
431
 
                # Not especially, but it's part of the contract.
432
 
                result_branch = result.create_branch()
433
 
                if revision_id is not None:
434
 
                    result_branch.generate_revision_history(revision_id)
435
 
            else:
436
 
                result_branch = source_branch.sprout(
437
 
                    result, revision_id=revision_id,
438
 
                    repository_policy=repository_policy, repository=result_repo)
439
 
            mutter("created new branch %r" % (result_branch,))
440
 
 
441
 
            # Create/update the result working tree
442
 
            if (create_tree_if_local and not result.has_workingtree()
443
 
                    and isinstance(target_transport, local.LocalTransport)
444
 
                    and (result_repo is None or result_repo.make_working_trees())
445
 
                    and result.open_branch(
446
 
                        name="",
447
 
                        possible_transports=possible_transports).name == result_branch.name):
448
 
                wt = result.create_workingtree(
449
 
                    accelerator_tree=accelerator_tree, hardlink=hardlink,
450
 
                    from_branch=result_branch)
451
 
                with wt.lock_write():
452
 
                    if not wt.is_versioned(''):
453
 
                        try:
454
 
                            wt.set_root_id(self.open_workingtree.path2id(''))
455
 
                        except errors.NoWorkingTree:
456
 
                            pass
457
 
            else:
458
 
                wt = None
459
 
            if recurse == 'down':
460
 
                tree = None
461
 
                if wt is not None:
462
 
                    tree = wt
463
 
                    basis = tree.basis_tree()
464
 
                    stack.enter_context(basis.lock_read())
465
 
                elif result_branch is not None:
466
 
                    basis = tree = result_branch.basis_tree()
467
 
                elif source_branch is not None:
468
 
                    basis = tree = source_branch.basis_tree()
469
 
                if tree is not None:
470
 
                    stack.enter_context(tree.lock_read())
471
 
                    subtrees = tree.iter_references()
472
 
                else:
473
 
                    subtrees = []
474
 
                for path in subtrees:
475
 
                    target = urlutils.join(url, urlutils.escape(path))
476
 
                    sublocation = tree.reference_parent(
477
 
                        path, branch=result_branch,
478
 
                        possible_transports=possible_transports)
479
 
                    if sublocation is None:
480
 
                        warning(
481
 
                            'Ignoring nested tree %s, parent location unknown.',
482
 
                            path)
483
 
                        continue
484
 
                    sublocation.controldir.sprout(
485
 
                        target, basis.get_reference_revision(path),
486
 
                        force_new_repo=force_new_repo, recurse=recurse,
487
 
                        stacked=stacked)
488
 
            return result
 
444
        """
 
445
        operation = cleanup.OperationWithCleanups(self._sprout)
 
446
        return operation.run(url, revision_id=revision_id,
 
447
            force_new_repo=force_new_repo, recurse=recurse,
 
448
            possible_transports=possible_transports,
 
449
            accelerator_tree=accelerator_tree, hardlink=hardlink,
 
450
            stacked=stacked, source_branch=source_branch,
 
451
            create_tree_if_local=create_tree_if_local)
 
452
 
 
453
    def _sprout(self, op, url, revision_id=None, force_new_repo=False,
 
454
               recurse='down', possible_transports=None,
 
455
               accelerator_tree=None, hardlink=False, stacked=False,
 
456
               source_branch=None, create_tree_if_local=True):
 
457
        add_cleanup = op.add_cleanup
 
458
        fetch_spec_factory = fetch.FetchSpecFactory()
 
459
        if revision_id is not None:
 
460
            fetch_spec_factory.add_revision_ids([revision_id])
 
461
            fetch_spec_factory.source_branch_stop_revision_id = revision_id
 
462
        target_transport = _mod_transport.get_transport(url,
 
463
            possible_transports)
 
464
        target_transport.ensure_base()
 
465
        cloning_format = self.cloning_metadir(stacked)
 
466
        # Create/update the result branch
 
467
        result = cloning_format.initialize_on_transport(target_transport)
 
468
        source_branch, source_repository = self._find_source_repo(
 
469
            add_cleanup, source_branch)
 
470
        fetch_spec_factory.source_branch = source_branch
 
471
        # if a stacked branch wasn't requested, we don't create one
 
472
        # even if the origin was stacked
 
473
        if stacked and source_branch is not None:
 
474
            stacked_branch_url = self.root_transport.base
 
475
        else:
 
476
            stacked_branch_url = None
 
477
        repository_policy = result.determine_repository_policy(
 
478
            force_new_repo, stacked_branch_url, require_stacking=stacked)
 
479
        result_repo, is_new_repo = repository_policy.acquire_repository()
 
480
        add_cleanup(result_repo.lock_write().unlock)
 
481
        fetch_spec_factory.source_repo = source_repository
 
482
        fetch_spec_factory.target_repo = result_repo
 
483
        if stacked or (len(result_repo._fallback_repositories) != 0):
 
484
            target_repo_kind = fetch.TargetRepoKinds.STACKED
 
485
        elif is_new_repo:
 
486
            target_repo_kind = fetch.TargetRepoKinds.EMPTY
 
487
        else:
 
488
            target_repo_kind = fetch.TargetRepoKinds.PREEXISTING
 
489
        fetch_spec_factory.target_repo_kind = target_repo_kind
 
490
        if source_repository is not None:
 
491
            fetch_spec = fetch_spec_factory.make_fetch_spec()
 
492
            result_repo.fetch(source_repository, fetch_spec=fetch_spec)
 
493
 
 
494
        if source_branch is None:
 
495
            # this is for sprouting a controldir without a branch; is that
 
496
            # actually useful?
 
497
            # Not especially, but it's part of the contract.
 
498
            result_branch = result.create_branch()
 
499
        else:
 
500
            result_branch = source_branch.sprout(result,
 
501
                revision_id=revision_id, repository_policy=repository_policy,
 
502
                repository=result_repo)
 
503
        mutter("created new branch %r" % (result_branch,))
 
504
 
 
505
        # Create/update the result working tree
 
506
        if (create_tree_if_local and
 
507
            isinstance(target_transport, local.LocalTransport) and
 
508
            (result_repo is None or result_repo.make_working_trees())):
 
509
            wt = result.create_workingtree(accelerator_tree=accelerator_tree,
 
510
                hardlink=hardlink, from_branch=result_branch)
 
511
            wt.lock_write()
 
512
            try:
 
513
                if wt.path2id('') is None:
 
514
                    try:
 
515
                        wt.set_root_id(self.open_workingtree.get_root_id())
 
516
                    except errors.NoWorkingTree:
 
517
                        pass
 
518
            finally:
 
519
                wt.unlock()
 
520
        else:
 
521
            wt = None
 
522
        if recurse == 'down':
 
523
            basis = None
 
524
            if wt is not None:
 
525
                basis = wt.basis_tree()
 
526
            elif result_branch is not None:
 
527
                basis = result_branch.basis_tree()
 
528
            elif source_branch is not None:
 
529
                basis = source_branch.basis_tree()
 
530
            if basis is not None:
 
531
                add_cleanup(basis.lock_read().unlock)
 
532
                subtrees = basis.iter_references()
 
533
            else:
 
534
                subtrees = []
 
535
            for path, file_id in subtrees:
 
536
                target = urlutils.join(url, urlutils.escape(path))
 
537
                sublocation = source_branch.reference_parent(file_id, path)
 
538
                sublocation.bzrdir.sprout(target,
 
539
                    basis.get_reference_revision(file_id, path),
 
540
                    force_new_repo=force_new_repo, recurse=recurse,
 
541
                    stacked=stacked)
 
542
        return result
 
543
 
 
544
 
 
545
 
 
546
    @staticmethod
 
547
    def create_branch_convenience(base, force_new_repo=False,
 
548
                                  force_new_tree=None, format=None,
 
549
                                  possible_transports=None):
 
550
        """Create a new BzrDir, Branch and Repository at the url 'base'.
 
551
 
 
552
        This is a convenience function - it will use an existing repository
 
553
        if possible, can be told explicitly whether to create a working tree or
 
554
        not.
 
555
 
 
556
        This will use the current default BzrDirFormat unless one is
 
557
        specified, and use whatever
 
558
        repository format that that uses via bzrdir.create_branch and
 
559
        create_repository. If a shared repository is available that is used
 
560
        preferentially. Whatever repository is used, its tree creation policy
 
561
        is followed.
 
562
 
 
563
        The created Branch object is returned.
 
564
        If a working tree cannot be made due to base not being a file:// url,
 
565
        no error is raised unless force_new_tree is True, in which case no
 
566
        data is created on disk and NotLocalUrl is raised.
 
567
 
 
568
        :param base: The URL to create the branch at.
 
569
        :param force_new_repo: If True a new repository is always created.
 
570
        :param force_new_tree: If True or False force creation of a tree or
 
571
                               prevent such creation respectively.
 
572
        :param format: Override for the bzrdir format to create.
 
573
        :param possible_transports: An optional reusable transports list.
 
574
        """
 
575
        if force_new_tree:
 
576
            # check for non local urls
 
577
            t = _mod_transport.get_transport(base, possible_transports)
 
578
            if not isinstance(t, local.LocalTransport):
 
579
                raise errors.NotLocalUrl(base)
 
580
        bzrdir = BzrDir.create(base, format, possible_transports)
 
581
        repo = bzrdir._find_or_create_repository(force_new_repo)
 
582
        result = bzrdir.create_branch()
 
583
        if force_new_tree or (repo.make_working_trees() and
 
584
                              force_new_tree is None):
 
585
            try:
 
586
                bzrdir.create_workingtree()
 
587
            except errors.NotLocalUrl:
 
588
                pass
 
589
        return result
 
590
 
 
591
    @staticmethod
 
592
    def create_standalone_workingtree(base, format=None):
 
593
        """Create a new BzrDir, WorkingTree, Branch and Repository at 'base'.
 
594
 
 
595
        'base' must be a local path or a file:// url.
 
596
 
 
597
        This will use the current default BzrDirFormat unless one is
 
598
        specified, and use whatever
 
599
        repository format that that uses for bzrdirformat.create_workingtree,
 
600
        create_branch and create_repository.
 
601
 
 
602
        :param format: Override for the bzrdir format to create.
 
603
        :return: The WorkingTree object.
 
604
        """
 
605
        t = _mod_transport.get_transport(base)
 
606
        if not isinstance(t, local.LocalTransport):
 
607
            raise errors.NotLocalUrl(base)
 
608
        bzrdir = BzrDir.create_branch_and_repo(base,
 
609
                                               force_new_repo=True,
 
610
                                               format=format).bzrdir
 
611
        return bzrdir.create_workingtree()
 
612
 
 
613
    @deprecated_method(deprecated_in((2, 3, 0)))
 
614
    def generate_backup_name(self, base):
 
615
        return self._available_backup_name(base)
489
616
 
490
617
    def _available_backup_name(self, base):
491
618
        """Find a non-existing backup file name based on base.
492
619
 
493
 
        See breezy.osutils.available_backup_name about race conditions.
 
620
        See bzrlib.osutils.available_backup_name about race conditions.
494
621
        """
495
622
        return osutils.available_backup_name(base, self.root_transport.has)
496
623
 
500
627
        :return: Tuple with old path name and new path name
501
628
        """
502
629
 
503
 
        with ui.ui_factory.nested_progress_bar():
 
630
        pb = ui.ui_factory.nested_progress_bar()
 
631
        try:
504
632
            old_path = self.root_transport.abspath('.bzr')
505
633
            backup_dir = self._available_backup_name('backup.bzr')
506
634
            new_path = self.root_transport.abspath(backup_dir)
507
 
            ui.ui_factory.note(
508
 
                gettext('making backup of {0}\n  to {1}').format(
509
 
                    urlutils.unescape_for_display(old_path, 'utf-8'),
510
 
                    urlutils.unescape_for_display(new_path, 'utf-8')))
 
635
            ui.ui_factory.note('making backup of %s\n  to %s'
 
636
                               % (old_path, new_path,))
511
637
            self.root_transport.copy_tree('.bzr', backup_dir)
512
638
            return (old_path, new_path)
 
639
        finally:
 
640
            pb.finished()
513
641
 
514
642
    def retire_bzrdir(self, limit=10000):
515
643
        """Permanently disable the bzrdir.
521
649
        in use.
522
650
        :param limit: number of times to retry
523
651
        """
524
 
        i = 0
 
652
        i  = 0
525
653
        while True:
526
654
            try:
527
655
                to_path = '.bzr.retired.%d' % i
528
656
                self.root_transport.rename('.bzr', to_path)
529
 
                note(gettext("renamed {0} to {1}").format(
530
 
                    self.root_transport.abspath('.bzr'), to_path))
 
657
                note("renamed %s to %s"
 
658
                    % (self.root_transport.abspath('.bzr'), to_path))
531
659
                return
532
660
            except (errors.TransportError, IOError, errors.PathError):
533
661
                i += 1
560
688
                return None
561
689
            # find the next containing bzrdir
562
690
            try:
563
 
                found_bzrdir = self.open_containing_from_transport(
 
691
                found_bzrdir = BzrDir.open_containing_from_transport(
564
692
                    next_transport)[0]
565
693
            except errors.NotBranchError:
566
694
                return None
611
739
            # directories and files are read-write for this user. This is
612
740
            # mostly a workaround for filesystems which lie about being able to
613
741
            # write to a directory (cygwin & win32)
614
 
            if (st.st_mode & 0o7777 == 00000):
 
742
            if (st.st_mode & 07777 == 00000):
615
743
                # FTP allows stat but does not return dir/file modes
616
744
                self._dir_mode = None
617
745
                self._file_mode = None
618
746
            else:
619
 
                self._dir_mode = (st.st_mode & 0o7777) | 0o0700
 
747
                self._dir_mode = (st.st_mode & 07777) | 00700
620
748
                # Remove the sticky and execute bits for files
621
 
                self._file_mode = self._dir_mode & ~0o7111
 
749
                self._file_mode = self._dir_mode & ~07111
622
750
 
623
751
    def _get_file_mode(self):
624
752
        """Return Unix mode for newly created files, or None.
652
780
        :param _transport: the transport this dir is based at.
653
781
        """
654
782
        self._format = _format
655
 
        # these are also under the more standard names of
 
783
        # these are also under the more standard names of 
656
784
        # control_transport and user_transport
657
785
        self.transport = _transport.clone('.bzr')
658
786
        self.root_transport = _transport
659
787
        self._mode_check_done = False
660
788
 
661
 
    @property
 
789
    @property 
662
790
    def user_transport(self):
663
791
        return self.root_transport
664
792
 
666
794
    def control_transport(self):
667
795
        return self.transport
668
796
 
 
797
    def is_control_filename(self, filename):
 
798
        """True if filename is the name of a path which is reserved for bzrdir's.
 
799
 
 
800
        :param filename: A filename within the root transport of this bzrdir.
 
801
 
 
802
        This is true IF and ONLY IF the filename is part of the namespace reserved
 
803
        for bzr control dirs. Currently this is the '.bzr' directory in the root
 
804
        of the root_transport. 
 
805
        """
 
806
        # this might be better on the BzrDirFormat class because it refers to
 
807
        # all the possible bzrdir disk formats.
 
808
        # This method is tested via the workingtree is_control_filename tests-
 
809
        # it was extracted from WorkingTree.is_control_filename. If the method's
 
810
        # contract is extended beyond the current trivial implementation, please
 
811
        # add new tests for it to the appropriate place.
 
812
        return filename == '.bzr' or filename.startswith('.bzr/')
 
813
 
 
814
    @staticmethod
 
815
    def open_unsupported(base):
 
816
        """Open a branch which is not supported."""
 
817
        return BzrDir.open(base, _unsupported=True)
 
818
 
 
819
    @staticmethod
 
820
    def open(base, _unsupported=False, possible_transports=None):
 
821
        """Open an existing bzrdir, rooted at 'base' (url).
 
822
 
 
823
        :param _unsupported: a private parameter to the BzrDir class.
 
824
        """
 
825
        t = _mod_transport.get_transport(base, possible_transports)
 
826
        return BzrDir.open_from_transport(t, _unsupported=_unsupported)
 
827
 
 
828
    @staticmethod
 
829
    def open_from_transport(transport, _unsupported=False,
 
830
                            _server_formats=True):
 
831
        """Open a bzrdir within a particular directory.
 
832
 
 
833
        :param transport: Transport containing the bzrdir.
 
834
        :param _unsupported: private.
 
835
        """
 
836
        for hook in BzrDir.hooks['pre_open']:
 
837
            hook(transport)
 
838
        # Keep initial base since 'transport' may be modified while following
 
839
        # the redirections.
 
840
        base = transport.base
 
841
        def find_format(transport):
 
842
            return transport, controldir.ControlDirFormat.find_format(
 
843
                transport, _server_formats=_server_formats)
 
844
 
 
845
        def redirected(transport, e, redirection_notice):
 
846
            redirected_transport = transport._redirected_to(e.source, e.target)
 
847
            if redirected_transport is None:
 
848
                raise errors.NotBranchError(base)
 
849
            note('%s is%s redirected to %s',
 
850
                 transport.base, e.permanently, redirected_transport.base)
 
851
            return redirected_transport
 
852
 
 
853
        try:
 
854
            transport, format = do_catching_redirections(find_format,
 
855
                                                         transport,
 
856
                                                         redirected)
 
857
        except errors.TooManyRedirections:
 
858
            raise errors.NotBranchError(base)
 
859
 
 
860
        format.check_support_status(_unsupported)
 
861
        return format.open(transport, _found=True)
 
862
 
 
863
    @staticmethod
 
864
    def open_containing(url, possible_transports=None):
 
865
        """Open an existing branch which contains url.
 
866
 
 
867
        :param url: url to search from.
 
868
        See open_containing_from_transport for more detail.
 
869
        """
 
870
        transport = _mod_transport.get_transport(url, possible_transports)
 
871
        return BzrDir.open_containing_from_transport(transport)
 
872
 
 
873
    @staticmethod
 
874
    def open_containing_from_transport(a_transport):
 
875
        """Open an existing branch which contains a_transport.base.
 
876
 
 
877
        This probes for a branch at a_transport, and searches upwards from there.
 
878
 
 
879
        Basically we keep looking up until we find the control directory or
 
880
        run into the root.  If there isn't one, raises NotBranchError.
 
881
        If there is one and it is either an unrecognised format or an unsupported
 
882
        format, UnknownFormatError or UnsupportedFormatError are raised.
 
883
        If there is one, it is returned, along with the unused portion of url.
 
884
 
 
885
        :return: The BzrDir that contains the path, and a Unicode path
 
886
                for the rest of the URL.
 
887
        """
 
888
        # this gets the normalised url back. I.e. '.' -> the full path.
 
889
        url = a_transport.base
 
890
        while True:
 
891
            try:
 
892
                result = BzrDir.open_from_transport(a_transport)
 
893
                return result, urlutils.unescape(a_transport.relpath(url))
 
894
            except errors.NotBranchError, e:
 
895
                pass
 
896
            try:
 
897
                new_t = a_transport.clone('..')
 
898
            except errors.InvalidURLJoin:
 
899
                # reached the root, whatever that may be
 
900
                raise errors.NotBranchError(path=url)
 
901
            if new_t.base == a_transport.base:
 
902
                # reached the root, whatever that may be
 
903
                raise errors.NotBranchError(path=url)
 
904
            a_transport = new_t
 
905
 
 
906
    @classmethod
 
907
    def open_tree_or_branch(klass, location):
 
908
        """Return the branch and working tree at a location.
 
909
 
 
910
        If there is no tree at the location, tree will be None.
 
911
        If there is no branch at the location, an exception will be
 
912
        raised
 
913
        :return: (tree, branch)
 
914
        """
 
915
        bzrdir = klass.open(location)
 
916
        return bzrdir._get_tree_branch()
 
917
 
 
918
    @classmethod
 
919
    def open_containing_tree_or_branch(klass, location):
 
920
        """Return the branch and working tree contained by a location.
 
921
 
 
922
        Returns (tree, branch, relpath).
 
923
        If there is no tree at containing the location, tree will be None.
 
924
        If there is no branch containing the location, an exception will be
 
925
        raised
 
926
        relpath is the portion of the path that is contained by the branch.
 
927
        """
 
928
        bzrdir, relpath = klass.open_containing(location)
 
929
        tree, branch = bzrdir._get_tree_branch()
 
930
        return tree, branch, relpath
 
931
 
 
932
    @classmethod
 
933
    def open_containing_tree_branch_or_repository(klass, location):
 
934
        """Return the working tree, branch and repo contained by a location.
 
935
 
 
936
        Returns (tree, branch, repository, relpath).
 
937
        If there is no tree containing the location, tree will be None.
 
938
        If there is no branch containing the location, branch will be None.
 
939
        If there is no repository containing the location, repository will be
 
940
        None.
 
941
        relpath is the portion of the path that is contained by the innermost
 
942
        BzrDir.
 
943
 
 
944
        If no tree, branch or repository is found, a NotBranchError is raised.
 
945
        """
 
946
        bzrdir, relpath = klass.open_containing(location)
 
947
        try:
 
948
            tree, branch = bzrdir._get_tree_branch()
 
949
        except errors.NotBranchError:
 
950
            try:
 
951
                repo = bzrdir.find_repository()
 
952
                return None, None, repo, relpath
 
953
            except (errors.NoRepositoryPresent):
 
954
                raise errors.NotBranchError(location)
 
955
        return tree, branch, branch.repository, relpath
 
956
 
669
957
    def _cloning_metadir(self):
670
958
        """Produce a metadir suitable for cloning with.
671
959
 
678
966
                source_repository = branch.repository
679
967
                result_format._branch_format = branch._format
680
968
            except errors.NotBranchError:
 
969
                source_branch = None
681
970
                source_repository = self.open_repository()
682
971
        except errors.NoRepositoryPresent:
683
972
            source_repository = None
710
999
 
711
1000
        :require_stacking: If True, non-stackable formats will be upgraded
712
1001
            to similar stackable formats.
713
 
        :returns: a ControlDirFormat with all component formats either set
 
1002
        :returns: a BzrDirFormat with all component formats either set
714
1003
            appropriately or set to None if that component should not be
715
1004
            created.
716
1005
        """
722
1011
                return format
723
1012
            # We have a repository, so set a working tree? (Why? This seems to
724
1013
            # contradict the stated return value in the docstring).
725
 
            tree_format = (
726
 
                repository._format._matchingcontroldir.workingtree_format)
 
1014
            tree_format = repository._format._matchingbzrdir.workingtree_format
727
1015
            format.workingtree_format = tree_format.__class__()
728
1016
        if require_stacking:
729
1017
            format.require_stacking()
730
1018
        return format
731
1019
 
 
1020
    @classmethod
 
1021
    def create(cls, base, format=None, possible_transports=None):
 
1022
        """Create a new BzrDir at the url 'base'.
 
1023
 
 
1024
        :param format: If supplied, the format of branch to create.  If not
 
1025
            supplied, the default is used.
 
1026
        :param possible_transports: If supplied, a list of transports that
 
1027
            can be reused to share a remote connection.
 
1028
        """
 
1029
        if cls is not BzrDir:
 
1030
            raise AssertionError("BzrDir.create always creates the"
 
1031
                "default format, not one of %r" % cls)
 
1032
        t = _mod_transport.get_transport(base, possible_transports)
 
1033
        t.ensure_base()
 
1034
        if format is None:
 
1035
            format = controldir.ControlDirFormat.get_default_format()
 
1036
        return format.initialize_on_transport(t)
 
1037
 
732
1038
    def get_branch_transport(self, branch_format, name=None):
733
1039
        """Get the transport for use by branch format in this BzrDir.
734
1040
 
768
1074
        """
769
1075
        raise NotImplementedError(self.get_workingtree_transport)
770
1076
 
771
 
    @classmethod
772
 
    def create(cls, base, format=None, possible_transports=None):
773
 
        """Create a new BzrDir at the url 'base'.
774
 
 
775
 
        :param format: If supplied, the format of branch to create.  If not
776
 
            supplied, the default is used.
777
 
        :param possible_transports: If supplied, a list of transports that
778
 
            can be reused to share a remote connection.
 
1077
 
 
1078
class BzrDirHooks(hooks.Hooks):
 
1079
    """Hooks for BzrDir operations."""
 
1080
 
 
1081
    def __init__(self):
 
1082
        """Create the default hooks."""
 
1083
        hooks.Hooks.__init__(self, "bzrlib.bzrdir", "BzrDir.hooks")
 
1084
        self.add_hook('pre_open',
 
1085
            "Invoked before attempting to open a BzrDir with the transport "
 
1086
            "that the open will use.", (1, 14))
 
1087
        self.add_hook('post_repo_init',
 
1088
            "Invoked after a repository has been initialized. "
 
1089
            "post_repo_init is called with a "
 
1090
            "bzrlib.bzrdir.RepoInitHookParams.",
 
1091
            (2, 2))
 
1092
 
 
1093
# install the default hooks
 
1094
BzrDir.hooks = BzrDirHooks()
 
1095
 
 
1096
 
 
1097
class RepoInitHookParams(object):
 
1098
    """Object holding parameters passed to *_repo_init hooks.
 
1099
 
 
1100
    There are 4 fields that hooks may wish to access:
 
1101
 
 
1102
    :ivar repository: Repository created
 
1103
    :ivar format: Repository format
 
1104
    :ivar bzrdir: The bzrdir for the repository
 
1105
    :ivar shared: The repository is shared
 
1106
    """
 
1107
 
 
1108
    def __init__(self, repository, format, a_bzrdir, shared):
 
1109
        """Create a group of RepoInitHook parameters.
 
1110
 
 
1111
        :param repository: Repository created
 
1112
        :param format: Repository format
 
1113
        :param bzrdir: The bzrdir for the repository
 
1114
        :param shared: The repository is shared
779
1115
        """
780
 
        if cls is not BzrDir:
781
 
            raise AssertionError("BzrDir.create always creates the "
782
 
                                 "default format, not one of %r" % cls)
783
 
        return controldir.ControlDir.create(
784
 
            base, format=format, possible_transports=possible_transports)
 
1116
        self.repository = repository
 
1117
        self.format = format
 
1118
        self.bzrdir = a_bzrdir
 
1119
        self.shared = shared
 
1120
 
 
1121
    def __eq__(self, other):
 
1122
        return self.__dict__ == other.__dict__
785
1123
 
786
1124
    def __repr__(self):
787
 
        return "<%s at %r>" % (self.__class__.__name__, self.user_url)
788
 
 
789
 
    def update_feature_flags(self, updated_flags):
790
 
        """Update the features required by this bzrdir.
791
 
 
792
 
        :param updated_flags: Dictionary mapping feature names to necessities
793
 
            A necessity can be None to indicate the feature should be removed
794
 
        """
795
 
        self.control_files.lock_write()
796
 
        try:
797
 
            self._format._update_feature_flags(updated_flags)
798
 
            self.transport.put_bytes('branch-format', self._format.as_string())
799
 
        finally:
800
 
            self.control_files.unlock()
 
1125
        if self.repository:
 
1126
            return "<%s for %s>" % (self.__class__.__name__,
 
1127
                self.repository)
 
1128
        else:
 
1129
            return "<%s for %s>" % (self.__class__.__name__,
 
1130
                self.bzrdir)
801
1131
 
802
1132
 
803
1133
class BzrDirMeta1(BzrDir):
809
1139
    present within a BzrDir.
810
1140
    """
811
1141
 
812
 
    def _get_branch_path(self, name):
813
 
        """Obtain the branch path to use.
814
 
 
815
 
        This uses the API specified branch name first, and then falls back to
816
 
        the branch name specified in the URL. If neither of those is specified,
817
 
        it uses the default branch.
818
 
 
819
 
        :param name: Optional branch name to use
820
 
        :return: Relative path to branch
821
 
        """
822
 
        if name == "":
823
 
            return 'branch'
824
 
        return urlutils.join('branches', urlutils.escape(name))
825
 
 
826
 
    def _read_branch_list(self):
827
 
        """Read the branch list.
828
 
 
829
 
        :return: List of branch names.
830
 
        """
831
 
        try:
832
 
            f = self.control_transport.get('branch-list')
833
 
        except errors.NoSuchFile:
834
 
            return []
835
 
 
836
 
        ret = []
837
 
        try:
838
 
            for name in f:
839
 
                ret.append(name.rstrip(b"\n").decode('utf-8'))
840
 
        finally:
841
 
            f.close()
842
 
        return ret
843
 
 
844
 
    def _write_branch_list(self, branches):
845
 
        """Write out the branch list.
846
 
 
847
 
        :param branches: List of utf-8 branch names to write
848
 
        """
849
 
        self.transport.put_bytes(
850
 
            'branch-list',
851
 
            b"".join([name.encode('utf-8') + b"\n" for name in branches]))
852
 
 
853
 
    def __init__(self, _transport, _format):
854
 
        super(BzrDirMeta1, self).__init__(_transport, _format)
855
 
        self.control_files = lockable_files.LockableFiles(
856
 
            self.control_transport, self._format._lock_file_name,
857
 
            self._format._lock_class)
858
 
 
859
1142
    def can_convert_format(self):
860
1143
        """See BzrDir.can_convert_format()."""
861
1144
        return True
862
1145
 
863
 
    def create_branch(self, name=None, repository=None,
864
 
                      append_revisions_only=None):
865
 
        """See ControlDir.create_branch."""
866
 
        if name is None:
867
 
            name = self._get_selected_branch()
868
 
        return self._format.get_branch_format().initialize(
869
 
            self, name=name, repository=repository,
870
 
            append_revisions_only=append_revisions_only)
 
1146
    def create_branch(self, name=None, repository=None):
 
1147
        """See BzrDir.create_branch."""
 
1148
        return self._format.get_branch_format().initialize(self, name=name,
 
1149
                repository=repository)
871
1150
 
872
1151
    def destroy_branch(self, name=None):
873
 
        """See ControlDir.destroy_branch."""
874
 
        if name is None:
875
 
            name = self._get_selected_branch()
876
 
        path = self._get_branch_path(name)
877
 
        if name != u"":
878
 
            self.control_files.lock_write()
879
 
            try:
880
 
                branches = self._read_branch_list()
881
 
                try:
882
 
                    branches.remove(name)
883
 
                except ValueError:
884
 
                    raise errors.NotBranchError(name)
885
 
                self._write_branch_list(branches)
886
 
            finally:
887
 
                self.control_files.unlock()
888
 
        try:
889
 
            self.transport.delete_tree(path)
890
 
        except errors.NoSuchFile:
891
 
            raise errors.NotBranchError(
892
 
                path=urlutils.join(self.transport.base, path), controldir=self)
 
1152
        """See BzrDir.create_branch."""
 
1153
        if name is not None:
 
1154
            raise errors.NoColocatedBranchSupport(self)
 
1155
        self.transport.delete_tree('branch')
893
1156
 
894
1157
    def create_repository(self, shared=False):
895
1158
        """See BzrDir.create_repository."""
897
1160
 
898
1161
    def destroy_repository(self):
899
1162
        """See BzrDir.destroy_repository."""
900
 
        try:
901
 
            self.transport.delete_tree('repository')
902
 
        except errors.NoSuchFile:
903
 
            raise errors.NoRepositoryPresent(self)
 
1163
        self.transport.delete_tree('repository')
904
1164
 
905
1165
    def create_workingtree(self, revision_id=None, from_branch=None,
906
1166
                           accelerator_tree=None, hardlink=False):
917
1177
        # We ignore the conflicts returned by wt.revert since we're about to
918
1178
        # delete the wt metadata anyway, all that should be left here are
919
1179
        # detritus. But see bug #634470 about subtree .bzr dirs.
920
 
        wt.revert(old_tree=empty)
 
1180
        conflicts = wt.revert(old_tree=empty)
921
1181
        self.destroy_workingtree_metadata()
922
1182
 
923
1183
    def destroy_workingtree_metadata(self):
928
1188
 
929
1189
        This might be a synthetic object for e.g. RemoteBranch and SVN.
930
1190
        """
931
 
        from .branch import BranchFormatMetadir
932
 
        return BranchFormatMetadir.find_format(self, name=name)
 
1191
        from bzrlib.branch import BranchFormat
 
1192
        return BranchFormat.find_format(self, name=name)
933
1193
 
934
1194
    def _get_mkdir_mode(self):
935
1195
        """Figure out the mode to use when creating a bzrdir subdir."""
936
 
        temp_control = lockable_files.LockableFiles(
937
 
            self.transport, '', lockable_files.TransportLock)
 
1196
        temp_control = lockable_files.LockableFiles(self.transport, '',
 
1197
                                     lockable_files.TransportLock)
938
1198
        return temp_control._dir_mode
939
1199
 
940
1200
    def get_branch_reference(self, name=None):
941
1201
        """See BzrDir.get_branch_reference()."""
942
 
        from .branch import BranchFormatMetadir
943
 
        format = BranchFormatMetadir.find_format(self, name=name)
 
1202
        from bzrlib.branch import BranchFormat
 
1203
        format = BranchFormat.find_format(self, name=name)
944
1204
        return format.get_reference(self, name=name)
945
1205
 
946
 
    def set_branch_reference(self, target_branch, name=None):
947
 
        format = _mod_bzrbranch.BranchReferenceFormat()
948
 
        if (self.control_url == target_branch.controldir.control_url
949
 
                and name == target_branch.name):
950
 
            raise controldir.BranchReferenceLoop(target_branch)
951
 
        return format.initialize(self, target_branch=target_branch, name=name)
952
 
 
953
1206
    def get_branch_transport(self, branch_format, name=None):
954
1207
        """See BzrDir.get_branch_transport()."""
955
 
        if name is None:
956
 
            name = self._get_selected_branch()
957
 
        path = self._get_branch_path(name)
 
1208
        if name is not None:
 
1209
            raise errors.NoColocatedBranchSupport(self)
958
1210
        # XXX: this shouldn't implicitly create the directory if it's just
959
1211
        # promising to get a transport -- mbp 20090727
960
1212
        if branch_format is None:
961
 
            return self.transport.clone(path)
 
1213
            return self.transport.clone('branch')
962
1214
        try:
963
1215
            branch_format.get_format_string()
964
1216
        except NotImplementedError:
965
1217
            raise errors.IncompatibleFormat(branch_format, self._format)
966
 
        if name != "":
967
 
            branches = self._read_branch_list()
968
 
            if name not in branches:
969
 
                self.control_files.lock_write()
970
 
                try:
971
 
                    branches = self._read_branch_list()
972
 
                    dirname = urlutils.dirname(name)
973
 
                    if dirname != u"" and dirname in branches:
974
 
                        raise errors.ParentBranchExists(name)
975
 
                    child_branches = [
976
 
                        b.startswith(name + u"/") for b in branches]
977
 
                    if any(child_branches):
978
 
                        raise errors.AlreadyBranchError(name)
979
 
                    branches.append(name)
980
 
                    self._write_branch_list(branches)
981
 
                finally:
982
 
                    self.control_files.unlock()
983
 
        branch_transport = self.transport.clone(path)
984
 
        mode = self._get_mkdir_mode()
985
 
        branch_transport.create_prefix(mode=mode)
986
1218
        try:
987
 
            self.transport.mkdir(path, mode=mode)
 
1219
            self.transport.mkdir('branch', mode=self._get_mkdir_mode())
988
1220
        except errors.FileExists:
989
1221
            pass
990
 
        return self.transport.clone(path)
 
1222
        return self.transport.clone('branch')
991
1223
 
992
1224
    def get_repository_transport(self, repository_format):
993
1225
        """See BzrDir.get_repository_transport()."""
1017
1249
            pass
1018
1250
        return self.transport.clone('checkout')
1019
1251
 
1020
 
    def branch_names(self):
1021
 
        """See ControlDir.branch_names."""
1022
 
        ret = []
1023
 
        try:
1024
 
            self.get_branch_reference()
1025
 
        except errors.NotBranchError:
1026
 
            pass
1027
 
        else:
1028
 
            ret.append("")
1029
 
        ret.extend(self._read_branch_list())
1030
 
        return ret
1031
 
 
1032
 
    def get_branches(self):
1033
 
        """See ControlDir.get_branches."""
1034
 
        ret = {}
1035
 
        try:
1036
 
            ret[""] = self.open_branch(name="")
1037
 
        except (errors.NotBranchError, errors.NoRepositoryPresent):
1038
 
            pass
1039
 
 
1040
 
        for name in self._read_branch_list():
1041
 
            ret[name] = self.open_branch(name=name)
1042
 
 
1043
 
        return ret
1044
 
 
1045
1252
    def has_workingtree(self):
1046
1253
        """Tell if this bzrdir contains a working tree.
1047
1254
 
 
1255
        This will still raise an exception if the bzrdir has a workingtree that
 
1256
        is remote & inaccessible.
 
1257
 
1048
1258
        Note: if you're going to open the working tree, you should just go
1049
1259
        ahead and try, and not ask permission first.
1050
1260
        """
1051
 
        from .workingtree import WorkingTreeFormatMetaDir
 
1261
        from bzrlib.workingtree import WorkingTreeFormat
1052
1262
        try:
1053
 
            WorkingTreeFormatMetaDir.find_format_string(self)
 
1263
            WorkingTreeFormat.find_format(self)
1054
1264
        except errors.NoWorkingTree:
1055
1265
            return False
1056
1266
        return True
1057
1267
 
1058
1268
    def needs_format_conversion(self, format):
1059
1269
        """See BzrDir.needs_format_conversion()."""
1060
 
        if (not isinstance(self._format, format.__class__)
1061
 
                or self._format.get_format_string() != format.get_format_string()):
 
1270
        if not isinstance(self._format, format.__class__):
1062
1271
            # it is not a meta dir format, conversion is needed.
1063
1272
            return True
1064
1273
        # we might want to push this down to the repository?
1085
1294
        return False
1086
1295
 
1087
1296
    def open_branch(self, name=None, unsupported=False,
1088
 
                    ignore_fallbacks=False, possible_transports=None):
1089
 
        """See ControlDir.open_branch."""
1090
 
        if name is None:
1091
 
            name = self._get_selected_branch()
 
1297
                    ignore_fallbacks=False):
 
1298
        """See BzrDir.open_branch."""
1092
1299
        format = self.find_branch_format(name=name)
1093
1300
        format.check_support_status(unsupported)
1094
 
        if possible_transports is None:
1095
 
            possible_transports = []
1096
 
        else:
1097
 
            possible_transports = list(possible_transports)
1098
 
        possible_transports.append(self.root_transport)
1099
1301
        return format.open(self, name=name,
1100
 
                           _found=True, ignore_fallbacks=ignore_fallbacks,
1101
 
                           possible_transports=possible_transports)
 
1302
            _found=True, ignore_fallbacks=ignore_fallbacks)
1102
1303
 
1103
1304
    def open_repository(self, unsupported=False):
1104
1305
        """See BzrDir.open_repository."""
1105
 
        from .repository import RepositoryFormatMetaDir
1106
 
        format = RepositoryFormatMetaDir.find_format(self)
 
1306
        from bzrlib.repository import RepositoryFormat
 
1307
        format = RepositoryFormat.find_format(self)
1107
1308
        format.check_support_status(unsupported)
1108
1309
        return format.open(self, _found=True)
1109
1310
 
1110
1311
    def open_workingtree(self, unsupported=False,
1111
 
                         recommend_upgrade=True):
 
1312
            recommend_upgrade=True):
1112
1313
        """See BzrDir.open_workingtree."""
1113
 
        from .workingtree import WorkingTreeFormatMetaDir
1114
 
        format = WorkingTreeFormatMetaDir.find_format(self)
 
1314
        from bzrlib.workingtree import WorkingTreeFormat
 
1315
        format = WorkingTreeFormat.find_format(self)
1115
1316
        format.check_support_status(unsupported, recommend_upgrade,
1116
 
                                    basedir=self.root_transport.base)
 
1317
            basedir=self.root_transport.base)
1117
1318
        return format.open(self, _found=True)
1118
1319
 
1119
1320
    def _get_config(self):
1120
1321
        return config.TransportConfig(self.transport, 'control.conf')
1121
1322
 
1122
1323
 
1123
 
class BzrFormat(object):
1124
 
    """Base class for all formats of things living in metadirs.
1125
 
 
1126
 
    This class manages the format string that is stored in the 'format'
1127
 
    or 'branch-format' file.
1128
 
 
1129
 
    All classes for (branch-, repository-, workingtree-) formats that
1130
 
    live in meta directories and have their own 'format' file
1131
 
    (i.e. different from .bzr/branch-format) derive from this class,
1132
 
    as well as the relevant base class for their kind
1133
 
    (BranchFormat, WorkingTreeFormat, RepositoryFormat).
1134
 
 
1135
 
    Each format is identified by a "format" or "branch-format" file with a
1136
 
    single line containing the base format name and then an optional list of
1137
 
    feature flags.
1138
 
 
1139
 
    Feature flags are supported as of bzr 2.5. Setting feature flags on formats
1140
 
    will render them inaccessible to older versions of bzr.
1141
 
 
1142
 
    :ivar features: Dictionary mapping feature names to their necessity
1143
 
    """
1144
 
 
1145
 
    _present_features = set()
1146
 
 
1147
 
    def __init__(self):
1148
 
        self.features = {}
1149
 
 
1150
 
    @classmethod
1151
 
    def register_feature(cls, name):
1152
 
        """Register a feature as being present.
1153
 
 
1154
 
        :param name: Name of the feature
1155
 
        """
1156
 
        if b" " in name:
1157
 
            raise ValueError("spaces are not allowed in feature names")
1158
 
        if name in cls._present_features:
1159
 
            raise FeatureAlreadyRegistered(name)
1160
 
        cls._present_features.add(name)
1161
 
 
1162
 
    @classmethod
1163
 
    def unregister_feature(cls, name):
1164
 
        """Unregister a feature."""
1165
 
        cls._present_features.remove(name)
1166
 
 
1167
 
    def check_support_status(self, allow_unsupported, recommend_upgrade=True,
1168
 
                             basedir=None):
1169
 
        for name, necessity in self.features.items():
1170
 
            if name in self._present_features:
1171
 
                continue
1172
 
            if necessity == b"optional":
1173
 
                mutter("ignoring optional missing feature %s", name)
1174
 
                continue
1175
 
            elif necessity == b"required":
1176
 
                raise MissingFeature(name)
1177
 
            else:
1178
 
                mutter("treating unknown necessity as require for %s",
1179
 
                       name)
1180
 
                raise MissingFeature(name)
1181
 
 
1182
 
    @classmethod
1183
 
    def get_format_string(cls):
1184
 
        """Return the ASCII format string that identifies this format."""
1185
 
        raise NotImplementedError(cls.get_format_string)
1186
 
 
1187
 
    @classmethod
1188
 
    def from_string(cls, text):
1189
 
        format_string = cls.get_format_string()
1190
 
        if not text.startswith(format_string):
1191
 
            raise AssertionError(
1192
 
                "Invalid format header %r for %r" % (text, cls))
1193
 
        lines = text[len(format_string):].splitlines()
1194
 
        ret = cls()
1195
 
        for lineno, line in enumerate(lines):
1196
 
            try:
1197
 
                (necessity, feature) = line.split(b" ", 1)
1198
 
            except ValueError:
1199
 
                raise errors.ParseFormatError(format=cls, lineno=lineno + 2,
1200
 
                                              line=line, text=text)
1201
 
            ret.features[feature] = necessity
1202
 
        return ret
1203
 
 
1204
 
    def as_string(self):
1205
 
        """Return the string representation of this format.
1206
 
        """
1207
 
        lines = [self.get_format_string()]
1208
 
        lines.extend([(item[1] + b" " + item[0] + b"\n")
1209
 
                      for item in sorted(self.features.items())])
1210
 
        return b"".join(lines)
1211
 
 
1212
 
    @classmethod
1213
 
    def _find_format(klass, registry, kind, format_string):
1214
 
        try:
1215
 
            first_line = format_string[:format_string.index(b"\n") + 1]
1216
 
        except ValueError:
1217
 
            first_line = format_string
1218
 
        try:
1219
 
            cls = registry.get(first_line)
 
1324
class BzrProber(controldir.Prober):
 
1325
    """Prober for formats that use a .bzr/ control directory."""
 
1326
 
 
1327
    formats = registry.FormatRegistry(controldir.network_format_registry)
 
1328
    """The known .bzr formats."""
 
1329
 
 
1330
    @classmethod
 
1331
    @deprecated_method(deprecated_in((2, 4, 0)))
 
1332
    def register_bzrdir_format(klass, format):
 
1333
        klass.formats.register(format.get_format_string(), format)
 
1334
 
 
1335
    @classmethod
 
1336
    @deprecated_method(deprecated_in((2, 4, 0)))
 
1337
    def unregister_bzrdir_format(klass, format):
 
1338
        klass.formats.remove(format.get_format_string())
 
1339
 
 
1340
    @classmethod
 
1341
    def probe_transport(klass, transport):
 
1342
        """Return the .bzrdir style format present in a directory."""
 
1343
        try:
 
1344
            format_string = transport.get_bytes(".bzr/branch-format")
 
1345
        except errors.NoSuchFile:
 
1346
            raise errors.NotBranchError(path=transport.base)
 
1347
        try:
 
1348
            return klass.formats.get(format_string)
1220
1349
        except KeyError:
1221
 
            raise errors.UnknownFormatError(format=first_line, kind=kind)
1222
 
        return cls.from_string(format_string)
1223
 
 
1224
 
    def network_name(self):
1225
 
        """A simple byte string uniquely identifying this format for RPC calls.
1226
 
 
1227
 
        Metadir branch formats use their format string.
1228
 
        """
1229
 
        return self.as_string()
1230
 
 
1231
 
    def __eq__(self, other):
1232
 
        return (self.__class__ is other.__class__
1233
 
                and self.features == other.features)
1234
 
 
1235
 
    def _update_feature_flags(self, updated_flags):
1236
 
        """Update the feature flags in this format.
1237
 
 
1238
 
        :param updated_flags: Updated feature flags
1239
 
        """
1240
 
        for name, necessity in updated_flags.items():
1241
 
            if necessity is None:
 
1350
            raise errors.UnknownFormatError(format=format_string, kind='bzrdir')
 
1351
 
 
1352
    @classmethod
 
1353
    def known_formats(cls):
 
1354
        result = set()
 
1355
        for name, format in cls.formats.iteritems():
 
1356
            if callable(format):
 
1357
                format = format()
 
1358
            result.add(format)
 
1359
        return result
 
1360
 
 
1361
 
 
1362
controldir.ControlDirFormat.register_prober(BzrProber)
 
1363
 
 
1364
 
 
1365
class RemoteBzrProber(controldir.Prober):
 
1366
    """Prober for remote servers that provide a Bazaar smart server."""
 
1367
 
 
1368
    @classmethod
 
1369
    def probe_transport(klass, transport):
 
1370
        """Return a RemoteBzrDirFormat object if it looks possible."""
 
1371
        try:
 
1372
            medium = transport.get_smart_medium()
 
1373
        except (NotImplementedError, AttributeError,
 
1374
                errors.TransportNotPossible, errors.NoSmartMedium,
 
1375
                errors.SmartProtocolError):
 
1376
            # no smart server, so not a branch for this format type.
 
1377
            raise errors.NotBranchError(path=transport.base)
 
1378
        else:
 
1379
            # Decline to open it if the server doesn't support our required
 
1380
            # version (3) so that the VFS-based transport will do it.
 
1381
            if medium.should_probe():
1242
1382
                try:
1243
 
                    del self.features[name]
1244
 
                except KeyError:
1245
 
                    pass
1246
 
            else:
1247
 
                self.features[name] = necessity
1248
 
 
1249
 
 
1250
 
class BzrDirFormat(BzrFormat, controldir.ControlDirFormat):
 
1383
                    server_version = medium.protocol_version()
 
1384
                except errors.SmartProtocolError:
 
1385
                    # Apparently there's no usable smart server there, even though
 
1386
                    # the medium supports the smart protocol.
 
1387
                    raise errors.NotBranchError(path=transport.base)
 
1388
                if server_version != '2':
 
1389
                    raise errors.NotBranchError(path=transport.base)
 
1390
            from bzrlib.remote import RemoteBzrDirFormat
 
1391
            return RemoteBzrDirFormat()
 
1392
 
 
1393
    @classmethod
 
1394
    def known_formats(cls):
 
1395
        from bzrlib.remote import RemoteBzrDirFormat
 
1396
        return set([RemoteBzrDirFormat()])
 
1397
 
 
1398
 
 
1399
class BzrDirFormat(controldir.ControlDirFormat):
1251
1400
    """ControlDirFormat base class for .bzr/ directories.
1252
1401
 
1253
1402
    Formats are placed in a dict by their format string for reference
1264
1413
    # _lock_class must be set in subclasses to the lock type, typ.
1265
1414
    # TransportLock or LockDir
1266
1415
 
 
1416
    @classmethod
 
1417
    def get_format_string(cls):
 
1418
        """Return the ASCII format string that identifies this format."""
 
1419
        raise NotImplementedError(self.get_format_string)
 
1420
 
1267
1421
    def initialize_on_transport(self, transport):
1268
1422
        """Initialize a new bzrdir in the base directory of a Transport."""
1269
1423
        try:
1276
1430
            # Current RPC's only know how to create bzr metadir1 instances, so
1277
1431
            # we still delegate to vfs methods if the requested format is not a
1278
1432
            # metadir1
1279
 
            if not isinstance(self, BzrDirMetaFormat1):
 
1433
            if type(self) != BzrDirMetaFormat1:
1280
1434
                return self._initialize_on_transport_vfs(transport)
1281
 
            from .remote import RemoteBzrDirFormat
 
1435
            from bzrlib.remote import RemoteBzrDirFormat
1282
1436
            remote_format = RemoteBzrDirFormat()
1283
1437
            self._supply_sub_formats_to(remote_format)
1284
1438
            return remote_format.initialize_on_transport(transport)
1285
1439
 
1286
1440
    def initialize_on_transport_ex(self, transport, use_existing_dir=False,
1287
 
                                   create_prefix=False, force_new_repo=False, stacked_on=None,
1288
 
                                   stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
1289
 
                                   shared_repo=False, vfs_only=False):
 
1441
        create_prefix=False, force_new_repo=False, stacked_on=None,
 
1442
        stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
 
1443
        shared_repo=False, vfs_only=False):
1290
1444
        """Create this format on transport.
1291
1445
 
1292
1446
        The directory to initialize will be created.
1310
1464
        :param shared_repo: Control whether made repositories are shared or
1311
1465
            not.
1312
1466
        :param vfs_only: If True do not attempt to use a smart server
1313
 
        :return: repo, controldir, require_stacking, repository_policy. repo is
 
1467
        :return: repo, bzrdir, require_stacking, repository_policy. repo is
1314
1468
            None if none was created or found, bzrdir is always valid.
1315
1469
            require_stacking is the result of examining the stacked_on
1316
1470
            parameter and any stacking policy found for the target.
1317
1471
        """
1318
1472
        if not vfs_only:
1319
 
            # Try to hand off to a smart server
 
1473
            # Try to hand off to a smart server 
1320
1474
            try:
1321
1475
                client_medium = transport.get_smart_medium()
1322
1476
            except errors.NoSmartMedium:
1323
1477
                pass
1324
1478
            else:
1325
 
                from .remote import RemoteBzrDirFormat
 
1479
                from bzrlib.remote import RemoteBzrDirFormat
1326
1480
                # TODO: lookup the local format from a server hint.
1327
1481
                remote_dir_format = RemoteBzrDirFormat()
1328
1482
                remote_dir_format._network_name = self.network_name()
1329
1483
                self._supply_sub_formats_to(remote_dir_format)
1330
 
                return remote_dir_format.initialize_on_transport_ex(
1331
 
                    transport, use_existing_dir=use_existing_dir,
1332
 
                    create_prefix=create_prefix, force_new_repo=force_new_repo,
1333
 
                    stacked_on=stacked_on, stack_on_pwd=stack_on_pwd,
1334
 
                    repo_format_name=repo_format_name,
1335
 
                    make_working_trees=make_working_trees,
1336
 
                    shared_repo=shared_repo)
 
1484
                return remote_dir_format.initialize_on_transport_ex(transport,
 
1485
                    use_existing_dir=use_existing_dir, create_prefix=create_prefix,
 
1486
                    force_new_repo=force_new_repo, stacked_on=stacked_on,
 
1487
                    stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
 
1488
                    make_working_trees=make_working_trees, shared_repo=shared_repo)
1337
1489
        # XXX: Refactor the create_prefix/no_create_prefix code into a
1338
1490
        #      common helper function
1339
1491
        # The destination may not exist - if so make it according to policy.
1340
 
 
1341
1492
        def make_directory(transport):
1342
1493
            transport.mkdir('.')
1343
1494
            return transport
1344
 
 
1345
1495
        def redirected(transport, e, redirection_notice):
1346
1496
            note(redirection_notice)
1347
1497
            return transport._redirected_to(e.source, e.target)
1348
1498
        try:
1349
1499
            transport = do_catching_redirections(make_directory, transport,
1350
 
                                                 redirected)
 
1500
                redirected)
1351
1501
        except errors.FileExists:
1352
1502
            if not use_existing_dir:
1353
1503
                raise
1394
1544
        # Since we are creating a .bzr directory, inherit the
1395
1545
        # mode from the root directory
1396
1546
        temp_control = lockable_files.LockableFiles(transport,
1397
 
                                                    '', lockable_files.TransportLock)
1398
 
        try:
1399
 
            temp_control._transport.mkdir('.bzr',
1400
 
                                          # FIXME: RBC 20060121 don't peek under
1401
 
                                          # the covers
1402
 
                                          mode=temp_control._dir_mode)
1403
 
        except errors.FileExists:
1404
 
            raise errors.AlreadyControlDirError(transport.base)
 
1547
                            '', lockable_files.TransportLock)
 
1548
        temp_control._transport.mkdir('.bzr',
 
1549
                                      # FIXME: RBC 20060121 don't peek under
 
1550
                                      # the covers
 
1551
                                      mode=temp_control._dir_mode)
1405
1552
        if sys.platform == 'win32' and isinstance(transport, local.LocalTransport):
1406
1553
            win32utils.set_file_attr_hidden(transport._abspath('.bzr'))
1407
1554
        file_mode = temp_control._file_mode
1408
1555
        del temp_control
1409
1556
        bzrdir_transport = transport.clone('.bzr')
1410
1557
        utf8_files = [('README',
1411
 
                       b"This is a Bazaar control directory.\n"
1412
 
                       b"Do not change any files in this directory.\n"
1413
 
                       b"See http://bazaar.canonical.com/ for more information about Bazaar.\n"),
1414
 
                      ('branch-format', self.as_string()),
 
1558
                       "This is a Bazaar control directory.\n"
 
1559
                       "Do not change any files in this directory.\n"
 
1560
                       "See http://bazaar.canonical.com/ for more information about Bazaar.\n"),
 
1561
                      ('branch-format', self.get_format_string()),
1415
1562
                      ]
1416
1563
        # NB: no need to escape relative paths that are url safe.
1417
1564
        control_files = lockable_files.LockableFiles(bzrdir_transport,
1418
 
                                                     self._lock_file_name, self._lock_class)
 
1565
            self._lock_file_name, self._lock_class)
1419
1566
        control_files.create_lock()
1420
1567
        control_files.lock_write()
1421
1568
        try:
1422
1569
            for (filename, content) in utf8_files:
1423
1570
                bzrdir_transport.put_bytes(filename, content,
1424
 
                                           mode=file_mode)
 
1571
                    mode=file_mode)
1425
1572
        finally:
1426
1573
            control_files.unlock()
1427
1574
        return self.open(transport, _found=True)
1435
1582
            found_format = controldir.ControlDirFormat.find_format(transport)
1436
1583
            if not isinstance(found_format, self.__class__):
1437
1584
                raise AssertionError("%s was asked to open %s, but it seems to need "
1438
 
                                     "format %s"
1439
 
                                     % (self, transport, found_format))
 
1585
                        "format %s"
 
1586
                        % (self, transport, found_format))
1440
1587
            # Allow subclasses - use the found format.
1441
1588
            self._supply_sub_formats_to(found_format)
1442
1589
            return found_format._open(transport)
1461
1608
            compatible with whatever sub formats are supported by self.
1462
1609
        :return: None.
1463
1610
        """
1464
 
        other_format.features = dict(self.features)
1465
 
 
1466
 
    def supports_transport(self, transport):
1467
 
        # bzr formats can be opened over all known transports
1468
 
        return True
1469
 
 
1470
 
    def check_support_status(self, allow_unsupported, recommend_upgrade=True,
1471
 
                             basedir=None):
1472
 
        controldir.ControlDirFormat.check_support_status(self,
1473
 
                                                         allow_unsupported=allow_unsupported, recommend_upgrade=recommend_upgrade,
1474
 
                                                         basedir=basedir)
1475
 
        BzrFormat.check_support_status(self, allow_unsupported=allow_unsupported,
1476
 
                                       recommend_upgrade=recommend_upgrade, basedir=basedir)
1477
 
 
1478
 
    @classmethod
1479
 
    def is_control_filename(klass, filename):
1480
 
        """True if filename is the name of a path which is reserved for bzrdir's.
1481
 
 
1482
 
        :param filename: A filename within the root transport of this bzrdir.
1483
 
 
1484
 
        This is true IF and ONLY IF the filename is part of the namespace
1485
 
        reserved for bzr control dirs. Currently this is the '.bzr' directory
1486
 
        in the root of the root_transport.
1487
 
        """
1488
 
        # this might be better on the BzrDirFormat class because it refers to
1489
 
        # all the possible bzrdir disk formats.
1490
 
        # This method is tested via the workingtree is_control_filename tests-
1491
 
        # it was extracted from WorkingTree.is_control_filename. If the
1492
 
        # method's contract is extended beyond the current trivial
1493
 
        # implementation, please add new tests for it to the appropriate place.
1494
 
        return filename == '.bzr' or filename.startswith('.bzr/')
1495
 
 
1496
 
    @classmethod
1497
 
    def get_default_format(klass):
1498
 
        """Return the current default format."""
1499
 
        return controldir.format_registry.get('bzr')()
1500
1611
 
1501
1612
 
1502
1613
class BzrDirMetaFormat1(BzrDirFormat):
1504
1615
 
1505
1616
    This is the first format with split out working tree, branch and repository
1506
1617
    disk storage.
1507
 
 
1508
1618
    It has:
1509
 
 
1510
 
    - Format 3 working trees [optional]
1511
 
    - Format 5 branches [optional]
1512
 
    - Format 7 repositories [optional]
 
1619
     - Format 3 working trees [optional]
 
1620
     - Format 5 branches [optional]
 
1621
     - Format 7 repositories [optional]
1513
1622
    """
1514
1623
 
1515
1624
    _lock_class = lockdir.LockDir
1516
1625
 
1517
1626
    fixed_components = False
1518
1627
 
1519
 
    colocated_branches = True
1520
 
 
1521
1628
    def __init__(self):
1522
 
        BzrDirFormat.__init__(self)
1523
1629
        self._workingtree_format = None
1524
1630
        self._branch_format = None
1525
1631
        self._repository_format = None
1531
1637
            return False
1532
1638
        if other.workingtree_format != self.workingtree_format:
1533
1639
            return False
1534
 
        if other.features != self.features:
1535
 
            return False
1536
1640
        return True
1537
1641
 
1538
1642
    def __ne__(self, other):
1540
1644
 
1541
1645
    def get_branch_format(self):
1542
1646
        if self._branch_format is None:
1543
 
            from .branch import format_registry as branch_format_registry
 
1647
            from bzrlib.branch import format_registry as branch_format_registry
1544
1648
            self._branch_format = branch_format_registry.get_default()
1545
1649
        return self._branch_format
1546
1650
 
1548
1652
        self._branch_format = format
1549
1653
 
1550
1654
    def require_stacking(self, stack_on=None, possible_transports=None,
1551
 
                         _skip_repo=False):
 
1655
            _skip_repo=False):
1552
1656
        """We have a request to stack, try to ensure the formats support it.
1553
1657
 
1554
1658
        :param stack_on: If supplied, it is the URL to a branch that we want to
1563
1667
 
1564
1668
        # a bit of state for get_target_branch so that we don't try to open it
1565
1669
        # 2 times, for both repo *and* branch
1566
 
        target = [None, False, None]  # target_branch, checked, upgrade anyway
1567
 
 
 
1670
        target = [None, False, None] # target_branch, checked, upgrade anyway
1568
1671
        def get_target_branch():
1569
1672
            if target[1]:
1570
1673
                # We've checked, don't check again
1575
1678
                return target
1576
1679
            try:
1577
1680
                target_dir = BzrDir.open(stack_on,
1578
 
                                         possible_transports=possible_transports)
 
1681
                    possible_transports=possible_transports)
1579
1682
            except errors.NotBranchError:
1580
1683
                # Nothing there, don't change formats
1581
1684
                target[:] = [None, True, False]
1593
1696
            target[:] = [target_branch, True, False]
1594
1697
            return target
1595
1698
 
1596
 
        if (not _skip_repo
1597
 
                and not self.repository_format.supports_external_lookups):
 
1699
        if (not _skip_repo and
 
1700
                 not self.repository_format.supports_external_lookups):
1598
1701
            # We need to upgrade the Repository.
1599
1702
            target_branch, _, do_upgrade = get_target_branch()
1600
1703
            if target_branch is None:
1617
1720
                    new_repo_format = None
1618
1721
            if new_repo_format is not None:
1619
1722
                self.repository_format = new_repo_format
1620
 
                note(gettext('Source repository format does not support stacking,'
1621
 
                             ' using format:\n  %s'),
 
1723
                note('Source repository format does not support stacking,'
 
1724
                     ' using format:\n  %s',
1622
1725
                     new_repo_format.get_format_description())
1623
1726
 
1624
1727
        if not self.get_branch_format().supports_stacking():
1628
1731
            if target_branch is None:
1629
1732
                if do_upgrade:
1630
1733
                    # TODO: bad monkey, hard-coded formats...
1631
 
                    from .branch import BzrBranchFormat7
 
1734
                    from bzrlib.branch import BzrBranchFormat7
1632
1735
                    new_branch_format = BzrBranchFormat7()
1633
1736
            else:
1634
1737
                new_branch_format = target_branch._format
1637
1740
            if new_branch_format is not None:
1638
1741
                # Does support stacking, use its format.
1639
1742
                self.set_branch_format(new_branch_format)
1640
 
                note(gettext('Source branch format does not support stacking,'
1641
 
                             ' using format:\n  %s'),
 
1743
                note('Source branch format does not support stacking,'
 
1744
                     ' using format:\n  %s',
1642
1745
                     new_branch_format.get_format_description())
1643
1746
 
1644
1747
    def get_converter(self, format=None):
1645
1748
        """See BzrDirFormat.get_converter()."""
1646
1749
        if format is None:
1647
1750
            format = BzrDirFormat.get_default_format()
1648
 
        if (isinstance(self, BzrDirMetaFormat1)
1649
 
                and isinstance(format, BzrDirMetaFormat1Colo)):
1650
 
            return ConvertMetaToColo(format)
1651
 
        if (isinstance(self, BzrDirMetaFormat1Colo)
1652
 
                and isinstance(format, BzrDirMetaFormat1)):
1653
 
            return ConvertMetaToColo(format)
1654
1751
        if not isinstance(self, format.__class__):
1655
1752
            # converting away from metadir is not implemented
1656
1753
            raise NotImplementedError(self.get_converter)
1659
1756
    @classmethod
1660
1757
    def get_format_string(cls):
1661
1758
        """See BzrDirFormat.get_format_string()."""
1662
 
        return b"Bazaar-NG meta directory, format 1\n"
 
1759
        return "Bazaar-NG meta directory, format 1\n"
1663
1760
 
1664
1761
    def get_format_description(self):
1665
1762
        """See BzrDirFormat.get_format_description()."""
1666
1763
        return "Meta directory format 1"
1667
1764
 
 
1765
    def network_name(self):
 
1766
        return self.get_format_string()
 
1767
 
1668
1768
    def _open(self, transport):
1669
1769
        """See BzrDirFormat._open."""
1670
1770
        # Create a new format instance because otherwise initialisation of new
1678
1778
        """Circular import protection."""
1679
1779
        if self._repository_format:
1680
1780
            return self._repository_format
1681
 
        from .repository import format_registry
 
1781
        from bzrlib.repository import format_registry
1682
1782
        return format_registry.get_default()
1683
1783
 
1684
1784
    def _set_repository_format(self, value):
1686
1786
        self._repository_format = value
1687
1787
 
1688
1788
    repository_format = property(__return_repository_format,
1689
 
                                 _set_repository_format)
 
1789
        _set_repository_format)
1690
1790
 
1691
1791
    def _supply_sub_formats_to(self, other_format):
1692
1792
        """Give other_format the same values for sub formats as this has.
1699
1799
            compatible with whatever sub formats are supported by self.
1700
1800
        :return: None.
1701
1801
        """
1702
 
        super(BzrDirMetaFormat1, self)._supply_sub_formats_to(other_format)
1703
1802
        if getattr(self, '_repository_format', None) is not None:
1704
1803
            other_format.repository_format = self.repository_format
1705
1804
        if self._branch_format is not None:
1709
1808
 
1710
1809
    def __get_workingtree_format(self):
1711
1810
        if self._workingtree_format is None:
1712
 
            from .workingtree import (
 
1811
            from bzrlib.workingtree import (
1713
1812
                format_registry as wt_format_registry,
1714
1813
                )
1715
1814
            self._workingtree_format = wt_format_registry.get_default()
1718
1817
    def __set_workingtree_format(self, wt_format):
1719
1818
        self._workingtree_format = wt_format
1720
1819
 
1721
 
    def __repr__(self):
1722
 
        return "<%r>" % (self.__class__.__name__,)
1723
 
 
1724
1820
    workingtree_format = property(__get_workingtree_format,
1725
1821
                                  __set_workingtree_format)
1726
1822
 
1727
1823
 
1728
 
class BzrDirMetaFormat1Colo(BzrDirMetaFormat1):
1729
 
    """BzrDirMeta1 format with support for colocated branches."""
1730
 
 
1731
 
    colocated_branches = True
1732
 
 
1733
 
    @classmethod
1734
 
    def get_format_string(cls):
1735
 
        """See BzrDirFormat.get_format_string()."""
1736
 
        return b"Bazaar meta directory, format 1 (with colocated branches)\n"
1737
 
 
1738
 
    def get_format_description(self):
1739
 
        """See BzrDirFormat.get_format_description()."""
1740
 
        return "Meta directory format 1 with support for colocated branches"
1741
 
 
1742
 
    def _open(self, transport):
1743
 
        """See BzrDirFormat._open."""
1744
 
        # Create a new format instance because otherwise initialisation of new
1745
 
        # metadirs share the global default format object leading to alias
1746
 
        # problems.
1747
 
        format = BzrDirMetaFormat1Colo()
1748
 
        self._supply_sub_formats_to(format)
1749
 
        return BzrDirMeta1(transport, format)
 
1824
# Register bzr formats
 
1825
BzrProber.formats.register(BzrDirMetaFormat1.get_format_string(),
 
1826
    BzrDirMetaFormat1)
 
1827
controldir.ControlDirFormat._default_format = BzrDirMetaFormat1()
1750
1828
 
1751
1829
 
1752
1830
class ConvertMetaToMeta(controldir.Converter):
1761
1839
 
1762
1840
    def convert(self, to_convert, pb):
1763
1841
        """See Converter.convert()."""
1764
 
        self.controldir = to_convert
1765
 
        with ui.ui_factory.nested_progress_bar() as self.pb:
1766
 
            self.count = 0
1767
 
            self.total = 1
1768
 
            self.step('checking repository format')
1769
 
            try:
1770
 
                repo = self.controldir.open_repository()
1771
 
            except errors.NoRepositoryPresent:
1772
 
                pass
1773
 
            else:
1774
 
                repo_fmt = self.target_format.repository_format
1775
 
                if not isinstance(repo._format, repo_fmt.__class__):
1776
 
                    from ..repository import CopyConverter
1777
 
                    ui.ui_factory.note(gettext('starting repository conversion'))
1778
 
                    if not repo_fmt.supports_overriding_transport:
1779
 
                        raise AssertionError(
1780
 
                            "Repository in metadir does not support "
1781
 
                            "overriding transport")
1782
 
                    converter = CopyConverter(self.target_format.repository_format)
1783
 
                    converter.convert(repo, pb)
1784
 
            for branch in self.controldir.list_branches():
1785
 
                # TODO: conversions of Branch and Tree should be done by
1786
 
                # InterXFormat lookups/some sort of registry.
1787
 
                # Avoid circular imports
 
1842
        self.bzrdir = to_convert
 
1843
        self.pb = ui.ui_factory.nested_progress_bar()
 
1844
        self.count = 0
 
1845
        self.total = 1
 
1846
        self.step('checking repository format')
 
1847
        try:
 
1848
            repo = self.bzrdir.open_repository()
 
1849
        except errors.NoRepositoryPresent:
 
1850
            pass
 
1851
        else:
 
1852
            if not isinstance(repo._format, self.target_format.repository_format.__class__):
 
1853
                from bzrlib.repository import CopyConverter
 
1854
                ui.ui_factory.note('starting repository conversion')
 
1855
                converter = CopyConverter(self.target_format.repository_format)
 
1856
                converter.convert(repo, pb)
 
1857
        for branch in self.bzrdir.list_branches():
 
1858
            # TODO: conversions of Branch and Tree should be done by
 
1859
            # InterXFormat lookups/some sort of registry.
 
1860
            # Avoid circular imports
 
1861
            old = branch._format.__class__
 
1862
            new = self.target_format.get_branch_format().__class__
 
1863
            while old != new:
 
1864
                if (old == _mod_branch.BzrBranchFormat5 and
 
1865
                    new in (_mod_branch.BzrBranchFormat6,
 
1866
                        _mod_branch.BzrBranchFormat7,
 
1867
                        _mod_branch.BzrBranchFormat8)):
 
1868
                    branch_converter = _mod_branch.Converter5to6()
 
1869
                elif (old == _mod_branch.BzrBranchFormat6 and
 
1870
                    new in (_mod_branch.BzrBranchFormat7,
 
1871
                            _mod_branch.BzrBranchFormat8)):
 
1872
                    branch_converter = _mod_branch.Converter6to7()
 
1873
                elif (old == _mod_branch.BzrBranchFormat7 and
 
1874
                      new is _mod_branch.BzrBranchFormat8):
 
1875
                    branch_converter = _mod_branch.Converter7to8()
 
1876
                else:
 
1877
                    raise errors.BadConversionTarget("No converter", new,
 
1878
                        branch._format)
 
1879
                branch_converter.convert(branch)
 
1880
                branch = self.bzrdir.open_branch()
1788
1881
                old = branch._format.__class__
1789
 
                new = self.target_format.get_branch_format().__class__
1790
 
                while old != new:
1791
 
                    if (old == fullhistorybranch.BzrBranchFormat5
1792
 
                        and new in (_mod_bzrbranch.BzrBranchFormat6,
1793
 
                                    _mod_bzrbranch.BzrBranchFormat7,
1794
 
                                    _mod_bzrbranch.BzrBranchFormat8)):
1795
 
                        branch_converter = _mod_bzrbranch.Converter5to6()
1796
 
                    elif (old == _mod_bzrbranch.BzrBranchFormat6
1797
 
                          and new in (_mod_bzrbranch.BzrBranchFormat7,
1798
 
                                      _mod_bzrbranch.BzrBranchFormat8)):
1799
 
                        branch_converter = _mod_bzrbranch.Converter6to7()
1800
 
                    elif (old == _mod_bzrbranch.BzrBranchFormat7
1801
 
                          and new is _mod_bzrbranch.BzrBranchFormat8):
1802
 
                        branch_converter = _mod_bzrbranch.Converter7to8()
1803
 
                    else:
1804
 
                        raise errors.BadConversionTarget("No converter", new,
1805
 
                                                         branch._format)
1806
 
                    branch_converter.convert(branch)
1807
 
                    branch = self.controldir.open_branch()
1808
 
                    old = branch._format.__class__
1809
 
            try:
1810
 
                tree = self.controldir.open_workingtree(recommend_upgrade=False)
1811
 
            except (errors.NoWorkingTree, errors.NotLocalUrl):
1812
 
                pass
1813
 
            else:
1814
 
                # TODO: conversions of Branch and Tree should be done by
1815
 
                # InterXFormat lookups
1816
 
                if (isinstance(tree, workingtree_3.WorkingTree3)
1817
 
                    and not isinstance(tree, workingtree_4.DirStateWorkingTree)
1818
 
                    and isinstance(self.target_format.workingtree_format,
1819
 
                                   workingtree_4.DirStateWorkingTreeFormat)):
1820
 
                    workingtree_4.Converter3to4().convert(tree)
1821
 
                if (isinstance(tree, workingtree_4.DirStateWorkingTree)
1822
 
                    and not isinstance(tree, workingtree_4.WorkingTree5)
1823
 
                    and isinstance(self.target_format.workingtree_format,
1824
 
                                   workingtree_4.WorkingTreeFormat5)):
1825
 
                    workingtree_4.Converter4to5().convert(tree)
1826
 
                if (isinstance(tree, workingtree_4.DirStateWorkingTree)
1827
 
                    and not isinstance(tree, workingtree_4.WorkingTree6)
1828
 
                    and isinstance(self.target_format.workingtree_format,
1829
 
                                   workingtree_4.WorkingTreeFormat6)):
1830
 
                    workingtree_4.Converter4or5to6().convert(tree)
 
1882
        try:
 
1883
            tree = self.bzrdir.open_workingtree(recommend_upgrade=False)
 
1884
        except (errors.NoWorkingTree, errors.NotLocalUrl):
 
1885
            pass
 
1886
        else:
 
1887
            # TODO: conversions of Branch and Tree should be done by
 
1888
            # InterXFormat lookups
 
1889
            if (isinstance(tree, workingtree.WorkingTree3) and
 
1890
                not isinstance(tree, workingtree_4.DirStateWorkingTree) and
 
1891
                isinstance(self.target_format.workingtree_format,
 
1892
                    workingtree_4.DirStateWorkingTreeFormat)):
 
1893
                workingtree_4.Converter3to4().convert(tree)
 
1894
            if (isinstance(tree, workingtree_4.DirStateWorkingTree) and
 
1895
                not isinstance(tree, workingtree_4.WorkingTree5) and
 
1896
                isinstance(self.target_format.workingtree_format,
 
1897
                    workingtree_4.WorkingTreeFormat5)):
 
1898
                workingtree_4.Converter4to5().convert(tree)
 
1899
            if (isinstance(tree, workingtree_4.DirStateWorkingTree) and
 
1900
                not isinstance(tree, workingtree_4.WorkingTree6) and
 
1901
                isinstance(self.target_format.workingtree_format,
 
1902
                    workingtree_4.WorkingTreeFormat6)):
 
1903
                workingtree_4.Converter4or5to6().convert(tree)
 
1904
        self.pb.finished()
1831
1905
        return to_convert
1832
1906
 
1833
1907
 
1834
 
class ConvertMetaToColo(controldir.Converter):
1835
 
    """Add colocated branch support."""
1836
 
 
1837
 
    def __init__(self, target_format):
1838
 
        """Create a converter.that upgrades a metadir to the colo format.
1839
 
 
1840
 
        :param target_format: The final metadir format that is desired.
1841
 
        """
1842
 
        self.target_format = target_format
1843
 
 
1844
 
    def convert(self, to_convert, pb):
1845
 
        """See Converter.convert()."""
1846
 
        to_convert.transport.put_bytes('branch-format',
1847
 
                                       self.target_format.as_string())
1848
 
        return BzrDir.open_from_transport(to_convert.root_transport)
1849
 
 
1850
 
 
1851
 
class ConvertMetaToColo(controldir.Converter):
1852
 
    """Convert a 'development-colo' bzrdir to a '2a' bzrdir."""
1853
 
 
1854
 
    def __init__(self, target_format):
1855
 
        """Create a converter that converts a 'development-colo' metadir
1856
 
        to a '2a' metadir.
1857
 
 
1858
 
        :param target_format: The final metadir format that is desired.
1859
 
        """
1860
 
        self.target_format = target_format
1861
 
 
1862
 
    def convert(self, to_convert, pb):
1863
 
        """See Converter.convert()."""
1864
 
        to_convert.transport.put_bytes('branch-format',
1865
 
                                       self.target_format.as_string())
1866
 
        return BzrDir.open_from_transport(to_convert.root_transport)
1867
 
 
1868
 
 
1869
 
class CreateRepository(controldir.RepositoryAcquisitionPolicy):
 
1908
controldir.ControlDirFormat.register_server_prober(RemoteBzrProber)
 
1909
 
 
1910
 
 
1911
class RepositoryAcquisitionPolicy(object):
 
1912
    """Abstract base class for repository acquisition policies.
 
1913
 
 
1914
    A repository acquisition policy decides how a BzrDir acquires a repository
 
1915
    for a branch that is being created.  The most basic policy decision is
 
1916
    whether to create a new repository or use an existing one.
 
1917
    """
 
1918
    def __init__(self, stack_on, stack_on_pwd, require_stacking):
 
1919
        """Constructor.
 
1920
 
 
1921
        :param stack_on: A location to stack on
 
1922
        :param stack_on_pwd: If stack_on is relative, the location it is
 
1923
            relative to.
 
1924
        :param require_stacking: If True, it is a failure to not stack.
 
1925
        """
 
1926
        self._stack_on = stack_on
 
1927
        self._stack_on_pwd = stack_on_pwd
 
1928
        self._require_stacking = require_stacking
 
1929
 
 
1930
    def configure_branch(self, branch):
 
1931
        """Apply any configuration data from this policy to the branch.
 
1932
 
 
1933
        Default implementation sets repository stacking.
 
1934
        """
 
1935
        if self._stack_on is None:
 
1936
            return
 
1937
        if self._stack_on_pwd is None:
 
1938
            stack_on = self._stack_on
 
1939
        else:
 
1940
            try:
 
1941
                stack_on = urlutils.rebase_url(self._stack_on,
 
1942
                    self._stack_on_pwd,
 
1943
                    branch.user_url)
 
1944
            except errors.InvalidRebaseURLs:
 
1945
                stack_on = self._get_full_stack_on()
 
1946
        try:
 
1947
            branch.set_stacked_on_url(stack_on)
 
1948
        except (errors.UnstackableBranchFormat,
 
1949
                errors.UnstackableRepositoryFormat):
 
1950
            if self._require_stacking:
 
1951
                raise
 
1952
 
 
1953
    def requires_stacking(self):
 
1954
        """Return True if this policy requires stacking."""
 
1955
        return self._stack_on is not None and self._require_stacking
 
1956
 
 
1957
    def _get_full_stack_on(self):
 
1958
        """Get a fully-qualified URL for the stack_on location."""
 
1959
        if self._stack_on is None:
 
1960
            return None
 
1961
        if self._stack_on_pwd is None:
 
1962
            return self._stack_on
 
1963
        else:
 
1964
            return urlutils.join(self._stack_on_pwd, self._stack_on)
 
1965
 
 
1966
    def _add_fallback(self, repository, possible_transports=None):
 
1967
        """Add a fallback to the supplied repository, if stacking is set."""
 
1968
        stack_on = self._get_full_stack_on()
 
1969
        if stack_on is None:
 
1970
            return
 
1971
        try:
 
1972
            stacked_dir = BzrDir.open(stack_on,
 
1973
                                      possible_transports=possible_transports)
 
1974
        except errors.JailBreak:
 
1975
            # We keep the stacking details, but we are in the server code so
 
1976
            # actually stacking is not needed.
 
1977
            return
 
1978
        try:
 
1979
            stacked_repo = stacked_dir.open_branch().repository
 
1980
        except errors.NotBranchError:
 
1981
            stacked_repo = stacked_dir.open_repository()
 
1982
        try:
 
1983
            repository.add_fallback_repository(stacked_repo)
 
1984
        except errors.UnstackableRepositoryFormat:
 
1985
            if self._require_stacking:
 
1986
                raise
 
1987
        else:
 
1988
            self._require_stacking = True
 
1989
 
 
1990
    def acquire_repository(self, make_working_trees=None, shared=False):
 
1991
        """Acquire a repository for this bzrdir.
 
1992
 
 
1993
        Implementations may create a new repository or use a pre-exising
 
1994
        repository.
 
1995
        :param make_working_trees: If creating a repository, set
 
1996
            make_working_trees to this value (if non-None)
 
1997
        :param shared: If creating a repository, make it shared if True
 
1998
        :return: A repository, is_new_flag (True if the repository was
 
1999
            created).
 
2000
        """
 
2001
        raise NotImplemented(RepositoryAcquisitionPolicy.acquire_repository)
 
2002
 
 
2003
 
 
2004
class CreateRepository(RepositoryAcquisitionPolicy):
1870
2005
    """A policy of creating a new repository"""
1871
2006
 
1872
 
    def __init__(self, controldir, stack_on=None, stack_on_pwd=None,
 
2007
    def __init__(self, bzrdir, stack_on=None, stack_on_pwd=None,
1873
2008
                 require_stacking=False):
1874
 
        """Constructor.
1875
 
 
1876
 
        :param controldir: The controldir to create the repository on.
 
2009
        """
 
2010
        Constructor.
 
2011
        :param bzrdir: The bzrdir to create the repository on.
1877
2012
        :param stack_on: A location to stack on
1878
2013
        :param stack_on_pwd: If stack_on is relative, the location it is
1879
2014
            relative to.
1880
2015
        """
1881
 
        super(CreateRepository, self).__init__(
1882
 
            stack_on, stack_on_pwd, require_stacking)
1883
 
        self._controldir = controldir
 
2016
        RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
 
2017
                                             require_stacking)
 
2018
        self._bzrdir = bzrdir
1884
2019
 
1885
 
    def acquire_repository(self, make_working_trees=None, shared=False,
1886
 
                           possible_transports=None):
 
2020
    def acquire_repository(self, make_working_trees=None, shared=False):
1887
2021
        """Implementation of RepositoryAcquisitionPolicy.acquire_repository
1888
2022
 
1889
 
        Creates the desired repository in the controldir we already have.
 
2023
        Creates the desired repository in the bzrdir we already have.
1890
2024
        """
1891
 
        if possible_transports is None:
1892
 
            possible_transports = []
1893
 
        else:
1894
 
            possible_transports = list(possible_transports)
1895
 
        possible_transports.append(self._controldir.root_transport)
1896
2025
        stack_on = self._get_full_stack_on()
1897
2026
        if stack_on:
1898
 
            format = self._controldir._format
 
2027
            format = self._bzrdir._format
1899
2028
            format.require_stacking(stack_on=stack_on,
1900
 
                                    possible_transports=possible_transports)
 
2029
                                    possible_transports=[self._bzrdir.root_transport])
1901
2030
            if not self._require_stacking:
1902
2031
                # We have picked up automatic stacking somewhere.
1903
 
                note(gettext('Using default stacking branch {0} at {1}').format(
1904
 
                    self._stack_on, self._stack_on_pwd))
1905
 
        repository = self._controldir.create_repository(shared=shared)
 
2032
                note('Using default stacking branch %s at %s', self._stack_on,
 
2033
                    self._stack_on_pwd)
 
2034
        repository = self._bzrdir.create_repository(shared=shared)
1906
2035
        self._add_fallback(repository,
1907
 
                           possible_transports=possible_transports)
 
2036
                           possible_transports=[self._bzrdir.transport])
1908
2037
        if make_working_trees is not None:
1909
2038
            repository.set_make_working_trees(make_working_trees)
1910
2039
        return repository, True
1911
2040
 
1912
2041
 
1913
 
class UseExistingRepository(controldir.RepositoryAcquisitionPolicy):
 
2042
class UseExistingRepository(RepositoryAcquisitionPolicy):
1914
2043
    """A policy of reusing an existing repository"""
1915
2044
 
1916
2045
    def __init__(self, repository, stack_on=None, stack_on_pwd=None,
1922
2051
        :param stack_on_pwd: If stack_on is relative, the location it is
1923
2052
            relative to.
1924
2053
        """
1925
 
        super(UseExistingRepository, self).__init__(
1926
 
            stack_on, stack_on_pwd, require_stacking)
 
2054
        RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
 
2055
                                             require_stacking)
1927
2056
        self._repository = repository
1928
2057
 
1929
 
    def acquire_repository(self, make_working_trees=None, shared=False,
1930
 
                           possible_transports=None):
 
2058
    def acquire_repository(self, make_working_trees=None, shared=False):
1931
2059
        """Implementation of RepositoryAcquisitionPolicy.acquire_repository
1932
2060
 
1933
2061
        Returns an existing repository to use.
1934
2062
        """
1935
 
        if possible_transports is None:
1936
 
            possible_transports = []
1937
 
        else:
1938
 
            possible_transports = list(possible_transports)
1939
 
        possible_transports.append(self._repository.controldir.transport)
1940
2063
        self._add_fallback(self._repository,
1941
 
                           possible_transports=possible_transports)
 
2064
                       possible_transports=[self._repository.bzrdir.transport])
1942
2065
        return self._repository, False
1943
2066
 
1944
2067
 
1945
 
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):
 
2075
    """Register a metadir subformat.
 
2076
 
 
2077
    These all use a BzrDirMetaFormat1 bzrdir, but can be parameterized
 
2078
    by the 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
    # This should be expanded to support setting WorkingTree and Branch
 
2088
    # formats, once BzrDirMetaFormat1 supports that.
 
2089
    def _load(full_name):
 
2090
        mod_name, factory_name = full_name.rsplit('.', 1)
 
2091
        try:
 
2092
            factory = pyutils.get_named_object(mod_name, factory_name)
 
2093
        except ImportError, e:
 
2094
            raise ImportError('failed to load %s: %s' % (full_name, e))
 
2095
        except AttributeError:
 
2096
            raise AttributeError('no factory %s in module %r'
 
2097
                % (full_name, sys.modules[mod_name]))
 
2098
        return factory()
 
2099
 
 
2100
    def helper():
 
2101
        bd = BzrDirMetaFormat1()
 
2102
        if branch_format is not None:
 
2103
            bd.set_branch_format(_load(branch_format))
 
2104
        if tree_format is not None:
 
2105
            bd.workingtree_format = _load(tree_format)
 
2106
        if repository_format is not None:
 
2107
            bd.repository_format = _load(repository_format)
 
2108
        return bd
 
2109
    registry.register(key, helper, help, native, deprecated, hidden,
 
2110
        experimental, alias)
 
2111
 
 
2112
register_metadir(controldir.format_registry, 'knit',
 
2113
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
 
2114
    'Format using knits.  Recommended for interoperation with bzr <= 0.14.',
 
2115
    branch_format='bzrlib.branch.BzrBranchFormat5',
 
2116
    tree_format='bzrlib.workingtree.WorkingTreeFormat3',
 
2117
    hidden=True,
 
2118
    deprecated=True)
 
2119
register_metadir(controldir.format_registry, 'dirstate',
 
2120
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
 
2121
    help='New in 0.15: Fast local operations. Compatible with bzr 0.8 and '
 
2122
        'above when accessed over the network.',
 
2123
    branch_format='bzrlib.branch.BzrBranchFormat5',
 
2124
    # this uses bzrlib.workingtree.WorkingTreeFormat4 because importing
 
2125
    # directly from workingtree_4 triggers a circular import.
 
2126
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
 
2127
    hidden=True,
 
2128
    deprecated=True)
 
2129
register_metadir(controldir.format_registry, 'dirstate-tags',
 
2130
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
 
2131
    help='New in 0.15: Fast local operations and improved scaling for '
 
2132
        'network operations. Additionally adds support for tags.'
 
2133
        ' Incompatible with bzr < 0.15.',
 
2134
    branch_format='bzrlib.branch.BzrBranchFormat6',
 
2135
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
 
2136
    hidden=True,
 
2137
    deprecated=True)
 
2138
register_metadir(controldir.format_registry, 'rich-root',
 
2139
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit4',
 
2140
    help='New in 1.0.  Better handling of tree roots.  Incompatible with'
 
2141
        ' bzr < 1.0.',
 
2142
    branch_format='bzrlib.branch.BzrBranchFormat6',
 
2143
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
 
2144
    hidden=True,
 
2145
    deprecated=True)
 
2146
register_metadir(controldir.format_registry, 'dirstate-with-subtree',
 
2147
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
 
2148
    help='New in 0.15: Fast local operations and improved scaling for '
 
2149
        'network operations. Additionally adds support for versioning nested '
 
2150
        'bzr branches. Incompatible with bzr < 0.15.',
 
2151
    branch_format='bzrlib.branch.BzrBranchFormat6',
 
2152
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
 
2153
    experimental=True,
 
2154
    hidden=True,
 
2155
    )
 
2156
register_metadir(controldir.format_registry, 'pack-0.92',
 
2157
    'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack1',
 
2158
    help='New in 0.92: Pack-based format with data compatible with '
 
2159
        'dirstate-tags format repositories. Interoperates with '
 
2160
        'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
 
2161
        ,
 
2162
    branch_format='bzrlib.branch.BzrBranchFormat6',
 
2163
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
 
2164
    )
 
2165
register_metadir(controldir.format_registry, 'pack-0.92-subtree',
 
2166
    'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack3',
 
2167
    help='New in 0.92: Pack-based format with data compatible with '
 
2168
        'dirstate-with-subtree format repositories. Interoperates with '
 
2169
        'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
 
2170
        ,
 
2171
    branch_format='bzrlib.branch.BzrBranchFormat6',
 
2172
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
 
2173
    hidden=True,
 
2174
    experimental=True,
 
2175
    )
 
2176
register_metadir(controldir.format_registry, 'rich-root-pack',
 
2177
    'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack4',
 
2178
    help='New in 1.0: A variant of pack-0.92 that supports rich-root data '
 
2179
         '(needed for bzr-svn and bzr-git).',
 
2180
    branch_format='bzrlib.branch.BzrBranchFormat6',
 
2181
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
 
2182
    hidden=True,
 
2183
    )
 
2184
register_metadir(controldir.format_registry, '1.6',
 
2185
    'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack5',
 
2186
    help='A format that allows a branch to indicate that there is another '
 
2187
         '(stacked) repository that should be used to access data that is '
 
2188
         'not present locally.',
 
2189
    branch_format='bzrlib.branch.BzrBranchFormat7',
 
2190
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
 
2191
    hidden=True,
 
2192
    )
 
2193
register_metadir(controldir.format_registry, '1.6.1-rich-root',
 
2194
    'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack5RichRoot',
 
2195
    help='A variant of 1.6 that supports rich-root data '
 
2196
         '(needed for bzr-svn and bzr-git).',
 
2197
    branch_format='bzrlib.branch.BzrBranchFormat7',
 
2198
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
 
2199
    hidden=True,
 
2200
    )
 
2201
register_metadir(controldir.format_registry, '1.9',
 
2202
    'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack6',
 
2203
    help='A repository format using B+tree indexes. These indexes '
 
2204
         'are smaller in size, have smarter caching and provide faster '
 
2205
         'performance for most operations.',
 
2206
    branch_format='bzrlib.branch.BzrBranchFormat7',
 
2207
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
 
2208
    hidden=True,
 
2209
    )
 
2210
register_metadir(controldir.format_registry, '1.9-rich-root',
 
2211
    'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack6RichRoot',
 
2212
    help='A variant of 1.9 that supports rich-root data '
 
2213
         '(needed for bzr-svn and bzr-git).',
 
2214
    branch_format='bzrlib.branch.BzrBranchFormat7',
 
2215
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
 
2216
    hidden=True,
 
2217
    )
 
2218
register_metadir(controldir.format_registry, '1.14',
 
2219
    'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack6',
 
2220
    help='A working-tree format that supports content filtering.',
 
2221
    branch_format='bzrlib.branch.BzrBranchFormat7',
 
2222
    tree_format='bzrlib.workingtree.WorkingTreeFormat5',
 
2223
    )
 
2224
register_metadir(controldir.format_registry, '1.14-rich-root',
 
2225
    'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack6RichRoot',
 
2226
    help='A variant of 1.14 that supports rich-root data '
 
2227
         '(needed for bzr-svn and bzr-git).',
 
2228
    branch_format='bzrlib.branch.BzrBranchFormat7',
 
2229
    tree_format='bzrlib.workingtree.WorkingTreeFormat5',
 
2230
    )
 
2231
# The following un-numbered 'development' formats should always just be aliases.
 
2232
register_metadir(controldir.format_registry, 'development-subtree',
 
2233
    'bzrlib.repofmt.groupcompress_repo.RepositoryFormat2aSubtree',
 
2234
    help='Current development format, subtree variant. Can convert data to and '
 
2235
        'from pack-0.92-subtree (and anything compatible with '
 
2236
        'pack-0.92-subtree) format repositories. Repositories and branches in '
 
2237
        'this format can only be read by bzr.dev. Please read '
 
2238
        'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
 
2239
        'before use.',
 
2240
    branch_format='bzrlib.branch.BzrBranchFormat7',
 
2241
    tree_format='bzrlib.workingtree.WorkingTreeFormat6',
 
2242
    experimental=True,
 
2243
    hidden=True,
 
2244
    alias=False, # Restore to being an alias when an actual development subtree format is added
 
2245
                 # This current non-alias status is simply because we did not introduce a
 
2246
                 # chk based subtree format.
 
2247
    )
 
2248
register_metadir(controldir.format_registry, 'development5-subtree',
 
2249
    'bzrlib.repofmt.knitpack_repo.RepositoryFormatPackDevelopment2Subtree',
 
2250
    help='Development format, subtree variant. Can convert data to and '
 
2251
        'from pack-0.92-subtree (and anything compatible with '
 
2252
        'pack-0.92-subtree) format repositories. Repositories and branches in '
 
2253
        'this format can only be read by bzr.dev. Please read '
 
2254
        'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
 
2255
        'before use.',
 
2256
    branch_format='bzrlib.branch.BzrBranchFormat7',
 
2257
    tree_format='bzrlib.workingtree.WorkingTreeFormat6',
 
2258
    experimental=True,
 
2259
    hidden=True,
 
2260
    alias=False,
 
2261
    )
 
2262
 
 
2263
# And the development formats above will have aliased one of the following:
 
2264
 
 
2265
# Finally, the current format.
 
2266
register_metadir(controldir.format_registry, '2a',
 
2267
    'bzrlib.repofmt.groupcompress_repo.RepositoryFormat2a',
 
2268
    help='First format for bzr 2.0 series.\n'
 
2269
        'Uses group-compress storage.\n'
 
2270
        'Provides rich roots which are a one-way transition.\n',
 
2271
        # 'storage in packs, 255-way hashed CHK inventory, bencode revision, group compress, '
 
2272
        # 'rich roots. Supported by bzr 1.16 and later.',
 
2273
    branch_format='bzrlib.branch.BzrBranchFormat7',
 
2274
    tree_format='bzrlib.workingtree.WorkingTreeFormat6',
 
2275
    experimental=False,
 
2276
    )
 
2277
 
 
2278
# The following format should be an alias for the rich root equivalent 
 
2279
# of the default format
 
2280
register_metadir(controldir.format_registry, 'default-rich-root',
 
2281
    'bzrlib.repofmt.groupcompress_repo.RepositoryFormat2a',
 
2282
    branch_format='bzrlib.branch.BzrBranchFormat7',
 
2283
    tree_format='bzrlib.workingtree.WorkingTreeFormat6',
 
2284
    alias=True,
 
2285
    hidden=True,
 
2286
    help='Same as 2a.')
 
2287
 
 
2288
# The current format that is made on 'bzr init'.
 
2289
format_name = config.GlobalConfig().get_user_option('default_format')
 
2290
if format_name is None:
 
2291
    controldir.format_registry.set_default('2a')
 
2292
else:
 
2293
    controldir.format_registry.set_default(format_name)
 
2294
 
 
2295
# XXX 2010-08-20 JRV: There is still a lot of code relying on
 
2296
# bzrlib.bzrdir.format_registry existing. When BzrDir.create/BzrDir.open/etc
 
2297
# get changed to ControlDir.create/ControlDir.open/etc this should be removed.
 
2298
format_registry = controldir.format_registry