/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/branch.py

  • Committer: Martin Pool
  • Date: 2010-04-27 07:52:08 UTC
  • mto: This revision was merged to the branch mainline in revision 5192.
  • Revision ID: mbp@sourcefrog.net-20100427075208-nc9uf6jgwlyy5r3k
Add osutils.rename that includes the relevant filenames

Show diffs side-by-side

added added

removed removed

Lines of Context:
49
49
from bzrlib.decorators import needs_read_lock, needs_write_lock, only_raises
50
50
from bzrlib.hooks import HookPoint, Hooks
51
51
from bzrlib.inter import InterObject
52
 
from bzrlib.lock import _RelockDebugMixin, LogicalLockResult
 
52
from bzrlib.lock import _RelockDebugMixin
53
53
from bzrlib import registry
54
54
from bzrlib.symbol_versioning import (
55
55
    deprecated_in,
63
63
BZR_BRANCH_FORMAT_6 = "Bazaar Branch Format 6 (bzr 0.15)\n"
64
64
 
65
65
 
66
 
class Branch(bzrdir.ControlComponent):
 
66
# TODO: Maybe include checks for common corruption of newlines, etc?
 
67
 
 
68
# TODO: Some operations like log might retrieve the same revisions
 
69
# repeatedly to calculate deltas.  We could perhaps have a weakref
 
70
# cache in memory to make this faster.  In general anything can be
 
71
# cached in memory between lock and unlock operations. .. nb thats
 
72
# what the transaction identity map provides
 
73
 
 
74
 
 
75
######################################################################
 
76
# branch objects
 
77
 
 
78
class Branch(object):
67
79
    """Branch holding a history of revisions.
68
80
 
69
 
    :ivar base:
70
 
        Base directory/url of the branch; using control_url and
71
 
        control_transport is more standardized.
 
81
    base
 
82
        Base directory/url of the branch.
72
83
 
73
84
    hooks: An instance of BranchHooks.
74
85
    """
76
87
    # - RBC 20060112
77
88
    base = None
78
89
 
79
 
    @property
80
 
    def control_transport(self):
81
 
        return self._transport
82
 
 
83
 
    @property
84
 
    def user_transport(self):
85
 
        return self.bzrdir.user_transport
86
 
 
87
90
    def __init__(self, *ignored, **ignored_too):
88
91
        self.tags = self._format.make_tags(self)
89
92
        self._revision_history_cache = None
104
107
        """Activate the branch/repository from url as a fallback repository."""
105
108
        repo = self._get_fallback_repository(url)
106
109
        if repo.has_same_location(self.repository):
107
 
            raise errors.UnstackableLocationError(self.user_url, url)
 
110
            raise errors.UnstackableLocationError(self.base, url)
108
111
        self.repository.add_fallback_repository(repo)
109
112
 
110
113
    def break_lock(self):
283
286
        new_history.reverse()
284
287
        return new_history
285
288
 
286
 
    def lock_write(self, token=None):
287
 
        """Lock the branch for write operations.
288
 
 
289
 
        :param token: A token to permit reacquiring a previously held and
290
 
            preserved lock.
291
 
        :return: A BranchWriteLockResult.
292
 
        """
 
289
    def lock_write(self):
293
290
        raise NotImplementedError(self.lock_write)
294
291
 
295
292
    def lock_read(self):
296
 
        """Lock the branch for read operations.
297
 
 
298
 
        :return: A bzrlib.lock.LogicalLockResult.
299
 
        """
300
293
        raise NotImplementedError(self.lock_read)
301
294
 
302
295
    def unlock(self):
427
420
            * 'include' - the stop revision is the last item in the result
428
421
            * 'with-merges' - include the stop revision and all of its
429
422
              merged revisions in the result
430
 
            * 'with-merges-without-common-ancestry' - filter out revisions 
431
 
              that are in both ancestries
432
423
        :param direction: either 'reverse' or 'forward':
433
424
            * reverse means return the start_revision_id first, i.e.
434
425
              start at the most recent revision and go backwards in history
465
456
            stop_revision_id, stop_rule)
466
457
        # Make sure we don't return revisions that are not part of the
467
458
        # start_revision_id ancestry.
468
 
        filtered = self._filter_start_non_ancestors(filtered)
 
459
        filtered = self._filter_non_ancestors(filtered)
469
460
        if direction == 'reverse':
470
461
            return filtered
471
462
        if direction == 'forward':
508
499
                       node.end_of_merge)
509
500
                if rev_id == stop_revision_id:
510
501
                    return
511
 
        elif stop_rule == 'with-merges-without-common-ancestry':
512
 
            # We want to exclude all revisions that are already part of the
