/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: Robert Collins
  • Date: 2010-05-06 11:08:10 UTC
  • mto: This revision was merged to the branch mainline in revision 5223.
  • Revision ID: robertc@robertcollins.net-20100506110810-h3j07fh5gmw54s25
Cleaner matcher matching revised unlocking protocol.

Show diffs side-by-side

added added

removed removed

Lines of Context:
86
86
    registry,
87
87
    symbol_versioning,
88
88
    )
89
 
 
90
 
 
91
 
class BzrDir(object):
 
89
    
 
90
    
 
91
class ControlComponent(object):
 
92
    """Abstract base class for control directory components.
 
93
    
 
94
    This provides interfaces that are common across bzrdirs, 
 
95
    repositories, branches, and workingtree control directories.
 
96
    
 
97
    They all expose two urls and transports: the *user* URL is the 
 
98
    one that stops above the control directory (eg .bzr) and that 
 
99
    should normally be used in messages, and the *control* URL is
 
100
    under that in eg .bzr/checkout and is used to read the control
 
101
    files.
 
102
    
 
103
    This can be used as a mixin and is intended to fit with 
 
104
    foreign formats.
 
105
    """
 
106
    
 
107
    @property
 
108
    def control_transport(self):
 
109
        raise NotImplementedError
 
110
   
 
111
    @property
 
112
    def control_url(self):
 
113
        return self.control_transport.base
 
114
    
 
115
    @property
 
116
    def user_transport(self):
 
117
        raise NotImplementedError
 
118
        
 
119
    @property
 
120
    def user_url(self):
 
121
        return self.user_transport.base
 
122
    
 
123
 
 
124
class BzrDir(ControlComponent):
92
125
    """A .bzr control diretory.
93
126
 
94
127
    BzrDir instances let you create or open any of the things that can be
261
294
                # copied, and finally if we are copying up to a specific
262
295
                # revision_id then we can use the pending-ancestry-result which
263
296
                # does not require traversing all of history to describe it.
264
 
                if (result_repo.bzrdir.root_transport.base ==
265
 
                    result.root_transport.base and not require_stacking and
 
297
                if (result_repo.user_url == result.user_url
 
298
                    and not require_stacking and
266
299
                    revision_id is not None):
267
300
                    fetch_spec = graph.PendingAncestryResult(
268
301
                        [revision_id], local_repo)
355
388
                for subdir in sorted(subdirs, reverse=True):
356
389
                    pending.append(current_transport.clone(subdir))
357
390
 
 
391
    def list_branches(self):
 
392
        """Return a sequence of all branches local to this control directory.
 
393
 
 
394
        """
 
395
        try:
 
396
            return [self.open_branch()]
 
397
        except errors.NotBranchError:
 
398
            return []
 
399
 
358
400
    @staticmethod
359
401
    def find_branches(transport):
360
402
        """Find all branches under a transport.
372
414
            except errors.NoRepositoryPresent:
373
415
                pass
374
416
            else:
375
 
                return False, (None, repository)
376
 
            try:
377
 
                branch = bzrdir.open_branch()
378
 
            except errors.NotBranchError:
379
 
                return True, (None, None)
380
 
            else:
381
 
                return True, (branch, None)
382
 
        branches = []
383
 
        for branch, repo in BzrDir.find_bzrdirs(transport, evaluate=evaluate):
 
417
                return False, ([], repository)
 
418
            return True, (bzrdir.list_branches(), None)
 
419
        ret = []
 
420
        for branches, repo in BzrDir.find_bzrdirs(transport,
 
421
                                                  evaluate=evaluate):
384
422
            if repo is not None:
385
 
                branches.extend(repo.find_branches())
386
 
            if branch is not None:
387
 
                branches.append(branch)
388
 
        return branches
 
423
                ret.extend(repo.find_branches())
 
424
            if branches is not None:
 
425
                ret.extend(branches)
 
426
        return ret
389
427
 
390
428
    def destroy_repository(self):
391
429
        """Destroy the repository in this BzrDir"""
