/brz/remove-bazaar

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

« back to all changes in this revision

Viewing changes to bzrlib/bzrdir.py

  • Committer: Andrew Bennetts
  • Date: 2011-04-08 03:31:54 UTC
  • mfrom: (5766 +trunk)
  • mto: This revision was merged to the branch mainline in revision 5767.
  • Revision ID: andrew.bennetts@canonical.com-20110408033154-la08nghd4391sw5m
Merge latest lp:bzr, move our new release notes entries to the current release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
 
30
30
from bzrlib.lazy_import import lazy_import
31
31
lazy_import(globals(), """
32
 
from stat import S_ISDIR
33
 
 
34
32
import bzrlib
35
33
from bzrlib import (
 
34
    branch as _mod_branch,
 
35
    cleanup,
36
36
    config,
37
37
    controldir,
38
38
    errors,
 
39
    fetch,
39
40
    graph,
40
41
    lockable_files,
41
42
    lockdir,
47
48
    transport as _mod_transport,
48
49
    ui,
49
50
    urlutils,
50
 
    versionedfile,
51
51
    win32utils,
52
52
    workingtree,
53
53
    workingtree_4,
60
60
""")
61
61
 
62
62
from bzrlib.trace import (
 
63
    mutter,
63
64
    note,
64
65
    )
65
66
 
122
123
            # No repo, no problem.
123
124
            pass
124
125
 
125
 
    @staticmethod
126
 
    def _check_supported(format, allow_unsupported,
127
 
        recommend_upgrade=True,
128
 
        basedir=None):
129
 
        """Give an error or warning on old formats.
130
 
 
131
 
        :param format: may be any kind of format - workingtree, branch,
132
 
        or repository.
133
 
 
134
 
        :param allow_unsupported: If true, allow opening
135
 
        formats that are strongly deprecated, and which may
136
 
        have limited functionality.
137
 
 
138
 
        :param recommend_upgrade: If true (default), warn
139
 
        the user through the ui object that they may wish
140
 
        to upgrade the object.
141
 
        """
142
 
        # TODO: perhaps move this into a base Format class; it's not BzrDir
143
 
        # specific. mbp 20070323
144
 
        if not allow_unsupported and not format.is_supported():
145
 
            # see open_downlevel to open legacy branches.
146
 
            raise errors.UnsupportedFormatError(format=format)
147
 
        if recommend_upgrade \
148
 
            and getattr(format, 'upgrade_recommended', False):
149
 
            ui.ui_factory.recommend_upgrade(
150
 
                format.get_format_description(),
151
 
                basedir)
152
 
 
153
126
    def clone_on_transport(self, transport, revision_id=None,
154
127
        force_new_repo=False, preserve_stacking=False, stacked_on=None,
155
128
        create_prefix=False, use_existing_dir=True, no_tree=False):
415
388
        policy = self.determine_repository_policy(force_new_repo)
416
389
        return policy.acquire_repository()[0]
417
390
 
 
391
    def _find_source_repo(self, add_cleanup, source_branch):
 
392
        """Find the source branch and repo for a sprout operation.
 
393
        
 
394
        This is helper intended for use by _sprout.
 
395
 
 
396
        :returns: (source_branch, source_repository).  Either or both may be
 
397
            None.  If not None, they will be read-locked (and their unlock(s)
 
398
            scheduled via the add_cleanup param).
 
399
        """
 
400
        if source_branch is not None:
 
401
            add_cleanup(source_branch.lock_read().unlock)
 
402
            return source_branch, source_branch.repository
 
403
        try:
 
404
            source_branch = self.open_branch()
 
405
            source_repository = source_branch.repository
 
406
        except errors.NotBranchError:
 
407
            source_branch = None
 
408
            try:
 
409
                source_repository = self.open_repository()
 
410
            except errors.NoRepositoryPresent:
 
411
                source_repository = None
 
412
            else:
 
413
                add_cleanup(source_repository.lock_read().unlock)
 
414
        else:
 
415
            add_cleanup(source_branch.lock_read().unlock)
 
416
        return source_branch, source_repository
 
417
 
 
418
    def sprout(self, url, revision_id=None, force_new_repo=False,
 
419
               recurse='down', possible_transports=None,
 
420
               accelerator_tree=None, hardlink=False, stacked=False,
 
421
               source_branch=None, create_tree_if_local=True):
 
