Merge lp:~mbp/bzr/components into lp:bzr

Proposed by Martin Pool
Status: Merged
Approved by: bzr PQM
Approved revision: not available
Merged at revision: not available
Proposed branch: lp:~mbp/bzr/components
Merge into: lp:bzr
Diff against target: 846 lines (+215/-94)
20 files modified
NEWS (+8/-0)
bzrlib/branch.py (+32/-34)
bzrlib/builtins.py (+1/-3)
bzrlib/bzrdir.py (+57/-14)
bzrlib/check.py (+3/-3)
bzrlib/errors.py (+3/-3)
bzrlib/info.py (+6/-7)
bzrlib/reconcile.py (+1/-1)
bzrlib/reconfigure.py (+5/-6)
bzrlib/remote.py (+17/-4)
bzrlib/repofmt/weaverepo.py (+1/-1)
bzrlib/repository.py (+14/-7)
bzrlib/smart/bzrdir.py (+1/-1)
bzrlib/tests/per_branch/test_branch.py (+13/-0)
bzrlib/tests/per_bzrdir/test_bzrdir.py (+12/-0)
bzrlib/tests/per_repository/test_repository.py (+15/-0)
bzrlib/tests/per_workingtree/test_workingtree.py (+13/-0)
bzrlib/tests/test_foreign.py (+1/-0)
bzrlib/upgrade.py (+2/-3)
bzrlib/workingtree.py (+10/-7)
To merge this branch: bzr merge lp:~mbp/bzr/components
Reviewer Review Type Date Requested Status
Vincent Ladeuil Approve
Andrew Bennetts Approve
Review via email: mp+23827@code.launchpad.net

Commit message

(mbp) add ControlComponent base class

Description of the change