392
430
        raise NotImplementedError(self.destroy_repository)
393
431
 
394
 
    def create_branch(self):
 
432
    def create_branch(self, name=None):
395
433
        """Create a branch in this BzrDir.
396
434
 
 
435
        :param name: Name of the colocated branch to create, None for
 
436
            the default branch.
 
437
 
397
438
        The bzrdir's format will control what branch format is created.
398
439
        For more control see BranchFormatXX.create(a_bzrdir).
399
440
        """
400
441
        raise NotImplementedError(self.create_branch)
401
442
 
402
 
    def destroy_branch(self):
403
 
        """Destroy the branch in this BzrDir"""
 
443
    def destroy_branch(self, name=None):
 
444
        """Destroy a branch in this BzrDir.
 
445
        
 
446
        :param name: Name of the branch to destroy, None for the default 
 
447
            branch.
 
448
        """
404
449
        raise NotImplementedError(self.destroy_branch)
405
450
 
406
451
    @staticmethod
446
491
            stop = False
447
492
            stack_on = config.get_default_stack_on()
448
493
            if stack_on is not None:
449
 
                stack_on_pwd = found_bzrdir.root_transport.base
 
494
                stack_on_pwd = found_bzrdir.user_url
450
495
                stop = True
451
496
            # does it have a repository ?
452
497
            try:
454
499
            except errors.NoRepositoryPresent:
455
500
                repository = None
456
501
            else:
457
 
                if ((found_bzrdir.root_transport.base !=
458
 
                     self.root_transport.base) and not repository.is_shared()):
 
502
                if (found_bzrdir.user_url != self.user_url 
 
503
                    and not repository.is_shared()):
459
504
                    # Don't look higher, can't use a higher shared repo.
460
505
                    repository = None
461
506
                    stop = True
575
620
 
576
621
        :return: Tuple with old path name and new path name
577
622
        """
 
623
        def name_gen(base='backup.bzr'):
 
624
            counter = 1
 
625
            name = "%s.~%d~" % (base, counter)
 
626
            while self.root_transport.has(name):
 
627
                counter += 1
 
628
                name = "%s.~%d~" % (base, counter)
 
629
            return name
 
630
 
 
631
        backup_dir=name_gen()
578
632
        pb = ui.ui_factory.nested_progress_bar()
579
633
        try:
580
634
            # FIXME: bug 300001 -- the backup fails if the backup directory
581
635
            # already exists, but it should instead either remove it or make
582
636
            # a new backup directory.
583
637
            #
584
 
            # FIXME: bug 262450 -- the backup directory should have the same
585
 
            # permissions as the .bzr directory (probably a bug in copy_tree)
586
638
            old_path = self.root_transport.abspath('.bzr')
587
 
            new_path = self.root_transport.abspath('backup.bzr')
 
639
            new_path = self.root_transport.abspath(backup_dir)
588
640
            ui.ui_factory.note('making backup of %s\n  to %s' % (old_path, new_path,))
589
 
            self.root_transport.copy_tree('.bzr', 'backup.bzr')
 
641
            self.root_transport.copy_tree('.bzr', backup_dir)
590
642
            return (old_path, new_path)
591
643
        finally:
592
644
            pb.finished()
650
702
            if stop:
651
703
                return result
652
704
            next_transport = found_bzrdir.root_transport.clone('..')
653
 
            if (found_bzrdir.root_transport.base == next_transport.base):
 
705
            if (found_bzrdir.user_url == next_transport.base):
654
706
                # top of the file system
655
707
                return None
656
708
            # find the next containing bzrdir
673
725
                repository = found_bzrdir.open_repository()
674
726
            except errors.NoRepositoryPresent:
675
727
                return None, False
676
 
            if found_bzrdir.root_transport.base == self.root_transport.base:
 
728
            if found_bzrdir.user_url == self.user_url:
677
729
                return repository, True
678
730
            elif repository.is_shared():
679
731
                return repository, True
694
746
        """
695
747
        return None
696
748
 
697
 
    def get_branch_transport(self, branch_format):
 