422
        """Create a copy of this controldir prepared for use as a new line of
 
423
        development.
 
424
 
 
425
        If url's last component does not exist, it will be created.
 
426
 
 
427
        Attributes related to the identity of the source branch like
 
428
        branch nickname will be cleaned, a working tree is created
 
429
        whether one existed before or not; and a local branch is always
 
430
        created.
 
431
 
 
432
        if revision_id is not None, then the clone operation may tune
 
433
            itself to download less data.
 
434
        :param accelerator_tree: A tree which can be used for retrieving file
 
435
            contents more quickly than the revision tree, i.e. a workingtree.
 
436
            The revision tree will be used for cases where accelerator_tree's
 
437
            content is different.
 
438
        :param hardlink: If true, hard-link files from accelerator_tree,
 
439
            where possible.
 
440
        :param stacked: If true, create a stacked branch referring to the
 
441
            location of this control directory.
 
442
        :param create_tree_if_local: If true, a working-tree will be created
 
443
            when working locally.
 
444
        """
 
445
        operation = cleanup.OperationWithCleanups(self._sprout)
 
446
        return operation.run(url, revision_id=revision_id,
 
447
            force_new_repo=force_new_repo, recurse=recurse,
 
448
            possible_transports=possible_transports,
 
449
            accelerator_tree=accelerator_tree, hardlink=hardlink,
 
450
            stacked=stacked, source_branch=source_branch,
 
451
            create_tree_if_local=create_tree_if_local)
 
452
 
 
453
    def _sprout(self, op, url, revision_id=None, force_new_repo=False,
 
454
               recurse='down', possible_transports=None,
 
455
               accelerator_tree=None, hardlink=False, stacked=False,
 
456
               source_branch=None, create_tree_if_local=True):
 
457
        add_cleanup = op.add_cleanup
 
458
        fetch_spec_factory = fetch.FetchSpecFactory()
 
459
        if revision_id is not None:
 
460
            fetch_spec_factory.add_revision_ids([revision_id])
 
461
            fetch_spec_factory.source_branch_stop_revision_id = revision_id
 
462
        target_transport = _mod_transport.get_transport(url,
 
463
            possible_transports)
 
464
        target_transport.ensure_base()
 
465
        cloning_format = self.cloning_metadir(stacked)
 
466
        # Create/update the result branch
 
467
        result = cloning_format.initialize_on_transport(target_transport)
 
468
        source_branch, source_repository = self._find_source_repo(
 
469
            add_cleanup, source_branch)
 
470
        fetch_spec_factory.source_branch = source_branch
 
471
        # if a stacked branch wasn't requested, we don't create one
 
472
        # even if the origin was stacked
 
473
        if stacked and source_branch is not None:
 
474
            stacked_branch_url = self.root_transport.base
 
475
        else:
 
476
            stacked_branch_url = None
 
477
        repository_policy = result.determine_repository_policy(
 
478
            force_new_repo, stacked_branch_url, require_stacking=stacked)
 
479
        result_repo, is_new_repo = repository_policy.acquire_repository()
 
480
        add_cleanup(result_repo.lock_write().unlock)
 
481
        fetch_spec_factory.source_repo = source_repository
 
482
        fetch_spec_factory.target_repo = result_repo
 
483
        if stacked or (len(result_repo._fallback_repositories) != 0):
 
484
            target_repo_kind = fetch.TargetRepoKinds.STACKED
 
485
        elif is_new_repo:
 
486
            target_repo_kind = fetch.TargetRepoKinds.EMPTY
 
487
        else:
 
488
            target_repo_kind = fetch.TargetRepoKinds.PREEXISTING
 
489
        fetch_spec_factory.target_repo_kind = target_repo_kind
 
490
        if source_repository is not None:
 
491
            fetch_spec = fetch_spec_factory.make_fetch_spec()
 
492
            result_repo.fetch(source_repository, fetch_spec=fetch_spec)
 
493
 
 
494
        if source_branch is None:
 
495
            # this is for sprouting a controldir without a branch; is that
 
496
            # actually useful?
 
497
            # Not especially, but it's part of the contract.
 
498
            result_branch = result.create_branch()
 
499
        else:
 
500
            result_branch = source_branch.sprout(result,
 
501
                revision_id=revision_id, repository_policy=repository_policy,
 
502
                repository=result_repo)
 
503
        mutter("created new branch %r" % (result_branch,))
 
504
 
 
505
        # Create/update the result working tree
 
506
        if (create_tree_if_local and
 
507
            isinstance(target_transport, local.LocalTransport) and
 
508
            (result_repo is None or result_repo.make_working_trees())):
 
509
            wt = result.create_workingtree(accelerator_tree=accelerator_tree,
 
510
                hardlink=hardlink, from_branch=result_branch)
 
511
            wt.lock_write()
 