This adds a consistent interface for getting the control_transport and url (ie ends in .bzr/...) and the user_transport and url (doesn't) across branch, repository and bzrdir. At the moment there is some undesirable random variation across classes, and the names are not very obvious. This is a root cause behind us sometimes showing users urls containing .bzr when we don't really mean too.

I think those names are pretty clear but better suggestions are welcome.

As a followon I need to do this for wts but I thought I'd send this up to start with.

To post a comment you must log in.
Revision history for this message
Andrew Bennetts (spiv) wrote :

I like this! The new names are much much clearer. It seems a bit of a shame to create another mixin, but the new code is certainly much nicer.

review: Approve
Revision history for this message
Andrew Bennetts (spiv) wrote :

I know you want to do workingtrees before you land this, but also don't forget to write a NEWS entry.

Revision history for this message
Vincent Ladeuil (vila) wrote :

Sounds good, please land.

review: Approve
Revision history for this message
bzr PQM (bzr-pqm) wrote :

Successful steps
Failure output:
All lines of log output:
Executing star-merge http://bazaar.launchpad.net/~mbp/bzr/components at Tue Apr 27 09:01:40 2010
['Conflicts during merge: ', 'Text conflict in NEWS']

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'NEWS'
--- NEWS 2010-04-27 18:09:12 +0000
+++ NEWS 2010-04-28 07:06:33 +0000
@@ -64,6 +64,14 @@
64API Changes64API Changes
65***********65***********
6666
67* `BzrDir`, `Branch`, `Repository` and `WorkingTree` now all support `user_url`,
68 `user_transport`, `control_url` and `control_transport` members pointing
69 respectively to the directory containing the ``.bzr`` control directory,
70 and to the directory within ``.bzr`` used for the particular component.
71 All of them inherit from `ControlComponent` which provides default
72 implementations.
73 (Martin Pool)
74
67Internals75Internals
68*********76*********
6977
7078
=== modified file 'bzrlib/branch.py'
--- bzrlib/branch.py 2010-04-23 07:15:23 +0000
+++ bzrlib/branch.py 2010-04-28 07:06:33 +0000
@@ -63,23 +63,12 @@
63BZR_BRANCH_FORMAT_6 = "Bazaar Branch Format 6 (bzr 0.15)\n"63BZR_BRANCH_FORMAT_6 = "Bazaar Branch Format 6 (bzr 0.15)\n"
6464
6565
66# TODO: Maybe include checks for common corruption of newlines, etc?66class Branch(bzrdir.ControlComponent):
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
78class Branch(object):
79 """Branch holding a history of revisions.67 """Branch holding a history of revisions.
8068
81 base69 :ivar base:
82 Base directory/url of the branch.70 Base directory/url of the branch; using control_url and
71 control_transport is more standardized.
8372
84 hooks: An instance of BranchHooks.73 hooks: An instance of BranchHooks.
85 """74 """
@@ -87,6 +76,14 @@
87 # - RBC 2006011276 # - RBC 20060112
88 base = None77 base = None
8978
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
90 def __init__(self, *ignored, **ignored_too):87 def __init__(self, *ignored, **ignored_too):
91 self.tags = self._format.make_tags(self)88 self.tags = self._format.make_tags(self)
92 self._revision_history_cache = None89 self._revision_history_cache = None
@@ -107,7 +104,7 @@
107 """Activate the branch/repository from url as a fallback repository."""104 """Activate the branch/repository from url as a fallback repository."""
108 repo = self._get_fallback_repository(url)105 repo = self._get_fallback_repository(url)
109 if repo.has_same_location(self.repository):106 if repo.has_same_location(self.repository):
110 raise errors.UnstackableLocationError(self.base, url)107 raise errors.UnstackableLocationError(self.user_url, url)
111 self.repository.add_fallback_repository(repo)108 self.repository.add_fallback_repository(repo)
112109
113 def break_lock(self):110 def break_lock(self):
@@ -594,11 +591,11 @@
594 :param other: The branch to bind to591 :param other: The branch to bind to
595 :type other: Branch592 :type other: Branch
596 """593 """
597 raise errors.UpgradeRequired(self.base)594 raise errors.UpgradeRequired(self.user_url)
598595
599 def set_append_revisions_only(self, enabled):596 def set_append_revisions_only(self, enabled):
600 if not self._format.supports_set_append_revisions_only():597 if not self._format.supports_set_append_revisions_only():
601 raise errors.UpgradeRequired(self.base)598 raise errors.UpgradeRequired(self.user_url)
602 if enabled:599 if enabled:
603 value = 'True'600 value = 'True'
604 else:601 else:
@@ -652,7 +649,7 @@
652 def get_old_bound_location(self):649 def get_old_bound_location(self):
653 """Return the URL of the branch we used to be bound to650 """Return the URL of the branch we used to be bound to
654 """651 """
655 raise errors.UpgradeRequired(self.base)652 raise errors.UpgradeRequired(self.user_url)
656653
657 def get_commit_builder(self, parents, config=None, timestamp=None,654 def get_commit_builder(self, parents, config=None, timestamp=None,
658 timezone=None, committer=None, revprops=None,655 timezone=None, committer=None, revprops=None,
@@ -736,7 +733,7 @@
736 stacking.733 stacking.
737 """734 """
738 if not self._format.supports_stacking():735 if not self._format.supports_stacking():
739 raise errors.UnstackableBranchFormat(self._format, self.base)736 raise errors.UnstackableBranchFormat(self._format, self.user_url)
740 # XXX: Changing from one fallback repository to another does not check737 # XXX: Changing from one fallback repository to another does not check
741 # that all the data you need is present in the new fallback.738 # that all the data you need is present in the new fallback.
742 # Possibly it should.739 # Possibly it should.
@@ -893,7 +890,7 @@
893890
894 def unbind(self):891 def unbind(self):
895 """Older format branches cannot bind or unbind."""892 """Older format branches cannot bind or unbind."""
896 raise errors.UpgradeRequired(self.base)893 raise errors.UpgradeRequired(self.user_url)
897894
898 def last_revision(self):895 def last_revision(self):
899 """Return last revision id, or NULL_REVISION."""896 """Return last revision id, or NULL_REVISION."""
@@ -1059,7 +1056,7 @@
1059 try:1056 try:
1060 return urlutils.join(self.base[:-1], parent)1057 return urlutils.join(self.base[:-1], parent)
1061 except errors.InvalidURLJoin, e:1058 except errors.InvalidURLJoin, e:
1062 raise errors.InaccessibleParent(parent, self.base)1059 raise errors.InaccessibleParent(parent, self.user_url)
10631060
1064 def _get_parent_location(self):1061 def _get_parent_location(self):
1065 raise NotImplementedError(self._get_parent_location)1062 raise NotImplementedError(self._get_parent_location)
@@ -1564,7 +1561,7 @@
1564 elsewhere)1561 elsewhere)
1565 :return: a branch in this format1562 :return: a branch in this format
1566 """1563 """
1567 mutter('creating branch %r in %s', self, a_bzrdir.transport.base)1564 mutter('creating branch %r in %s', self, a_bzrdir.user_url)
1568 branch_transport = a_bzrdir.get_branch_transport(self, name=name)1565 branch_transport = a_bzrdir.get_branch_transport(self, name=name)
1569 lock_map = {1566 lock_map = {
1570 'metadir': ('lock', lockdir.LockDir),1567 'metadir': ('lock', lockdir.LockDir),
@@ -1957,8 +1954,8 @@
1957 if format.__class__ != self.__class__:1954 if format.__class__ != self.__class__:
1958 raise AssertionError("wrong format %r found for %r" %1955 raise AssertionError("wrong format %r found for %r" %
1959 (format, self))1956 (format, self))
1957 transport = a_bzrdir.get_branch_transport(None, name=name)
1960 try:1958 try:
1961 transport = a_bzrdir.get_branch_transport(None, name=name)
1962 control_files = lockable_files.LockableFiles(transport, 'lock',1959 control_files = lockable_files.LockableFiles(transport, 'lock',
1963 lockdir.LockDir)1960 lockdir.LockDir)
1964 return self._branch_class()(_format=self,1961 return self._branch_class()(_format=self,
@@ -2162,10 +2159,10 @@
2162 # this format does not implement branch itself, thus the implicit2159 # this format does not implement branch itself, thus the implicit
2163 # creation contract must see it as uninitializable2160 # creation contract must see it as uninitializable
2164 raise errors.UninitializableFormat(self)2161 raise errors.UninitializableFormat(self)
2165 mutter('creating branch reference in %s', a_bzrdir.transport.base)2162 mutter('creating branch reference in %s', a_bzrdir.user_url)
2166 branch_transport = a_bzrdir.get_branch_transport(self, name=name)2163 branch_transport = a_bzrdir.get_branch_transport(self, name=name)
2167 branch_transport.put_bytes('location',2164 branch_transport.put_bytes('location',
2168 target_branch.bzrdir.root_transport.base)2165 target_branch.bzrdir.user_url)
2169 branch_transport.put_bytes('format', self.get_format_string())2166 branch_transport.put_bytes('format', self.get_format_string())
2170 branch = self.open(2167 branch = self.open(
2171 a_bzrdir, name, _found=True,2168 a_bzrdir, name, _found=True,
@@ -2293,9 +2290,10 @@
22932290
2294 def __str__(self):2291 def __str__(self):
2295 if self.name is None:2292 if self.name is None:
2296 return '%s(%r)' % (self.__class__.__name__, self.base)2293 return '%s(%s)' % (self.__class__.__name__, self.user_url)
2297 else:2294 else:
2298 return '%s(%r,%r)' % (self.__class__.__name__, self.base, self.name)2295 return '%s(%s,%s)' % (self.__class__.__name__, self.user_url,
2296 self.name)
22992297
2300 __repr__ = __str__2298 __repr__ = __str__
23012299
@@ -2516,7 +2514,7 @@
2516 return result2514 return result
25172515
2518 def get_stacked_on_url(self):2516 def get_stacked_on_url(self):
2519 raise errors.UnstackableBranchFormat(self._format, self.base)2517 raise errors.UnstackableBranchFormat(self._format, self.user_url)
25202518
2521 def set_push_location(self, location):2519 def set_push_location(self, location):
2522 """See Branch.set_push_location."""2520 """See Branch.set_push_location."""
@@ -2712,7 +2710,7 @@
2712 if _mod_revision.is_null(last_revision):2710 if _mod_revision.is_null(last_revision):
2713 return2711 return
2714 if last_revision not in self._lefthand_history(revision_id):2712 if last_revision not in self._lefthand_history(revision_id):
2715 raise errors.AppendRevisionsOnlyViolation(self.base)2713 raise errors.AppendRevisionsOnlyViolation(self.user_url)
27162714
2717 def _gen_revision_history(self):2715 def _gen_revision_history(self):
2718 """Generate the revision history from last revision2716 """Generate the revision history from last revision
@@ -2818,7 +2816,7 @@
2818 if branch_location is None:2816 if branch_location is None:
2819 return Branch.reference_parent(self, file_id, path,2817 return Branch.reference_parent(self, file_id, path,
2820 possible_transports)2818 possible_transports)
2821 branch_location = urlutils.join(self.base, branch_location)2819 branch_location = urlutils.join(self.user_url, branch_location)
2822 return Branch.open(branch_location,2820 return Branch.open(branch_location,
2823 possible_transports=possible_transports)2821 possible_transports=possible_transports)
28242822
@@ -2939,7 +2937,7 @@
2939 """2937 """
29402938
2941 def get_stacked_on_url(self):2939 def get_stacked_on_url(self):
2942 raise errors.UnstackableBranchFormat(self._format, self.base)2940 raise errors.UnstackableBranchFormat(self._format, self.user_url)
29432941
29442942
2945######################################################################2943######################################################################
@@ -3032,7 +3030,7 @@
3032 :param verbose: Requests more detailed display of what was checked,3030 :param verbose: Requests more detailed display of what was checked,
3033 if any.3031 if any.
3034 """3032 """
3035 note('checked branch %s format %s', self.branch.base,3033 note('checked branch %s format %s', self.branch.user_url,
3036 self.branch._format)3034 self.branch._format)
3037 for error in self.errors:3035 for error in self.errors:
3038 note('found error:%s', error)3036 note('found error:%s', error)
@@ -3367,7 +3365,7 @@
3367 if local and not bound_location:3365 if local and not bound_location:
3368 raise errors.LocalRequiresBoundBranch()3366 raise errors.LocalRequiresBoundBranch()
3369 master_branch = None3367 master_branch = None
3370 if not local and bound_location and self.source.base != bound_location:3368 if not local and bound_location and self.source.user_url != bound_location:
3371 # not pulling from master, so we need to update master.3369 # not pulling from master, so we need to update master.
3372 master_branch = self.target.get_master_branch(possible_transports)3370 master_branch = self.target.get_master_branch(possible_transports)
3373 master_branch.lock_write()3371 master_branch.lock_write()
33743372
=== modified file 'bzrlib/builtins.py'
--- bzrlib/builtins.py 2010-04-23 11:11:22 +0000
+++ bzrlib/builtins.py 2010-04-28 07:06:33 +0000
@@ -504,9 +504,7 @@
504 if (working.has_changes()):504 if (working.has_changes()):
505 raise errors.UncommittedChanges(working)505 raise errors.UncommittedChanges(working)
506506
507 working_path = working.bzrdir.root_transport.base507 if working.user_url != working.branch.user_url:
508 branch_path = working.branch.bzrdir.root_transport.base
509 if working_path != branch_path:
510 raise errors.BzrCommandError("You cannot remove the working tree"508 raise errors.BzrCommandError("You cannot remove the working tree"
511 " from a lightweight checkout")509 " from a lightweight checkout")
512510
513511
=== modified file 'bzrlib/bzrdir.py'
--- bzrlib/bzrdir.py 2010-04-22 17:08:27 +0000
+++ bzrlib/bzrdir.py 2010-04-28 07:06:33 +0000
@@ -86,9 +86,42 @@
86 registry,86 registry,
87 symbol_versioning,87 symbol_versioning,
88 )88 )
8989
9090
91class BzrDir(object):91class 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
124class BzrDir(ControlComponent):
92 """A .bzr control diretory.125 """A .bzr control diretory.
93126
94 BzrDir instances let you create or open any of the things that can be127 BzrDir instances let you create or open any of the things that can be
@@ -261,8 +294,8 @@
261 # copied, and finally if we are copying up to a specific294 # copied, and finally if we are copying up to a specific
262 # revision_id then we can use the pending-ancestry-result which295 # revision_id then we can use the pending-ancestry-result which
263 # does not require traversing all of history to describe it.296 # does not require traversing all of history to describe it.
264 if (result_repo.bzrdir.root_transport.base ==297 if (result_repo.user_url == result.user_url
265 result.root_transport.base and not require_stacking and298 and not require_stacking and
266 revision_id is not None):299 revision_id is not None):
267 fetch_spec = graph.PendingAncestryResult(300 fetch_spec = graph.PendingAncestryResult(
268 [revision_id], local_repo)301 [revision_id], local_repo)
@@ -458,7 +491,7 @@
458 stop = False491 stop = False
459 stack_on = config.get_default_stack_on()492 stack_on = config.get_default_stack_on()
460 if stack_on is not None:493 if stack_on is not None:
461 stack_on_pwd = found_bzrdir.root_transport.base494 stack_on_pwd = found_bzrdir.user_url
462 stop = True495 stop = True
463 # does it have a repository ?496 # does it have a repository ?
464 try:497 try:
@@ -466,8 +499,8 @@
466 except errors.NoRepositoryPresent:499 except errors.NoRepositoryPresent:
467 repository = None500 repository = None
468 else:501 else:
469 if ((found_bzrdir.root_transport.base !=502 if (found_bzrdir.user_url != self.user_url
470 self.root_transport.base) and not repository.is_shared()):503 and not repository.is_shared()):
471 # Don't look higher, can't use a higher shared repo.504 # Don't look higher, can't use a higher shared repo.
472 repository = None505 repository = None
473 stop = True506 stop = True
@@ -669,7 +702,7 @@
669 if stop:702 if stop:
670 return result703 return result
671 next_transport = found_bzrdir.root_transport.clone('..')704 next_transport = found_bzrdir.root_transport.clone('..')
672 if (found_bzrdir.root_transport.base == next_transport.base):705 if (found_bzrdir.user_url == next_transport.base):
673 # top of the file system706 # top of the file system
674 return None707 return None
675 # find the next containing bzrdir708 # find the next containing bzrdir
@@ -692,7 +725,7 @@
692 repository = found_bzrdir.open_repository()725 repository = found_bzrdir.open_repository()
693 except errors.NoRepositoryPresent:726 except errors.NoRepositoryPresent:
694 return None, False727 return None, False
695 if found_bzrdir.root_transport.base == self.root_transport.base:728 if found_bzrdir.user_url == self.user_url:
696 return repository, True729 return repository, True
697 elif repository.is_shared():730 elif repository.is_shared():
698 return repository, True731 return repository, True
@@ -814,9 +847,19 @@
814 :param _transport: the transport this dir is based at.847 :param _transport: the transport this dir is based at.
815 """848 """
816 self._format = _format849 self._format = _format
850 # these are also under the more standard names of
851 # control_transport and user_transport
817 self.transport = _transport.clone('.bzr')852 self.transport = _transport.clone('.bzr')
818 self.root_transport = _transport853 self.root_transport = _transport
819 self._mode_check_done = False854 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
820863
821 def is_control_filename(self, filename):864 def is_control_filename(self, filename):
822 """True if filename is the name of a path which is reserved for bzrdir's.865 """True if filename is the name of a path which is reserved for bzrdir's.
@@ -2692,7 +2735,7 @@
2692 if isinstance(self.bzrdir.transport, local.LocalTransport):2735 if isinstance(self.bzrdir.transport, local.LocalTransport):
2693 self.bzrdir.get_workingtree_transport(None).delete('stat-cache')2736 self.bzrdir.get_workingtree_transport(None).delete('stat-cache')
2694 self._convert_to_weaves()2737 self._convert_to_weaves()
2695 return BzrDir.open(self.bzrdir.root_transport.base)2738 return BzrDir.open(self.bzrdir.user_url)
2696 finally:2739 finally:
2697 self.pb.finished()2740 self.pb.finished()
26982741
@@ -2945,7 +2988,7 @@
2945 try:2988 try:
2946 ui.ui_factory.note('starting upgrade from format 5 to 6')2989 ui.ui_factory.note('starting upgrade from format 5 to 6')
2947 self._convert_to_prefixed()2990 self._convert_to_prefixed()
2948 return BzrDir.open(self.bzrdir.root_transport.base)2991 return BzrDir.open(self.bzrdir.user_url)
2949 finally:2992 finally:
2950 pb.finished()2993 pb.finished()
29512994
@@ -3073,7 +3116,7 @@
3073 BzrDirMetaFormat1().get_format_string(),3116 BzrDirMetaFormat1().get_format_string(),
3074 mode=self.file_mode)3117 mode=self.file_mode)
3075 self.pb.finished()3118 self.pb.finished()
3076 return BzrDir.open(self.bzrdir.root_transport.base)3119 return BzrDir.open(self.bzrdir.user_url)
30773120
3078 def make_lock(self, name):3121 def make_lock(self, name):
3079 """Make a lock for the new control dir name."""3122 """Make a lock for the new control dir name."""
@@ -3660,7 +3703,7 @@
3660 try:3703 try:
3661 stack_on = urlutils.rebase_url(self._stack_on,3704 stack_on = urlutils.rebase_url(self._stack_on,
3662 self._stack_on_pwd,3705 self._stack_on_pwd,
3663 branch.bzrdir.root_transport.base)3706 branch.user_url)
3664 except errors.InvalidRebaseURLs:3707 except errors.InvalidRebaseURLs:
3665 stack_on = self._get_full_stack_on()3708 stack_on = self._get_full_stack_on()
3666 try:3709 try:
36673710
=== modified file 'bzrlib/check.py'
--- bzrlib/check.py 2009-09-18 01:06:10 +0000
+++ bzrlib/check.py 2010-04-28 07:06:33 +0000
@@ -192,8 +192,8 @@
192192
193 def _report_repo_results(self, verbose):193 def _report_repo_results(self, verbose):
194 note('checked repository %s format %s',194 note('checked repository %s format %s',
195 self.repository.bzrdir.root_transport,195 self.repository.user_url,
196 self.repository._format)196 self.repository._format)
197 note('%6d revisions', self.checked_rev_cnt)197 note('%6d revisions', self.checked_rev_cnt)
198 note('%6d file-ids', len(self.checked_weaves))198 note('%6d file-ids', len(self.checked_weaves))
199 if verbose:199 if verbose:
@@ -451,7 +451,7 @@
451 if do_repo or do_branch or do_tree:451 if do_repo or do_branch or do_tree:
452 if do_repo:452 if do_repo:
453 note("Checking repository at '%s'."453 note("Checking repository at '%s'."
454 % (repo.bzrdir.root_transport.base,))454 % (repo.user_url,))
455 result = repo.check(None, callback_refs=needed_refs,455 result = repo.check(None, callback_refs=needed_refs,
456 check_repo=do_repo)456 check_repo=do_repo)
457 result.report_results(verbose)457 result.report_results(verbose)
458458
=== modified file 'bzrlib/errors.py'
--- bzrlib/errors.py 2010-03-24 14:15:01 +0000
+++ bzrlib/errors.py 2010-04-28 07:06:33 +0000
@@ -2176,7 +2176,7 @@
21762176
2177 def __init__(self, repo):2177 def __init__(self, repo):
2178 BzrError.__init__(self)2178 BzrError.__init__(self)
2179 self.repo_path = repo.bzrdir.root_transport.base2179 self.repo_path = repo.user_url
21802180
21812181
2182class InconsistentDelta(BzrError):2182class InconsistentDelta(BzrError):
@@ -2754,7 +2754,7 @@
27542754
2755 def __init__(self, bzrdir):2755 def __init__(self, bzrdir):
2756 import bzrlib.urlutils as urlutils2756 import bzrlib.urlutils as urlutils
2757 display_url = urlutils.unescape_for_display(bzrdir.root_transport.base,2757 display_url = urlutils.unescape_for_display(bzrdir.user_url,
2758 'ascii')2758 'ascii')
2759 BzrError.__init__(self, bzrdir=bzrdir, display_url=display_url)2759 BzrError.__init__(self, bzrdir=bzrdir, display_url=display_url)
27602760
@@ -2835,7 +2835,7 @@
2835 more = ' ' + more2835 more = ' ' + more
2836 import bzrlib.urlutils as urlutils2836 import bzrlib.urlutils as urlutils
2837 display_url = urlutils.unescape_for_display(2837 display_url = urlutils.unescape_for_display(
2838 tree.bzrdir.root_transport.base, 'ascii')2838 tree.user_url, 'ascii')
2839 BzrError.__init__(self, tree=tree, display_url=display_url, more=more)2839 BzrError.__init__(self, tree=tree, display_url=display_url, more=more)
28402840
28412841
28422842
=== modified file 'bzrlib/info.py'
--- bzrlib/info.py 2010-02-17 17:11:16 +0000
+++ bzrlib/info.py 2010-04-28 07:06:33 +0000
@@ -80,9 +80,9 @@
8080
81def gather_location_info(repository, branch=None, working=None):81def gather_location_info(repository, branch=None, working=None):
82 locs = {}82 locs = {}
83 repository_path = repository.bzrdir.root_transport.base83 repository_path = repository.user_url
84 if branch is not None:84 if branch is not None:
85 branch_path = branch.bzrdir.root_transport.base85 branch_path = branch.user_url
86 master_path = branch.get_bound_location()86 master_path = branch.get_bound_location()
87 if master_path is None:87 if master_path is None:
88 master_path = branch_path88 master_path = branch_path
@@ -90,7 +90,7 @@
90 branch_path = None90 branch_path = None
91 master_path = None91 master_path = None
92 if working:92 if working:
93 working_path = working.bzrdir.root_transport.base93 working_path = working.user_url
94 if working_path != branch_path:94 if working_path != branch_path:
95 locs['light checkout root'] = working_path95 locs['light checkout root'] = working_path
96 if master_path != branch_path:96 if master_path != branch_path:
@@ -420,8 +420,8 @@
420 if branch is None and tree is not None:420 if branch is None and tree is not None:
421 phrase = "branchless tree"421 phrase = "branchless tree"
422 else:422 else:
423 if (tree is not None and tree.bzrdir.root_transport.base !=423 if (tree is not None and tree.user_url !=
424 branch.bzrdir.root_transport.base):424 branch.user_url):
425 independence = ''425 independence = ''
426 phrase = "Lightweight checkout"426 phrase = "Lightweight checkout"
427 elif branch.get_bound_location() is not None:427 elif branch.get_bound_location() is not None:
@@ -446,8 +446,7 @@
446 """446 """
447 candidates = []447 candidates = []
448 if (branch is not None and tree is not None and448 if (branch is not None and tree is not None and
449 branch.bzrdir.root_transport.base !=449 branch.user_url != tree.user_url):
450 tree.bzrdir.root_transport.base):
451 branch = None450 branch = None
452 repository = None451 repository = None
453 non_aliases = set(bzrdir.format_registry.keys())452 non_aliases = set(bzrdir.format_registry.keys())
454453
=== modified file 'bzrlib/reconcile.py'
--- bzrlib/reconcile.py 2010-02-17 17:11:16 +0000
+++ bzrlib/reconcile.py 2010-04-28 07:06:33 +0000
@@ -97,7 +97,7 @@
97 def _reconcile_repository(self):97 def _reconcile_repository(self):
98 self.repo = self.bzrdir.find_repository()98 self.repo = self.bzrdir.find_repository()
99 ui.ui_factory.note('Reconciling repository %s' %99 ui.ui_factory.note('Reconciling repository %s' %
100 self.repo.bzrdir.root_transport.base)100 self.repo.user_url)
101 self.pb.update("Reconciling repository", 0, 1)101 self.pb.update("Reconciling repository", 0, 1)
102 repo_reconciler = self.repo.reconcile(thorough=True)102 repo_reconciler = self.repo.reconcile(thorough=True)
103 self.inconsistent_parents = repo_reconciler.inconsistent_parents103 self.inconsistent_parents = repo_reconciler.inconsistent_parents
104104
=== modified file 'bzrlib/reconfigure.py'
--- bzrlib/reconfigure.py 2010-03-25 09:39:03 +0000
+++ bzrlib/reconfigure.py 2010-04-28 07:06:33 +0000
@@ -82,14 +82,13 @@
82 self.repository = None82 self.repository = None
83 self.local_repository = None83 self.local_repository = None
84 else:84 else:
85 if (self.repository.bzrdir.root_transport.base ==85 if (self.repository.user_url == self.bzrdir.user_url):
86 self.bzrdir.root_transport.base):
87 self.local_repository = self.repository86 self.local_repository = self.repository
88 else:87 else:
89 self.local_repository = None88 self.local_repository = None
90 try:89 try:
91 branch = self.bzrdir.open_branch()90 branch = self.bzrdir.open_branch()
92 if branch.bzrdir.root_transport.base == bzrdir.root_transport.base:91 if branch.user_url == bzrdir.user_url:
93 self.local_branch = branch92 self.local_branch = branch
94 self.referenced_branch = None93 self.referenced_branch = None
95 else:94 else:
@@ -217,8 +216,8 @@
217 if not want_reference:216 if not want_reference:
218 self._create_repository = True217 self._create_repository = True
219 else:218 else:
220 if want_reference and (self.repository.bzrdir.root_transport.base219 if want_reference and (
221 == self.bzrdir.root_transport.base):220 self.repository.user_url == self.bzrdir.user_url):
222 if not self.repository.is_shared():221 if not self.repository.is_shared():
223 self._destroy_repository = True222 self._destroy_repository = True
224 if self.referenced_branch is None:223 if self.referenced_branch is None:
@@ -344,7 +343,7 @@
344 if self._create_reference:343 if self._create_reference:
345 reference_branch.repository.fetch(self.repository)344 reference_branch.repository.fetch(self.repository)
346 elif self.local_branch is not None and not self._destroy_branch:345 elif self.local_branch is not None and not self._destroy_branch:
347 up = self.local_branch.bzrdir.root_transport.clone('..')346 up = self.local_branch.user_transport.clone('..')
348 up_bzrdir = bzrdir.BzrDir.open_containing_from_transport(up)[0]347 up_bzrdir = bzrdir.BzrDir.open_containing_from_transport(up)[0]
349 new_repo = up_bzrdir.find_repository()348 new_repo = up_bzrdir.find_repository()
350 new_repo.fetch(self.repository)349 new_repo.fetch(self.repository)
351350
=== modified file 'bzrlib/remote.py'
--- bzrlib/remote.py 2010-04-20 04:16:50 +0000
+++ bzrlib/remote.py 2010-04-28 07:06:33 +0000
@@ -643,7 +643,8 @@
643 return self._custom_format._serializer643 return self._custom_format._serializer
644644
645645
646class RemoteRepository(_RpcHelper, lock._RelockDebugMixin):646class RemoteRepository(_RpcHelper, lock._RelockDebugMixin,
647 bzrdir.ControlComponent):
647 """Repository accessed over rpc.648 """Repository accessed over rpc.
648649
649 For the moment most operations are performed using local transport-backed650 For the moment most operations are performed using local transport-backed
@@ -692,6 +693,17 @@
692 # Additional places to query for data.693 # Additional places to query for data.
693 self._fallback_repositories = []694 self._fallback_repositories = []
694695
696 @property
697 def user_transport(self):
698 return self.bzrdir.user_transport
699
700 @property
701 def control_transport(self):
702 # XXX: Normally you shouldn't directly get at the remote repository
703 # transport, but I'm not sure it's worth making this method
704 # optional -- mbp 2010-04-21
705 return self.bzrdir.get_repository_transport(None)
706
695 def __str__(self):707 def __str__(self):
696 return "%s(%s)" % (self.__class__.__name__, self.base)708 return "%s(%s)" % (self.__class__.__name__, self.base)
697709
@@ -1234,9 +1246,9 @@
1234 # _real_branch had its get_stacked_on_url method called), then the1246 # _real_branch had its get_stacked_on_url method called), then the
1235 # repository to be added may already be in the _real_repositories list.1247 # repository to be added may already be in the _real_repositories list.
1236 if self._real_repository is not None:1248 if self._real_repository is not None:
1237 fallback_locations = [repo.bzrdir.root_transport.base for repo in1249 fallback_locations = [repo.user_url for repo in
1238 self._real_repository._fallback_repositories]1250 self._real_repository._fallback_repositories]
1239 if repository.bzrdir.root_transport.base not in fallback_locations:1251 if repository.user_url not in fallback_locations:
1240 self._real_repository.add_fallback_repository(repository)1252 self._real_repository.add_fallback_repository(repository)
12411253
1242 def _check_fallback_repository(self, repository):1254 def _check_fallback_repository(self, repository):
@@ -2181,7 +2193,8 @@
2181 self._real_branch = None2193 self._real_branch = None
2182 # Fill out expected attributes of branch for bzrlib API users.2194 # Fill out expected attributes of branch for bzrlib API users.
2183 self._clear_cached_state()2195 self._clear_cached_state()
2184 self.base = self.bzrdir.root_transport.base2196 # TODO: deprecate self.base in favor of user_url
2197 self.base = self.bzrdir.user_url
2185 self._name = name2198 self._name = name
2186 self._control_files = None2199 self._control_files = None
2187 self._lock_mode = None2200 self._lock_mode = None
21882201
=== modified file 'bzrlib/repofmt/weaverepo.py'
--- bzrlib/repofmt/weaverepo.py 2010-04-26 13:51:08 +0000
+++ bzrlib/repofmt/weaverepo.py 2010-04-28 07:06:33 +0000
@@ -177,7 +177,7 @@
177 :param new_value: True to restore the default, False to disable making177 :param new_value: True to restore the default, False to disable making
178 working trees.178 working trees.
179 """179 """
180 raise errors.RepositoryUpgradeRequired(self.bzrdir.root_transport.base)180 raise errors.RepositoryUpgradeRequired(self.user_url)
181181
182 def make_working_trees(self):182 def make_working_trees(self):
183 """Returns the policy for making working trees on new branches."""183 """Returns the policy for making working trees on new branches."""
184184
=== modified file 'bzrlib/repository.py'
--- bzrlib/repository.py 2010-04-22 17:08:27 +0000
+++ bzrlib/repository.py 2010-04-28 07:06:33 +0000
@@ -864,7 +864,7 @@
864# Repositories864# Repositories
865865
866866
867class Repository(_RelockDebugMixin):867class Repository(_RelockDebugMixin, bzrdir.ControlComponent):
868 """Repository holding history for one or more branches.868 """Repository holding history for one or more branches.
869869
870 The repository holds and retrieves historical information including870 The repository holds and retrieves historical information including
@@ -1291,11 +1291,10 @@
12911291
1292 :param _format: The format of the repository on disk.1292 :param _format: The format of the repository on disk.
1293 :param a_bzrdir: The BzrDir of the repository.1293 :param a_bzrdir: The BzrDir of the repository.
1294
1295 In the future we will have a single api for all stores for
1296 getting file texts, inventories and revisions, then
1297 this construct will accept instances of those things.
1298 """1294 """
1295 # In the future we will have a single api for all stores for
1296 # getting file texts, inventories and revisions, then
1297 # this construct will accept instances of those things.
1299 super(Repository, self).__init__()1298 super(Repository, self).__init__()
1300 self._format = _format1299 self._format = _format
1301 # the following are part of the public API for Repository:1300 # the following are part of the public API for Repository:
@@ -1316,6 +1315,14 @@
1316 # rather copying them?1315 # rather copying them?
1317 self._safe_to_return_from_cache = False1316 self._safe_to_return_from_cache = False
13181317
1318 @property
1319 def user_transport(self):
1320 return self.bzrdir.user_transport
1321
1322 @property
1323 def control_transport(self):
1324 return self._transport
1325
1319 def __repr__(self):1326 def __repr__(self):
1320 if self._fallback_repositories:1327 if self._fallback_repositories:
1321 return '%s(%r, fallback_repositories=%r)' % (1328 return '%s(%r, fallback_repositories=%r)' % (
@@ -1469,7 +1476,7 @@
14691476
1470 # now gather global repository information1477 # now gather global repository information
1471 # XXX: This is available for many repos regardless of listability.1478 # XXX: This is available for many repos regardless of listability.
1472 if self.bzrdir.root_transport.listable():1479 if self.user_transport.listable():
1473 # XXX: do we want to __define len__() ?1480 # XXX: do we want to __define len__() ?
1474 # Maybe the versionedfiles object should provide a different1481 # Maybe the versionedfiles object should provide a different
1475 # method to get the number of keys.1482 # method to get the number of keys.
@@ -1507,7 +1514,7 @@
15071514
1508 ret = []1515 ret = []
1509 for branches, repository in bzrdir.BzrDir.find_bzrdirs(1516 for branches, repository in bzrdir.BzrDir.find_bzrdirs(
1510 self.bzrdir.root_transport, evaluate=Evaluator()):1517 self.user_transport, evaluate=Evaluator()):
1511 if branches is not None:1518 if branches is not None:
1512 ret.extend(branches)1519 ret.extend(branches)
1513 if not using and repository is not None:1520 if not using and repository is not None:
15141521
=== modified file 'bzrlib/smart/bzrdir.py'
--- bzrlib/smart/bzrdir.py 2010-02-17 17:11:16 +0000
+++ bzrlib/smart/bzrdir.py 2010-04-28 07:06:33 +0000
@@ -110,7 +110,7 @@
110 """Get the relative path for repository from current_transport."""110 """Get the relative path for repository from current_transport."""
111 # the relpath of the bzrdir in the found repository gives us the111 # the relpath of the bzrdir in the found repository gives us the
112 # path segments to pop-out.112 # path segments to pop-out.
113 relpath = repository.bzrdir.root_transport.relpath(113 relpath = repository.user_transport.relpath(
114 current_transport.base)114 current_transport.base)
115 if len(relpath):115 if len(relpath):
116 segments = ['..'] * len(relpath.split('/'))116 segments = ['..'] * len(relpath.split('/'))
117117
=== modified file 'bzrlib/tests/per_branch/test_branch.py'
--- bzrlib/tests/per_branch/test_branch.py 2010-03-02 22:25:58 +0000
+++ bzrlib/tests/per_branch/test_branch.py 2010-04-28 07:06:33 +0000
@@ -988,3 +988,16 @@
988 merger.do_merge()988 merger.do_merge()
989 self.assertEqual('../branch/reference',989 self.assertEqual('../branch/reference',
990 tree.branch.get_reference_info('file-id')[1])990 tree.branch.get_reference_info('file-id')[1])
991
992
993class TestBranchControlComponent(per_branch.TestCaseWithBranch):
994 """Branch implementations adequately implement ControlComponent."""
995
996 def test_urls(self):
997 br = self.make_branch('branch')
998 self.assertIsInstance(br.user_url, str)
999 self.assertEqual(br.user_url, br.user_transport.base)
1000 # for all current bzrdir implementations the user dir must be
1001 # above the control dir but we might need to relax that?
1002 self.assertEqual(br.control_url.find(br.user_url), 0)
1003 self.assertEqual(br.control_url, br.control_transport.base)
9911004
=== modified file 'bzrlib/tests/per_bzrdir/test_bzrdir.py'
--- bzrlib/tests/per_bzrdir/test_bzrdir.py 2010-04-11 19:40:23 +0000
+++ bzrlib/tests/per_bzrdir/test_bzrdir.py 2010-04-28 07:06:33 +0000
@@ -1971,3 +1971,15 @@
1971 self.assertRaises(errors.NoRepositoryPresent,1971 self.assertRaises(errors.NoRepositoryPresent,
1972 made_control.find_repository)1972 made_control.find_repository)
19731973
1974
1975class TestBzrDirControlComponent(TestCaseWithBzrDir):
1976 """BzrDir implementations adequately implement ControlComponent."""
1977
1978 def test_urls(self):
1979 bd = self.make_bzrdir('bd')
1980 self.assertIsInstance(bd.user_url, str)
1981 self.assertEqual(bd.user_url, bd.user_transport.base)
1982 # for all current bzrdir implementations the user dir must be
1983 # above the control dir but we might need to relax that?
1984 self.assertEqual(bd.control_url.find(bd.user_url), 0)
1985 self.assertEqual(bd.control_url, bd.control_transport.base)
19741986
=== modified file 'bzrlib/tests/per_repository/test_repository.py'
--- bzrlib/tests/per_repository/test_repository.py 2010-04-10 01:22:00 +0000
+++ bzrlib/tests/per_repository/test_repository.py 2010-04-28 07:06:33 +0000
@@ -1342,3 +1342,18 @@
1342 fileobj = StringIO()1342 fileobj = StringIO()
1343 wt.branch.repository.create_bundle(1343 wt.branch.repository.create_bundle(
1344 'rev1', _mod_revision.NULL_REVISION, fileobj)1344 'rev1', _mod_revision.NULL_REVISION, fileobj)
1345
1346
1347
1348
1349class TestRepositoryControlComponent(per_repository.TestCaseWithRepository):
1350 """Repository implementations adequately implement ControlComponent."""
1351
1352 def test_urls(self):
1353 repo = self.make_repository('repo')
1354 self.assertIsInstance(repo.user_url, str)
1355 self.assertEqual(repo.user_url, repo.user_transport.base)
1356 # for all current bzrdir implementations the user dir must be
1357 # above the control dir but we might need to relax that?
1358 self.assertEqual(repo.control_url.find(repo.user_url), 0)
1359 self.assertEqual(repo.control_url, repo.control_transport.base)
13451360
=== modified file 'bzrlib/tests/per_workingtree/test_workingtree.py'
--- bzrlib/tests/per_workingtree/test_workingtree.py 2010-03-02 22:25:58 +0000
+++ bzrlib/tests/per_workingtree/test_workingtree.py 2010-04-28 07:06:33 +0000
@@ -1091,3 +1091,16 @@
1091 # We should display the relative path1091 # We should display the relative path
1092 self.assertEqual('subdir/m\xb5', e.filename)1092 self.assertEqual('subdir/m\xb5', e.filename)
1093 self.assertEqual(osutils._fs_enc, e.fs_encoding)1093 self.assertEqual(osutils._fs_enc, e.fs_encoding)
1094
1095
1096class TestControlComponent(TestCaseWithWorkingTree):
1097 """WorkingTree implementations adequately implement ControlComponent."""
1098
1099 def test_urls(self):
1100 wt = self.make_branch_and_tree('wt')
1101 self.assertIsInstance(wt.user_url, str)
1102 self.assertEqual(wt.user_url, wt.user_transport.base)
1103 # for all current bzrdir implementations the user dir must be
1104 # above the control dir but we might need to relax that?
1105 self.assertEqual(wt.control_url.find(wt.user_url), 0)
1106 self.assertEqual(wt.control_url, wt.control_transport.base)
10941107
=== modified file 'bzrlib/tests/test_foreign.py'
--- bzrlib/tests/test_foreign.py 2010-03-02 22:25:58 +0000
+++ bzrlib/tests/test_foreign.py 2010-04-28 07:06:33 +0000
@@ -90,6 +90,7 @@
90 self._format = _format90 self._format = _format
91 self._base = a_bzrdir.transport.base91 self._base = a_bzrdir.transport.base
92 self._ignore_fallbacks = False92 self._ignore_fallbacks = False
93 self.bzrdir = a_bzrdir
93 foreign.ForeignBranch.__init__(self, 94 foreign.ForeignBranch.__init__(self,
94 DummyForeignVcsMapping(DummyForeignVcs()))95 DummyForeignVcsMapping(DummyForeignVcs()))
95 branch.BzrBranch6.__init__(self, _format, _control_files, a_bzrdir, 96 branch.BzrBranch6.__init__(self, _format, _control_files, a_bzrdir,
9697
=== modified file 'bzrlib/upgrade.py'
--- bzrlib/upgrade.py 2010-03-25 07:34:15 +0000
+++ bzrlib/upgrade.py 2010-04-28 07:06:33 +0000
@@ -47,11 +47,10 @@
47 def convert(self):47 def convert(self):
48 try:48 try:
49 branch = self.bzrdir.open_branch()49 branch = self.bzrdir.open_branch()
50 if branch.bzrdir.root_transport.base != \50 if branch.user_url != self.bzrdir.user_url:
51 self.bzrdir.root_transport.base:
52 ui.ui_factory.note("This is a checkout. The branch (%s) needs to be "51 ui.ui_factory.note("This is a checkout. The branch (%s) needs to be "
53 "upgraded separately." %52 "upgraded separately." %
54 branch.bzrdir.root_transport.base)53 branch.user_url)
55 del branch54 del branch
56 except (errors.NotBranchError, errors.IncompatibleRepositories):55 except (errors.NotBranchError, errors.IncompatibleRepositories):
57 # might not be a format we can open without upgrading; see e.g.56 # might not be a format we can open without upgrading; see e.g.
5857
=== modified file 'bzrlib/workingtree.py'
--- bzrlib/workingtree.py 2010-04-08 06:05:44 +0000
+++ bzrlib/workingtree.py 2010-04-28 07:06:33 +0000
@@ -29,12 +29,6 @@
29WorkingTree.open(dir).29WorkingTree.open(dir).
30"""30"""
3131
32# TODO: Give the workingtree sole responsibility for the working inventory;
33# remove the variable and references to it from the branch. This may require
34# updating the commit code so as to update the inventory within the working
35# copy, and making sure there's only one WorkingTree for any directory on disk.
36# At the moment they may alias the inventory and have old copies of it in
37# memory. (Now done? -- mbp 20060309)
3832
39from cStringIO import StringIO33from cStringIO import StringIO
40import os34import os
@@ -174,7 +168,8 @@
174 return ''168 return ''
175169
176170
177class WorkingTree(bzrlib.mutabletree.MutableTree):171class WorkingTree(bzrlib.mutabletree.MutableTree,
172 bzrdir.ControlComponent):
178 """Working copy tree.173 """Working copy tree.
179174
180 The inventory is held in the `Branch` working-inventory, and the175 The inventory is held in the `Branch` working-inventory, and the
@@ -253,6 +248,14 @@
253 self._rules_searcher = None248 self._rules_searcher = None
254 self.views = self._make_views()249 self.views = self._make_views()
255250
251 @property
252 def user_transport(self):
253 return self.bzrdir.user_transport
254
255 @property
256 def control_transport(self):
257 return self._transport
258
256 def _detect_case_handling(self):259 def _detect_case_handling(self):
257 wt_trans = self.bzrdir.get_workingtree_transport(None)260 wt_trans = self.bzrdir.get_workingtree_transport(None)
258 try:261 try: