~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/bzrdir.py

  • Committer: John Arbash Meinel
  • Date: 2005-11-30 15:43:57 UTC
  • mto: (1185.50.1 jam-integration)
  • mto: This revision was merged to the branch mainline in revision 1518.
  • Revision ID: john@arbash-meinel.com-20051130154357-614206b3a7b83cd0
Refactored bzrlib/ui.py into a module with the possibility for multiple ui forms.

Show diffs side-by-side

added added

removed removed

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