513
 
            # stop_revision_id ancestry.
514
 
            graph = self.repository.get_graph()
515
 
            ancestors = graph.find_unique_ancestors(start_revision_id,
516
 
                                                    [stop_revision_id])
517
 
            for node in rev_iter:
518
 
                rev_id = node.key[-1]
519
 
                if rev_id not in ancestors:
520
 
                    continue
521
 
                yield (rev_id, node.merge_depth, node.revno,
522
 
                       node.end_of_merge)
523
502
        elif stop_rule == 'with-merges':
524
503
            stop_rev = self.repository.get_revision(stop_revision_id)
525
504
            if stop_rev.parent_ids:
548
527
        else:
549
528
            raise ValueError('invalid stop_rule %r' % stop_rule)
550
529
 
551
 
    def _filter_start_non_ancestors(self, rev_iter):
 
530
    def _filter_non_ancestors(self, rev_iter):
552
531
        # If we started from a dotted revno, we want to consider it as a tip
553
532
        # and don't want to yield revisions that are not part of its
554
533
        # ancestry. Given the order guaranteed by the merge sort, we will see
615
594
        :param other: The branch to bind to
616
595
        :type other: Branch
617
596
        """
618
 
        raise errors.UpgradeRequired(self.user_url)
 
597
        raise errors.UpgradeRequired(self.base)
619
598
 
620
599
    def set_append_revisions_only(self, enabled):
621
600
        if not self._format.supports_set_append_revisions_only():
622
 
            raise errors.UpgradeRequired(self.user_url)
 
601
            raise errors.UpgradeRequired(self.base)
623
602
        if enabled:
624
603
            value = 'True'
625
604
        else:
673
652
    def get_old_bound_location(self):
674
653
        """Return the URL of the branch we used to be bound to
675
654
        """
676
 
        raise errors.UpgradeRequired(self.user_url)
 
655
        raise errors.UpgradeRequired(self.base)
677
656
 
678
657
    def get_commit_builder(self, parents, config=None, timestamp=None,
679
658
                           timezone=None, committer=None, revprops=None,
757
736
            stacking.
758
737
        """
759
738
        if not self._format.supports_stacking():
760
 
            raise errors.UnstackableBranchFormat(self._format, self.user_url)
 
739
            raise errors.UnstackableBranchFormat(self._format, self.base)
761
740
        # XXX: Changing from one fallback repository to another does not check
762
741
        # that all the data you need is present in the new fallback.
763
742
        # Possibly it should.
914
893
 
915
894
    def unbind(self):
916
895
        """Older format branches cannot bind or unbind."""
917
 
        raise errors.UpgradeRequired(self.user_url)
 
896
        raise errors.UpgradeRequired(self.base)
918
897
 
919
898
    def last_revision(self):
920
899
        """Return last revision id, or NULL_REVISION."""
1080
1059
        try:
1081
1060
            return urlutils.join(self.base[:-1], parent)
1082
1061
        except errors.InvalidURLJoin, e:
1083
 
            raise errors.InaccessibleParent(parent, self.user_url)
 
1062
            raise errors.InaccessibleParent(parent, self.base)
1084
1063
 
1085
1064
    def _get_parent_location(self):
1086
1065
        raise NotImplementedError(self._get_parent_location)
1356
1335
        """
1357
1336
        # XXX: Fix the bzrdir API to allow getting the branch back from the
1358
1337
        # clone call. Or something. 20090224 RBC/spiv.
1359
 
        # XXX: Should this perhaps clone colocated branches as well, 
1360
 
        # rather than just the default branch? 20100319 JRV
1361
1338
        if revision_id is None:
1362
1339
            revision_id = self.last_revision()
1363
1340
        dir_to = self.bzrdir.clone_on_transport(to_transport,
1533
1510
        """Return the current default format."""
1534
1511
        return klass._default_format
1535
1512
 
1536
 
    def get_reference(self, a_bzrdir, name=None):
 
1513
    def get_reference(self, a_bzrdir):
1537
1514
        """Get the target reference of the branch in a_bzrdir.
1538
1515
 
1539
1516
        format probing must have been completed before calling
1541
1518
        in a_bzrdir is correct.
1542
1519
 
1543
1520
        :param a_bzrdir: The bzrdir to get the branch data from.
1544
 
        :param name: Name of the colocated branch to fetch
1545
1521
        :return: None if the branch is not a reference branch.
1546
1522
        """
1547
1523
        return None
1548
1524
 
1549
1525
    @classmethod
1550
 
    def set_reference(self, a_bzrdir, name, to_branch):
 
1526
    def set_reference(self, a_bzrdir, to_branch):
1551
1527
        """Set the target reference of the branch in a_bzrdir.