512
            try:
 
513
                if wt.path2id('') is None:
 
514
                    try:
 
515
                        wt.set_root_id(self.open_workingtree.get_root_id())
 
516
                    except errors.NoWorkingTree:
 
517
                        pass
 
518
            finally:
 
519
                wt.unlock()
 
520
        else:
 
521
            wt = None
 
522
        if recurse == 'down':
 
523
            basis = None
 
524
            if wt is not None:
 
525
                basis = wt.basis_tree()
 
526
            elif result_branch is not None:
 
527
                basis = result_branch.basis_tree()
 
528
            elif source_branch is not None:
 
529
                basis = source_branch.basis_tree()
 
530
            if basis is not None:
 
531
                add_cleanup(basis.lock_read().unlock)
 
532
                subtrees = basis.iter_references()
 
533
            else:
 
534
                subtrees = []
 
535
            for path, file_id in subtrees:
 
536
                target = urlutils.join(url, urlutils.escape(path))
 
537
                sublocation = source_branch.reference_parent(file_id, path)
 
538
                sublocation.bzrdir.sprout(target,
 
539
                    basis.get_reference_revision(file_id, path),
 
540
                    force_new_repo=force_new_repo, recurse=recurse,
 
541
                    stacked=stacked)
 
542
        return result
 
543
 
 
544
 
 
545
 
418
546
    @staticmethod
419
547
    def create_branch_convenience(base, force_new_repo=False,
420
548
                                  force_new_tree=None, format=None,
729
857
        except errors.TooManyRedirections:
730
858
            raise errors.NotBranchError(base)
731
859
 
732
 
        BzrDir._check_supported(format, _unsupported)
 
860
        format.check_support_status(_unsupported)
733
861
        return format.open(transport, _found=True)
734
862
 
735
863
    @staticmethod
952
1080
 
953
1081
    def __init__(self):
954
1082
        """Create the default hooks."""
955
 
        hooks.Hooks.__init__(self)
956
 
        self.create_hook(hooks.HookPoint('pre_open',
 
1083
        hooks.Hooks.__init__(self, "bzrlib.bzrdir", "BzrDir.hooks")
 
1084
        self.add_hook('pre_open',
957
1085
            "Invoked before attempting to open a BzrDir with the transport "
958
 
            "that the open will use.", (1, 14), None))
959
 
        self.create_hook(hooks.HookPoint('post_repo_init',
 
1086
            "that the open will use.", (1, 14))
 
1087
        self.add_hook('post_repo_init',
960
1088
            "Invoked after a repository has been initialized. "
961
1089
            "post_repo_init is called with a "
962
1090
            "bzrlib.bzrdir.RepoInitHookParams.",
963
 
            (2, 2), None))
 
1091
            (2, 2))
964
1092
 
965
1093
# install the default hooks
966
1094
BzrDir.hooks = BzrDirHooks()
1169
1297
                    ignore_fallbacks=False):
1170
1298
        """See BzrDir.open_branch."""
1171
1299
        format = self.find_branch_format(name=name)
1172
 
        self._check_supported(format, unsupported)
 
1300
        format.check_support_status(unsupported)
1173
1301
        return format.open(self, name=name,
1174
1302
            _found=True, ignore_fallbacks=ignore_fallbacks)
1175
1303
 
1177
1305
        """See BzrDir.open_repository."""
1178
1306
        from bzrlib.repository import RepositoryFormat
1179
1307
        format = RepositoryFormat.find_format(self)
1180
 
        self._check_supported(format, unsupported)
 
1308
        format.check_support_status(unsupported)
1181
1309
        return format.open(self, _found=True)
1182
1310
 
1183
1311
    def open_workingtree(self, unsupported=False,
1185
1313
        """See BzrDir.open_workingtree."""
1186
1314
        from bzrlib.workingtree import WorkingTreeFormat
1187
1315
        format = WorkingTreeFormat.find_format(self)
1188
 
        self._check_supported(format, unsupported,
1189
 
            recommend_upgrade,
 
1316
        format.check_support_status(unsupported, recommend_upgrade,
1190
1317
            basedir=self.root_transport.base)
1191
1318
        return format.open(self, _found=True)
1192
1319
 
1731
1858
            # TODO: conversions of Branch and Tree should be done by
1732
1859
            # InterXFormat lookups/some sort of registry.
1733
1860
            # Avoid circular imports
1734
 
            from bzrlib import branch as _mod_branch
1735
1861
            old = branch._format.__class__
1736
1862
            new = self.target_format.get_branch_format().__class__
1737
1863
            while old != new: