~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/bzrdir.py

  • Committer: John Arbash Meinel
  • Date: 2009-03-04 17:02:18 UTC
  • mto: (0.17.34 trunk)
  • mto: This revision was merged to the branch mainline in revision 4280.
  • Revision ID: john@arbash-meinel.com-20090304170218-c3thty7hh2yfrnye
First cut at meta-info as text form.

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