1552
1528
 
1553
1529
        format probing must have been completed before calling
1555
1531
        in a_bzrdir is correct.
1556
1532
 
1557
1533
        :param a_bzrdir: The bzrdir to set the branch reference for.
1558
 
        :param name: Name of colocated branch to set, None for default
1559
1534
        :param to_branch: branch that the checkout is to reference
1560
1535
        """
1561
1536
        raise NotImplementedError(self.set_reference)
1589
1564
            elsewhere)
1590
1565
        :return: a branch in this format
1591
1566
        """
1592
 
        mutter('creating branch %r in %s', self, a_bzrdir.user_url)
 
1567
        mutter('creating branch %r in %s', self, a_bzrdir.transport.base)
1593
1568
        branch_transport = a_bzrdir.get_branch_transport(self, name=name)
1594
1569
        lock_map = {
1595
1570
            'metadir': ('lock', lockdir.LockDir),
1982
1957
            if format.__class__ != self.__class__:
1983
1958
                raise AssertionError("wrong format %r found for %r" %
1984
1959
                    (format, self))
1985
 
        transport = a_bzrdir.get_branch_transport(None, name=name)
1986
1960
        try:
 
1961
            transport = a_bzrdir.get_branch_transport(None, name=name)
1987
1962
            control_files = lockable_files.LockableFiles(transport, 'lock',
1988
1963
                                                         lockdir.LockDir)
1989
1964
            return self._branch_class()(_format=self,
2171
2146
        """See BranchFormat.get_format_description()."""
2172
2147
        return "Checkout reference format 1"
2173
2148
 
2174
 
    def get_reference(self, a_bzrdir, name=None):
 
2149
    def get_reference(self, a_bzrdir):
2175
2150
        """See BranchFormat.get_reference()."""
2176
 
        transport = a_bzrdir.get_branch_transport(None, name=name)
 
2151
        transport = a_bzrdir.get_branch_transport(None)
2177
2152
        return transport.get_bytes('location')
2178
2153
 
2179
 
    def set_reference(self, a_bzrdir, name, to_branch):
 
2154
    def set_reference(self, a_bzrdir, to_branch):
2180
2155
        """See BranchFormat.set_reference()."""
2181
 
        transport = a_bzrdir.get_branch_transport(None, name=name)
 
2156
        transport = a_bzrdir.get_branch_transport(None)
2182
2157
        location = transport.put_bytes('location', to_branch.base)
2183
2158
 
2184
2159
    def initialize(self, a_bzrdir, name=None, target_branch=None):
2187
2162
            # this format does not implement branch itself, thus the implicit
2188
2163
            # creation contract must see it as uninitializable
2189
2164
            raise errors.UninitializableFormat(self)
2190
 
        mutter('creating branch reference in %s', a_bzrdir.user_url)
 
2165
        mutter('creating branch reference in %s', a_bzrdir.transport.base)
2191
2166
        branch_transport = a_bzrdir.get_branch_transport(self, name=name)
2192
2167
        branch_transport.put_bytes('location',
2193
 
            target_branch.bzrdir.user_url)
 
2168
            target_branch.bzrdir.root_transport.base)
2194
2169
        branch_transport.put_bytes('format', self.get_format_string())
2195
2170
        branch = self.open(
2196
2171
            a_bzrdir, name, _found=True,
2235
2210
                raise AssertionError("wrong format %r found for %r" %
2236
2211
                    (format, self))
2237
2212
        if location is None:
2238
 
            location = self.get_reference(a_bzrdir, name)
 
2213
            location = self.get_reference(a_bzrdir)
2239
2214
        real_bzrdir = bzrdir.BzrDir.open(
2240
2215
            location, possible_transports=possible_transports)
2241
2216
        result = real_bzrdir.open_branch(name=name, 
2279
2254
    _legacy_formats[0].network_name(), _legacy_formats[0].__class__)
2280
2255
 
2281
2256
 
2282
 
class BranchWriteLockResult(LogicalLockResult):
2283
 
    """The result of write locking a branch.
2284
 
 
2285
 
    :ivar branch_token: The token obtained from the underlying branch lock, or
2286
 
        None.
2287
 
    :ivar unlock: A callable which will unlock the lock.
2288
 
    """
2289
 
 
2290
 
    def __init__(self, unlock, branch_token):
2291
 
        LogicalLockResult.__init__(self, unlock)
2292
 
        self.branch_token = branch_token
2293
 
 
2294
 
    def __repr__(self):
2295
 
        return "BranchWriteLockResult(%s, %s)" % (self.branch_token,
2296
 
            self.unlock)
2297
 
 
2298
 
 
2299
2257
class BzrBranch(Branch, _RelockDebugMixin):
2300
2258
    """A branch stored in the actual filesystem.
2301
2259
 
2335
2293
 
2336
2294
    def __str__(self):
2337
2295
        if self.name is None:
2338
 
            return '%s(%s)' % (self.__class__.__name__, self.user_url)
 
2296
            return '%s(%r)' % (self.__class__.__name__, self.base)
2339
2297
        else:
2340
 
            return '%s(%s,%s)' % (self.__class__.__name__, self.user_url,
2341
 
                self.name)
 
2298
            return '%s(%r,%r)' % (self.__class__.__name__, self.base, self.name)
2342
2299
 
2343
2300
    __repr__ = __str__
2344
2301
 
2355
2312
        return self.control_files.is_locked()
2356
2313
 
2357
2314
    def lock_write(self, token=None):
2358
 
        """Lock the branch for write operations.
2359
 
 
2360
 
        :param token: A token to permit reacquiring a previously held and
2361
 
            preserved lock.
2362
 
        :return: A BranchWriteLockResult.
2363
 
        """
2364
2315
        if not self.is_locked():
2365
2316
            self._note_lock('w')
2366
2317
        # All-in-one needs to always unlock/lock.
2372
2323
        else:
2373
2324
            took_lock = False
2374
2325
        try:
2375
 
            return BranchWriteLockResult(self.unlock,
2376
 
                self.control_files.lock_write(token=token))
 
2326
            return self.control_files.lock_write(token=token)
2377
2327
        except:
2378
2328
            if took_lock:
2379
2329
                self.repository.unlock()
2380
2330
            raise
2381
2331
 
2382
2332
    def lock_read(self):
2383
 
        """Lock the branch for read operations.
2384
 
 
2385
 
        :return: A bzrlib.lock.LogicalLockResult.
2386
 
        """
2387
2333
        if not self.is_locked():
2388
2334
            self._note_lock('r')
2389
2335
        # All-in-one needs to always unlock/lock.
2396
2342
            took_lock = False
2397
2343
        try:
2398
2344
            self.control_files.lock_read()
2399
 
            return LogicalLockResult(self.unlock)
2400
2345
        except:
2401
2346
            if took_lock:
2402
2347
                self.repository.unlock()
2571
2516
        return result
2572
2517
 
2573
2518
    def get_stacked_on_url(self):
2574
 
        raise errors.UnstackableBranchFormat(self._format, self.user_url)
 
2519
        raise errors.UnstackableBranchFormat(self._format, self.base)
2575
2520
 
2576
2521
    def set_push_location(self, location):
2577
2522
        """See Branch.set_push_location."""
2767
2712
        if _mod_revision.is_null(last_revision):
2768
2713
            return
2769
2714
        if last_revision not in self._lefthand_history(revision_id):
2770
 
            raise errors.AppendRevisionsOnlyViolation(self.user_url)
 
2715
            raise errors.AppendRevisionsOnlyViolation(self.base)
2771
2716
 
2772
2717
    def _gen_revision_history(self):
2773
2718
        """Generate the revision history from last revision
2873
2818
        if branch_location is None:
2874
2819
            return Branch.reference_parent(self, file_id, path,
2875
2820
                                           possible_transports)
2876
 
        branch_location = urlutils.join(self.user_url, branch_location)
 
2821
        branch_location = urlutils.join(self.base, branch_location)
2877
2822
        return Branch.open(branch_location,
2878
2823
                           possible_transports=possible_transports)
2879
2824
 
2994
2939
    """
2995
2940
 
2996
2941
    def get_stacked_on_url(self):
2997
 
        raise errors.UnstackableBranchFormat(self._format, self.user_url)
 
2942
        raise errors.UnstackableBranchFormat(self._format, self.base)
2998
2943
 
2999
2944
 
3000
2945
######################################################################
3087
3032
        :param verbose: Requests more detailed display of what was checked,
3088
3033
            if any.
3089
3034
        """
3090
 
        note('checked branch %s format %s', self.branch.user_url,
 
3035
        note('checked branch %s format %s', self.branch.base,
3091
3036
            self.branch._format)
3092
3037
        for error in self.errors:
3093
3038
            note('found error:%s', error)
3422
3367
        if local and not bound_location:
3423
3368
            raise errors.LocalRequiresBoundBranch()
3424
3369
        master_branch = None
3425
 
        if not local and bound_location and self.source.user_url != bound_location:
 
3370
        if not local and bound_location and self.source.base != bound_location:
3426
3371
            # not pulling from master, so we need to update master.
3427
3372
            master_branch = self.target.get_master_branch(possible_transports)
3428
3373
            master_branch.lock_write()