749
    def get_branch_transport(self, branch_format, name=None):
698
750
        """Get the transport for use by branch format in this BzrDir.
699
751
 
700
752
        Note that bzr dirs that do not support format strings will raise
795
847
        :param _transport: the transport this dir is based at.
796
848
        """
797
849
        self._format = _format
 
850
        # these are also under the more standard names of 
 
851
        # control_transport and user_transport
798
852
        self.transport = _transport.clone('.bzr')
799
853
        self.root_transport = _transport
800
854
        self._mode_check_done = False
 
855
        
 
856
    @property 
 
857
    def user_transport(self):
 
858
        return self.root_transport
 
859
        
 
860
    @property
 
861
    def control_transport(self):
 
862
        return self.transport
801
863
 
802
864
    def is_control_filename(self, filename):
803
865
        """True if filename is the name of a path which is reserved for bzrdir's.
878
940
        BzrDir._check_supported(format, _unsupported)
879
941
        return format.open(transport, _found=True)
880
942
 
881
 
    def open_branch(self, unsupported=False, ignore_fallbacks=False):
 
943
    def open_branch(self, name=None, unsupported=False,
 
944
                    ignore_fallbacks=False):
882
945
        """Open the branch object at this BzrDir if one is present.
883
946
 
884
947
        If unsupported is True, then no longer supported branch formats can
1022
1085
        """
1023
1086
        raise NotImplementedError(self.open_workingtree)
1024
1087
 
1025
 
    def has_branch(self):
 
1088
    def has_branch(self, name=None):
1026
1089
        """Tell if this bzrdir contains a branch.
1027
1090
 
1028
1091
        Note: if you're going to open the branch, you should just go ahead
1030
1093
        branch and discards it, and that's somewhat expensive.)
1031
1094
        """
1032
1095
        try:
1033
 
            self.open_branch()
 
1096
            self.open_branch(name)
1034
1097
            return True
1035
1098
        except errors.NotBranchError:
1036
1099
            return False
1310
1373
        self.create_hook(hooks.HookPoint('pre_open',
1311
1374
            "Invoked before attempting to open a BzrDir with the transport "
1312
1375
            "that the open will use.", (1, 14), None))
 
1376
        self.create_hook(hooks.HookPoint('post_repo_init',
 
1377
            "Invoked after a repository has been initialized. "
 
1378
            "post_repo_init is called with a "
 
1379
            "bzrlib.bzrdir.RepoInitHookParams.",
 
1380
            (2, 2), None))
1313
1381
 
1314
1382
# install the default hooks
1315
1383
BzrDir.hooks = BzrDirHooks()
1316
1384
 
1317
1385
 
 
1386
class RepoInitHookParams(object):
 
1387
    """Object holding parameters passed to *_repo_init hooks.
 
1388
 
 
1389
    There are 4 fields that hooks may wish to access:
 
1390
 
 
1391
    :ivar repository: Repository created
 
1392
    :ivar format: Repository format
 
1393
    :ivar bzrdir: The bzrdir for the repository
 
1394
    :ivar shared: The repository is shared
 
1395
    """
 
1396
 
 
1397
    def __init__(self, repository, format, a_bzrdir, shared):
 
1398
        """Create a group of RepoInitHook parameters.
 
1399
 
 
1400
        :param repository: Repository created
 
1401
        :param format: Repository format
 
1402
        :param bzrdir: The bzrdir for the repository
 
1403
        :param shared: The repository is shared
 
1404
        """
 
1405
        self.repository = repository
 
1406
        self.format = format
 
1407
        self.bzrdir = a_bzrdir
 
1408
        self.shared = shared
 
1409
 
 
1410
    def __eq__(self, other):
 
1411
        return self.__dict__ == other.__dict__
 
1412
 
 
1413
    def __repr__(self):
 
1414
        if self.repository:
 
1415
            return "<%s for %s>" % (self.__class__.__name__,
 
1416
                self.repository)
 
1417
        else:
 
1418
            return "<%s for %s>" % (self.__class__.__name__,
 
1419
                self.bzrdir)
 
1420
 
 
1421
 
1318
1422
class BzrDirPreSplitOut(BzrDir):
1319
1423
    """A common class for the all-in-one formats."""
1320
1424
 
1359
1463
            tree.clone(result)
1360
1464
        return result
1361
1465
 
1362
 
    def create_branch(self):
 
1466
    def create_branch(self, name=None):
1363
1467
        """See BzrDir.create_branch."""
1364
 
        return self._format.get_branch_format().initialize(self)
 
1468
        return self._format.get_branch_format().initialize(self, name=name)
1365
1469
 
1366
 
    def destroy_branch(self):
 
1470
    def destroy_branch(self, name=None):
1367
1471
        """See BzrDir.destroy_branch."""
1368
1472
        raise errors.UnsupportedOperation(self.destroy_branch, self)
1369
1473
 
1425
1529
        raise errors.UnsupportedOperation(self.destroy_workingtree_metadata,
1426
1530
                                          self)
1427
1531
 
1428
 
    def get_branch_transport(self, branch_format):
 
1532
    def get_branch_transport(self, branch_format, name=None):
1429
1533
        """See BzrDir.get_branch_transport()."""
 
1534
        if name is not None:
 
1535
            raise errors.NoColocatedBranchSupport(self)
1430
1536
        if branch_format is None:
1431
1537
            return self.transport
1432
1538
        try:
1465
1571
            format = BzrDirFormat.get_default_format()
1466
1572
        return not isinstance(self._format, format.__class__)
1467
1573
 
1468
 
    def open_branch(self, unsupported=False, ignore_fallbacks=False):
 
1574
    def open_branch(self, name=None, unsupported=False,
 
1575
                    ignore_fallbacks=False):
1469
1576
        """See BzrDir.open_branch."""
1470
1577
        from bzrlib.branch import BzrBranchFormat4
1471
1578
        format = BzrBranchFormat4()
1472
1579
        self._check_supported(format, unsupported)
1473
 
        return format.open(self, _found=True)
 
1580
        return format.open(self, name, _found=True)
1474
1581
 
1475
1582
    def sprout(self, url, revision_id=None, force_new_repo=False,
1476
1583
               possible_transports=None, accelerator_tree=None,
1593
1700
        """See BzrDir.can_convert_format()."""
1594
1701
        return True
1595
1702
 
1596
 
    def create_branch(self):
 
1703
    def create_branch(self, name=None):
1597
1704
        """See BzrDir.create_branch."""
1598
 
        return self._format.get_branch_format().initialize(self)
 
1705
        return self._format.get_branch_format().initialize(self, name=name)
1599
1706
 
1600
 
    def destroy_branch(self):
 
1707
    def destroy_branch(self, name=None):
1601
1708
        """See BzrDir.create_branch."""
 
1709
        if name is not None:
 
1710
            raise errors.NoColocatedBranchSupport(self)
1602
1711
        self.transport.delete_tree('branch')
1603
1712
 
1604
1713
    def create_repository(self, shared=False):
1647
1756
        format = BranchFormat.find_format(self)
1648
1757
        return format.get_reference(self)
1649
1758
 
1650
 
    def get_branch_transport(self, branch_format):
 
1759
    def get_branch_transport(self, branch_format, name=None):
1651
1760
        """See BzrDir.get_branch_transport()."""
 
1761
        if name is not None:
 
1762
            raise errors.NoColocatedBranchSupport(self)
1652
1763
        # XXX: this shouldn't implicitly create the directory if it's just
1653
1764
        # promising to get a transport -- mbp 20090727
1654
1765
        if branch_format is None:
1725
1836
                return True
1726
1837
        except errors.NoRepositoryPresent:
1727
1838
            pass
1728
 
        try:
1729
 
            if not isinstance(self.open_branch()._format,
 
1839
        for branch in self.list_branches():
 
1840
            if not isinstance(branch._format,
1730
1841
                              format.get_branch_format().__class__):
1731
1842
                # the branch needs an upgrade.
1732
1843
                return True
1733
 
        except errors.NotBranchError:
1734
 
            pass
1735
1844
        try:
1736
1845
            my_wt = self.open_workingtree(recommend_upgrade=False)
1737
1846
            if not isinstance(my_wt._format,
1742
1851
            pass
1743
1852
        return False
1744
1853
 
1745
 
    def open_branch(self, unsupported=False, ignore_fallbacks=False):
 
1854
    def open_branch(self, name=None, unsupported=False,
 
1855
                    ignore_fallbacks=False):
1746
1856
        """See BzrDir.open_branch."""
1747
1857
        format = self.find_branch_format()
1748
1858
        self._check_supported(format, unsupported)
1749
 
        return format.open(self, _found=True, ignore_fallbacks=ignore_fallbacks)
 
1859
        return format.open(self, name=name,
 
1860
            _found=True, ignore_fallbacks=ignore_fallbacks)
1750
1861
 
1751
1862
    def open_repository(self, unsupported=False):
1752
1863
        """See BzrDir.open_repository."""
1784
1895
    Once a format is deprecated, just deprecate the initialize and open
1785
1896
    methods on the format class. Do not deprecate the object, as the
1786
1897
    object will be created every system load.
 
1898
 
 
1899
    :cvar colocated_branches: Whether this formats supports colocated branches.
1787
1900
    """
1788
1901
 
1789
1902
    _default_format = None
1806
1919
 
1807
1920
    _lock_file_name = 'branch-lock'
1808
1921
 
 
1922
    colocated_branches = False
 
1923
    """Whether co-located branches are supported for this control dir format.
 
1924
    """
 
1925
 
1809
1926
    # _lock_class must be set in subclasses to the lock type, typ.
1810
1927
    # TransportLock or LockDir
1811
1928
 
2618
2735
            if isinstance(self.bzrdir.transport, local.LocalTransport):
2619
2736
                self.bzrdir.get_workingtree_transport(None).delete('stat-cache')
2620
2737
            self._convert_to_weaves()
2621
 
            return BzrDir.open(self.bzrdir.root_transport.base)
 
2738
            return BzrDir.open(self.bzrdir.user_url)
2622
2739
        finally:
2623
2740
            self.pb.finished()
2624
2741
 
2871
2988
        try:
2872
2989
            ui.ui_factory.note('starting upgrade from format 5 to 6')
2873
2990
            self._convert_to_prefixed()
2874
 
            return BzrDir.open(self.bzrdir.root_transport.base)
 
2991
            return BzrDir.open(self.bzrdir.user_url)
2875
2992
        finally:
2876
2993
            pb.finished()
2877
2994
 
2999
3116
            BzrDirMetaFormat1().get_format_string(),
3000
3117
            mode=self.file_mode)
3001
3118
        self.pb.finished()
3002
 
        return BzrDir.open(self.bzrdir.root_transport.base)
 
3119
        return BzrDir.open(self.bzrdir.user_url)
3003
3120
 
3004
3121
    def make_lock(self, name):
3005
3122
        """Make a lock for the new control dir name."""
3054
3171
                ui.ui_factory.note('starting repository conversion')
3055
3172
                converter = CopyConverter(self.target_format.repository_format)
3056
3173
                converter.convert(repo, pb)
3057
 
        try:
3058
 
            branch = self.bzrdir.open_branch()
3059
 
        except errors.NotBranchError:
3060
 
            pass
3061
 
        else:
 
3174
        for branch in self.bzrdir.list_branches():
3062
3175
            # TODO: conversions of Branch and Tree should be done by
3063
3176
            # InterXFormat lookups/some sort of registry.
3064
3177
            # Avoid circular imports
3590
3703
            try:
3591
3704
                stack_on = urlutils.rebase_url(self._stack_on,
3592
3705
                    self._stack_on_pwd,
3593
 
                    branch.bzrdir.root_transport.base)
 
3706
                    branch.user_url)
3594
3707
            except errors.InvalidRebaseURLs:
3595
3708
                stack_on = self._get_full_stack_on()
3596
3709
        try: