Merge lp:~mbp/bzr/components into lp:bzr
- components
- Merge into bzr.dev
| Status: | Merged |
|---|---|
| Approved by: | bzr PQM on 2010-04-27 |
| 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 |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Vincent Ladeuil | 2010-04-27 | Approve on 2010-04-27 | |
| Andrew Bennetts | 2010-04-21 | Approve on 2010-04-22 | |
|
Review via email:
|
|||
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.
| 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.
| bzr PQM (bzr-pqm) wrote : | # |
Successful steps
Failure output:
All lines of log output:
Executing star-merge http://
['Conflicts during merge: ', 'Text conflict in NEWS']
- 5172. By Martin Pool on 2010-04-28
-
merge news
Preview Diff
| 1 | === modified file 'NEWS' |
| 2 | --- NEWS 2010-04-27 18:09:12 +0000 |
| 3 | +++ NEWS 2010-04-28 07:06:33 +0000 |
| 4 | @@ -64,6 +64,14 @@ |
| 5 | API Changes |
| 6 | *********** |
| 7 | |
| 8 | +* `BzrDir`, `Branch`, `Repository` and `WorkingTree` now all support `user_url`, |
| 9 | + `user_transport`, `control_url` and `control_transport` members pointing |
| 10 | + respectively to the directory containing the ``.bzr`` control directory, |
| 11 | + and to the directory within ``.bzr`` used for the particular component. |
| 12 | + All of them inherit from `ControlComponent` which provides default |
| 13 | + implementations. |
| 14 | + (Martin Pool) |
| 15 | + |
| 16 | Internals |
| 17 | ********* |
| 18 | |
| 19 | |
| 20 | === modified file 'bzrlib/branch.py' |
| 21 | --- bzrlib/branch.py 2010-04-23 07:15:23 +0000 |
| 22 | +++ bzrlib/branch.py 2010-04-28 07:06:33 +0000 |
| 23 | @@ -63,23 +63,12 @@ |
| 24 | BZR_BRANCH_FORMAT_6 = "Bazaar Branch Format 6 (bzr 0.15)\n" |
| 25 | |
| 26 | |
| 27 | -# TODO: Maybe include checks for common corruption of newlines, etc? |
| 28 | - |
| 29 | -# TODO: Some operations like log might retrieve the same revisions |
| 30 | -# repeatedly to calculate deltas. We could perhaps have a weakref |
| 31 | -# cache in memory to make this faster. In general anything can be |
| 32 | -# cached in memory between lock and unlock operations. .. nb thats |
| 33 | -# what the transaction identity map provides |
| 34 | - |
| 35 | - |
| 36 | -###################################################################### |
| 37 | -# branch objects |
| 38 | - |
| 39 | -class Branch(object): |
| 40 | +class Branch(bzrdir.ControlComponent): |
| 41 | """Branch holding a history of revisions. |
| 42 | |
| 43 | - base |
| 44 | - Base directory/url of the branch. |
| 45 | + :ivar base: |
| 46 | + Base directory/url of the branch; using control_url and |
| 47 | + control_transport is more standardized. |
| 48 | |
| 49 | hooks: An instance of BranchHooks. |
| 50 | """ |
| 51 | @@ -87,6 +76,14 @@ |
| 52 | # - RBC 20060112 |
| 53 | base = None |
| 54 | |
| 55 | + @property |
| 56 | + def control_transport(self): |
| 57 | + return self._transport |
| 58 | + |
| 59 | + @property |
| 60 | + def user_transport(self): |
| 61 | + return self.bzrdir.user_transport |
| 62 | + |
| 63 | def __init__(self, *ignored, **ignored_too): |
| 64 | self.tags = self._format.make_tags(self) |
| 65 | self._revision_history_cache = None |
| 66 | @@ -107,7 +104,7 @@ |
| 67 | """Activate the branch/repository from url as a fallback repository.""" |
| 68 | repo = self._get_fallback_repository(url) |
| 69 | if repo.has_same_location(self.repository): |
| 70 | - raise errors.UnstackableLocationError(self.base, url) |
| 71 | + raise errors.UnstackableLocationError(self.user_url, url) |
| 72 | self.repository.add_fallback_repository(repo) |
| 73 | |
| 74 | def break_lock(self): |
| 75 | @@ -594,11 +591,11 @@ |
| 76 | :param other: The branch to bind to |
| 77 | :type other: Branch |
| 78 | """ |
| 79 | - raise errors.UpgradeRequired(self.base) |
| 80 | + raise errors.UpgradeRequired(self.user_url) |
| 81 | |
| 82 | def set_append_revisions_only(self, enabled): |
| 83 | if not self._format.supports_set_append_revisions_only(): |
| 84 | - raise errors.UpgradeRequired(self.base) |
| 85 | + raise errors.UpgradeRequired(self.user_url) |
| 86 | if enabled: |
| 87 | value = 'True' |
| 88 | else: |
| 89 | @@ -652,7 +649,7 @@ |
| 90 | def get_old_bound_location(self): |
| 91 | """Return the URL of the branch we used to be bound to |
| 92 | """ |
| 93 | - raise errors.UpgradeRequired(self.base) |
| 94 | + raise errors.UpgradeRequired(self.user_url) |
| 95 | |
| 96 | def get_commit_builder(self, parents, config=None, timestamp=None, |
| 97 | timezone=None, committer=None, revprops=None, |
| 98 | @@ -736,7 +733,7 @@ |
| 99 | stacking. |
| 100 | """ |
| 101 | if not self._format.supports_stacking(): |
| 102 | - raise errors.UnstackableBranchFormat(self._format, self.base) |
| 103 | + raise errors.UnstackableBranchFormat(self._format, self.user_url) |
| 104 | # XXX: Changing from one fallback repository to another does not check |
| 105 | # that all the data you need is present in the new fallback. |
| 106 | # Possibly it should. |
| 107 | @@ -893,7 +890,7 @@ |
| 108 | |
| 109 | def unbind(self): |
| 110 | """Older format branches cannot bind or unbind.""" |
| 111 | - raise errors.UpgradeRequired(self.base) |
| 112 | + raise errors.UpgradeRequired(self.user_url) |
| 113 | |
| 114 | def last_revision(self): |
| 115 | """Return last revision id, or NULL_REVISION.""" |
| 116 | @@ -1059,7 +1056,7 @@ |
| 117 | try: |
| 118 | return urlutils.join(self.base[:-1], parent) |
| 119 | except errors.InvalidURLJoin, e: |
| 120 | - raise errors.InaccessibleParent(parent, self.base) |
| 121 | + raise errors.InaccessibleParent(parent, self.user_url) |
| 122 | |
| 123 | def _get_parent_location(self): |
| 124 | raise NotImplementedError(self._get_parent_location) |
| 125 | @@ -1564,7 +1561,7 @@ |
| 126 | elsewhere) |
| 127 | :return: a branch in this format |
| 128 | """ |
| 129 | - mutter('creating branch %r in %s', self, a_bzrdir.transport.base) |
| 130 | + mutter('creating branch %r in %s', self, a_bzrdir.user_url) |
| 131 | branch_transport = a_bzrdir.get_branch_transport(self, name=name) |
| 132 | lock_map = { |
| 133 | 'metadir': ('lock', lockdir.LockDir), |
| 134 | @@ -1957,8 +1954,8 @@ |
| 135 | if format.__class__ != self.__class__: |
| 136 | raise AssertionError("wrong format %r found for %r" % |
| 137 | (format, self)) |
| 138 | + transport = a_bzrdir.get_branch_transport(None, name=name) |
| 139 | try: |
| 140 | - transport = a_bzrdir.get_branch_transport(None, name=name) |
| 141 | control_files = lockable_files.LockableFiles(transport, 'lock', |
| 142 | lockdir.LockDir) |
| 143 | return self._branch_class()(_format=self, |
| 144 | @@ -2162,10 +2159,10 @@ |
| 145 | # this format does not implement branch itself, thus the implicit |
| 146 | # creation contract must see it as uninitializable |
| 147 | raise errors.UninitializableFormat(self) |
| 148 | - mutter('creating branch reference in %s', a_bzrdir.transport.base) |
| 149 | + mutter('creating branch reference in %s', a_bzrdir.user_url) |
| 150 | branch_transport = a_bzrdir.get_branch_transport(self, name=name) |
| 151 | branch_transport.put_bytes('location', |
| 152 | - target_branch.bzrdir.root_transport.base) |
| 153 | + target_branch.bzrdir.user_url) |
| 154 | branch_transport.put_bytes('format', self.get_format_string()) |
| 155 | branch = self.open( |
| 156 | a_bzrdir, name, _found=True, |
| 157 | @@ -2293,9 +2290,10 @@ |
| 158 | |
| 159 | def __str__(self): |
| 160 | if self.name is None: |
| 161 | - return '%s(%r)' % (self.__class__.__name__, self.base) |
| 162 | + return '%s(%s)' % (self.__class__.__name__, self.user_url) |
| 163 | else: |
| 164 | - return '%s(%r,%r)' % (self.__class__.__name__, self.base, self.name) |
| 165 | + return '%s(%s,%s)' % (self.__class__.__name__, self.user_url, |
| 166 | + self.name) |
| 167 | |
| 168 | __repr__ = __str__ |
| 169 | |
| 170 | @@ -2516,7 +2514,7 @@ |
| 171 | return result |
| 172 | |
| 173 | def get_stacked_on_url(self): |
| 174 | - raise errors.UnstackableBranchFormat(self._format, self.base) |
| 175 | + raise errors.UnstackableBranchFormat(self._format, self.user_url) |
| 176 | |
| 177 | def set_push_location(self, location): |
| 178 | """See Branch.set_push_location.""" |
| 179 | @@ -2712,7 +2710,7 @@ |
| 180 | if _mod_revision.is_null(last_revision): |
| 181 | return |
| 182 | if last_revision not in self._lefthand_history(revision_id): |
| 183 | - raise errors.AppendRevisionsOnlyViolation(self.base) |
| 184 | + raise errors.AppendRevisionsOnlyViolation(self.user_url) |
| 185 | |
| 186 | def _gen_revision_history(self): |
| 187 | """Generate the revision history from last revision |
| 188 | @@ -2818,7 +2816,7 @@ |
| 189 | if branch_location is None: |
| 190 | return Branch.reference_parent(self, file_id, path, |
| 191 | possible_transports) |
| 192 | - branch_location = urlutils.join(self.base, branch_location) |
| 193 | + branch_location = urlutils.join(self.user_url, branch_location) |
| 194 | return Branch.open(branch_location, |
| 195 | possible_transports=possible_transports) |
| 196 | |
| 197 | @@ -2939,7 +2937,7 @@ |
| 198 | """ |
| 199 | |
| 200 | def get_stacked_on_url(self): |
| 201 | - raise errors.UnstackableBranchFormat(self._format, self.base) |
| 202 | + raise errors.UnstackableBranchFormat(self._format, self.user_url) |
| 203 | |
| 204 | |
| 205 | ###################################################################### |
| 206 | @@ -3032,7 +3030,7 @@ |
| 207 | :param verbose: Requests more detailed display of what was checked, |
| 208 | if any. |
| 209 | """ |
| 210 | - note('checked branch %s format %s', self.branch.base, |
| 211 | + note('checked branch %s format %s', self.branch.user_url, |
| 212 | self.branch._format) |
| 213 | for error in self.errors: |
| 214 | note('found error:%s', error) |
| 215 | @@ -3367,7 +3365,7 @@ |
| 216 | if local and not bound_location: |
| 217 | raise errors.LocalRequiresBoundBranch() |
| 218 | master_branch = None |
| 219 | - if not local and bound_location and self.source.base != bound_location: |
| 220 | + if not local and bound_location and self.source.user_url != bound_location: |
| 221 | # not pulling from master, so we need to update master. |
| 222 | master_branch = self.target.get_master_branch(possible_transports) |
| 223 | master_branch.lock_write() |
| 224 | |
| 225 | === modified file 'bzrlib/builtins.py' |
| 226 | --- bzrlib/builtins.py 2010-04-23 11:11:22 +0000 |
| 227 | +++ bzrlib/builtins.py 2010-04-28 07:06:33 +0000 |
| 228 | @@ -504,9 +504,7 @@ |
| 229 | if (working.has_changes()): |
| 230 | raise errors.UncommittedChanges(working) |
| 231 | |
| 232 | - working_path = working.bzrdir.root_transport.base |
| 233 | - branch_path = working.branch.bzrdir.root_transport.base |
| 234 | - if working_path != branch_path: |
| 235 | + if working.user_url != working.branch.user_url: |
| 236 | raise errors.BzrCommandError("You cannot remove the working tree" |
| 237 | " from a lightweight checkout") |
| 238 | |
| 239 | |
| 240 | === modified file 'bzrlib/bzrdir.py' |
| 241 | --- bzrlib/bzrdir.py 2010-04-22 17:08:27 +0000 |
| 242 | +++ bzrlib/bzrdir.py 2010-04-28 07:06:33 +0000 |
| 243 | @@ -86,9 +86,42 @@ |
| 244 | registry, |
| 245 | symbol_versioning, |
| 246 | ) |
| 247 | - |
| 248 | - |
| 249 | -class BzrDir(object): |
| 250 | + |
| 251 | + |
| 252 | +class ControlComponent(object): |
| 253 | + """Abstract base class for control directory components. |
| 254 | + |
| 255 | + This provides interfaces that are common across bzrdirs, |
| 256 | + repositories, branches, and workingtree control directories. |
| 257 | + |
| 258 | + They all expose two urls and transports: the *user* URL is the |
| 259 | + one that stops above the control directory (eg .bzr) and that |
| 260 | + should normally be used in messages, and the *control* URL is |
| 261 | + under that in eg .bzr/checkout and is used to read the control |
| 262 | + files. |
| 263 | + |
| 264 | + This can be used as a mixin and is intended to fit with |
| 265 | + foreign formats. |
| 266 | + """ |
| 267 | + |
| 268 | + @property |
| 269 | + def control_transport(self): |
| 270 | + raise NotImplementedError |
| 271 | + |
| 272 | + @property |
| 273 | + def control_url(self): |
| 274 | + return self.control_transport.base |
| 275 | + |
| 276 | + @property |
| 277 | + def user_transport(self): |
| 278 | + raise NotImplementedError |
| 279 | + |
| 280 | + @property |
| 281 | + def user_url(self): |
| 282 | + return self.user_transport.base |
| 283 | + |
| 284 | + |
| 285 | +class BzrDir(ControlComponent): |
| 286 | """A .bzr control diretory. |
| 287 | |
| 288 | BzrDir instances let you create or open any of the things that can be |
| 289 | @@ -261,8 +294,8 @@ |
| 290 | # copied, and finally if we are copying up to a specific |
| 291 | # revision_id then we can use the pending-ancestry-result which |
| 292 | # does not require traversing all of history to describe it. |
| 293 | - if (result_repo.bzrdir.root_transport.base == |
| 294 | - result.root_transport.base and not require_stacking and |
| 295 | + if (result_repo.user_url == result.user_url |
| 296 | + and not require_stacking and |
| 297 | revision_id is not None): |
| 298 | fetch_spec = graph.PendingAncestryResult( |
| 299 | [revision_id], local_repo) |
| 300 | @@ -458,7 +491,7 @@ |
| 301 | stop = False |
| 302 | stack_on = config.get_default_stack_on() |
| 303 | if stack_on is not None: |
| 304 | - stack_on_pwd = found_bzrdir.root_transport.base |
| 305 | + stack_on_pwd = found_bzrdir.user_url |
| 306 | stop = True |
| 307 | # does it have a repository ? |
| 308 | try: |
| 309 | @@ -466,8 +499,8 @@ |
| 310 | except errors.NoRepositoryPresent: |
| 311 | repository = None |
| 312 | else: |
| 313 | - if ((found_bzrdir.root_transport.base != |
| 314 | - self.root_transport.base) and not repository.is_shared()): |
| 315 | + if (found_bzrdir.user_url != self.user_url |
| 316 | + and not repository.is_shared()): |
| 317 | # Don't look higher, can't use a higher shared repo. |
| 318 | repository = None |
| 319 | stop = True |
| 320 | @@ -669,7 +702,7 @@ |
| 321 | if stop: |
| 322 | return result |
| 323 | next_transport = found_bzrdir.root_transport.clone('..') |
| 324 | - if (found_bzrdir.root_transport.base == next_transport.base): |
| 325 | + if (found_bzrdir.user_url == next_transport.base): |
| 326 | # top of the file system |
| 327 | return None |
| 328 | # find the next containing bzrdir |
| 329 | @@ -692,7 +725,7 @@ |
| 330 | repository = found_bzrdir.open_repository() |
| 331 | except errors.NoRepositoryPresent: |
| 332 | return None, False |
| 333 | - if found_bzrdir.root_transport.base == self.root_transport.base: |
| 334 | + if found_bzrdir.user_url == self.user_url: |
| 335 | return repository, True |
| 336 | elif repository.is_shared(): |
| 337 | return repository, True |
| 338 | @@ -814,9 +847,19 @@ |
| 339 | :param _transport: the transport this dir is based at. |
| 340 | """ |
| 341 | self._format = _format |
| 342 | + # these are also under the more standard names of |
| 343 | + # control_transport and user_transport |
| 344 | self.transport = _transport.clone('.bzr') |
| 345 | self.root_transport = _transport |
| 346 | self._mode_check_done = False |
| 347 | + |
| 348 | + @property |
| 349 | + def user_transport(self): |
| 350 | + return self.root_transport |
| 351 | + |
| 352 | + @property |
| 353 | + def control_transport(self): |
| 354 | + return self.transport |
| 355 | |
| 356 | def is_control_filename(self, filename): |
| 357 | """True if filename is the name of a path which is reserved for bzrdir's. |
| 358 | @@ -2692,7 +2735,7 @@ |
| 359 | if isinstance(self.bzrdir.transport, local.LocalTransport): |
| 360 | self.bzrdir.get_workingtree_transport(None).delete('stat-cache') |
| 361 | self._convert_to_weaves() |
| 362 | - return BzrDir.open(self.bzrdir.root_transport.base) |
| 363 | + return BzrDir.open(self.bzrdir.user_url) |
| 364 | finally: |
| 365 | self.pb.finished() |
| 366 | |
| 367 | @@ -2945,7 +2988,7 @@ |
| 368 | try: |
| 369 | ui.ui_factory.note('starting upgrade from format 5 to 6') |
| 370 | self._convert_to_prefixed() |
| 371 | - return BzrDir.open(self.bzrdir.root_transport.base) |
| 372 | + return BzrDir.open(self.bzrdir.user_url) |
| 373 | finally: |
| 374 | pb.finished() |
| 375 | |
| 376 | @@ -3073,7 +3116,7 @@ |
| 377 | BzrDirMetaFormat1().get_format_string(), |
| 378 | mode=self.file_mode) |
| 379 | self.pb.finished() |
| 380 | - return BzrDir.open(self.bzrdir.root_transport.base) |
| 381 | + return BzrDir.open(self.bzrdir.user_url) |
| 382 | |
| 383 | def make_lock(self, name): |
| 384 | """Make a lock for the new control dir name.""" |
| 385 | @@ -3660,7 +3703,7 @@ |
| 386 | try: |
| 387 | stack_on = urlutils.rebase_url(self._stack_on, |
| 388 | self._stack_on_pwd, |
| 389 | - branch.bzrdir.root_transport.base) |
| 390 | + branch.user_url) |
| 391 | except errors.InvalidRebaseURLs: |
| 392 | stack_on = self._get_full_stack_on() |
| 393 | try: |
| 394 | |
| 395 | === modified file 'bzrlib/check.py' |
| 396 | --- bzrlib/check.py 2009-09-18 01:06:10 +0000 |
| 397 | +++ bzrlib/check.py 2010-04-28 07:06:33 +0000 |
| 398 | @@ -192,8 +192,8 @@ |
| 399 | |
| 400 | def _report_repo_results(self, verbose): |
| 401 | note('checked repository %s format %s', |
| 402 | - self.repository.bzrdir.root_transport, |
| 403 | - self.repository._format) |
| 404 | + self.repository.user_url, |
| 405 | + self.repository._format) |
| 406 | note('%6d revisions', self.checked_rev_cnt) |
| 407 | note('%6d file-ids', len(self.checked_weaves)) |
| 408 | if verbose: |
| 409 | @@ -451,7 +451,7 @@ |
| 410 | if do_repo or do_branch or do_tree: |
| 411 | if do_repo: |
| 412 | note("Checking repository at '%s'." |
| 413 | - % (repo.bzrdir.root_transport.base,)) |
| 414 | + % (repo.user_url,)) |
| 415 | result = repo.check(None, callback_refs=needed_refs, |
| 416 | check_repo=do_repo) |
| 417 | result.report_results(verbose) |
| 418 | |
| 419 | === modified file 'bzrlib/errors.py' |
| 420 | --- bzrlib/errors.py 2010-03-24 14:15:01 +0000 |
| 421 | +++ bzrlib/errors.py 2010-04-28 07:06:33 +0000 |
| 422 | @@ -2176,7 +2176,7 @@ |
| 423 | |
| 424 | def __init__(self, repo): |
| 425 | BzrError.__init__(self) |
| 426 | - self.repo_path = repo.bzrdir.root_transport.base |
| 427 | + self.repo_path = repo.user_url |
| 428 | |
| 429 | |
| 430 | class InconsistentDelta(BzrError): |
| 431 | @@ -2754,7 +2754,7 @@ |
| 432 | |
| 433 | def __init__(self, bzrdir): |
| 434 | import bzrlib.urlutils as urlutils |
| 435 | - display_url = urlutils.unescape_for_display(bzrdir.root_transport.base, |
| 436 | + display_url = urlutils.unescape_for_display(bzrdir.user_url, |
| 437 | 'ascii') |
| 438 | BzrError.__init__(self, bzrdir=bzrdir, display_url=display_url) |
| 439 | |
| 440 | @@ -2835,7 +2835,7 @@ |
| 441 | more = ' ' + more |
| 442 | import bzrlib.urlutils as urlutils |
| 443 | display_url = urlutils.unescape_for_display( |
| 444 | - tree.bzrdir.root_transport.base, 'ascii') |
| 445 | + tree.user_url, 'ascii') |
| 446 | BzrError.__init__(self, tree=tree, display_url=display_url, more=more) |
| 447 | |
| 448 | |
| 449 | |
| 450 | === modified file 'bzrlib/info.py' |
| 451 | --- bzrlib/info.py 2010-02-17 17:11:16 +0000 |
| 452 | +++ bzrlib/info.py 2010-04-28 07:06:33 +0000 |
| 453 | @@ -80,9 +80,9 @@ |
| 454 | |
| 455 | def gather_location_info(repository, branch=None, working=None): |
| 456 | locs = {} |
| 457 | - repository_path = repository.bzrdir.root_transport.base |
| 458 | + repository_path = repository.user_url |
| 459 | if branch is not None: |
| 460 | - branch_path = branch.bzrdir.root_transport.base |
| 461 | + branch_path = branch.user_url |
| 462 | master_path = branch.get_bound_location() |
| 463 | if master_path is None: |
| 464 | master_path = branch_path |
| 465 | @@ -90,7 +90,7 @@ |
| 466 | branch_path = None |
| 467 | master_path = None |
| 468 | if working: |
| 469 | - working_path = working.bzrdir.root_transport.base |
| 470 | + working_path = working.user_url |
| 471 | if working_path != branch_path: |
| 472 | locs['light checkout root'] = working_path |
| 473 | if master_path != branch_path: |
| 474 | @@ -420,8 +420,8 @@ |
| 475 | if branch is None and tree is not None: |
| 476 | phrase = "branchless tree" |
| 477 | else: |
| 478 | - if (tree is not None and tree.bzrdir.root_transport.base != |
| 479 | - branch.bzrdir.root_transport.base): |
| 480 | + if (tree is not None and tree.user_url != |
| 481 | + branch.user_url): |
| 482 | independence = '' |
| 483 | phrase = "Lightweight checkout" |
| 484 | elif branch.get_bound_location() is not None: |
| 485 | @@ -446,8 +446,7 @@ |
| 486 | """ |
| 487 | candidates = [] |
| 488 | if (branch is not None and tree is not None and |
| 489 | - branch.bzrdir.root_transport.base != |
| 490 | - tree.bzrdir.root_transport.base): |
| 491 | + branch.user_url != tree.user_url): |
| 492 | branch = None |
| 493 | repository = None |
| 494 | non_aliases = set(bzrdir.format_registry.keys()) |
| 495 | |
| 496 | === modified file 'bzrlib/reconcile.py' |
| 497 | --- bzrlib/reconcile.py 2010-02-17 17:11:16 +0000 |
| 498 | +++ bzrlib/reconcile.py 2010-04-28 07:06:33 +0000 |
| 499 | @@ -97,7 +97,7 @@ |
| 500 | def _reconcile_repository(self): |
| 501 | self.repo = self.bzrdir.find_repository() |
| 502 | ui.ui_factory.note('Reconciling repository %s' % |
| 503 | - self.repo.bzrdir.root_transport.base) |
| 504 | + self.repo.user_url) |
| 505 | self.pb.update("Reconciling repository", 0, 1) |
| 506 | repo_reconciler = self.repo.reconcile(thorough=True) |
| 507 | self.inconsistent_parents = repo_reconciler.inconsistent_parents |
| 508 | |
| 509 | === modified file 'bzrlib/reconfigure.py' |
| 510 | --- bzrlib/reconfigure.py 2010-03-25 09:39:03 +0000 |
| 511 | +++ bzrlib/reconfigure.py 2010-04-28 07:06:33 +0000 |
| 512 | @@ -82,14 +82,13 @@ |
| 513 | self.repository = None |
| 514 | self.local_repository = None |
| 515 | else: |
| 516 | - if (self.repository.bzrdir.root_transport.base == |
| 517 | - self.bzrdir.root_transport.base): |
| 518 | + if (self.repository.user_url == self.bzrdir.user_url): |
| 519 | self.local_repository = self.repository |
| 520 | else: |
| 521 | self.local_repository = None |
| 522 | try: |
| 523 | branch = self.bzrdir.open_branch() |
| 524 | - if branch.bzrdir.root_transport.base == bzrdir.root_transport.base: |
| 525 | + if branch.user_url == bzrdir.user_url: |
| 526 | self.local_branch = branch |
| 527 | self.referenced_branch = None |
| 528 | else: |
| 529 | @@ -217,8 +216,8 @@ |
| 530 | if not want_reference: |
| 531 | self._create_repository = True |
| 532 | else: |
| 533 | - if want_reference and (self.repository.bzrdir.root_transport.base |
| 534 | - == self.bzrdir.root_transport.base): |
| 535 | + if want_reference and ( |
| 536 | + self.repository.user_url == self.bzrdir.user_url): |
| 537 | if not self.repository.is_shared(): |
| 538 | self._destroy_repository = True |
| 539 | if self.referenced_branch is None: |
| 540 | @@ -344,7 +343,7 @@ |
| 541 | if self._create_reference: |
| 542 | reference_branch.repository.fetch(self.repository) |
| 543 | elif self.local_branch is not None and not self._destroy_branch: |
| 544 | - up = self.local_branch.bzrdir.root_transport.clone('..') |
| 545 | + up = self.local_branch.user_transport.clone('..') |
| 546 | up_bzrdir = bzrdir.BzrDir.open_containing_from_transport(up)[0] |
| 547 | new_repo = up_bzrdir.find_repository() |
| 548 | new_repo.fetch(self.repository) |
| 549 | |
| 550 | === modified file 'bzrlib/remote.py' |
| 551 | --- bzrlib/remote.py 2010-04-20 04:16:50 +0000 |
| 552 | +++ bzrlib/remote.py 2010-04-28 07:06:33 +0000 |
| 553 | @@ -643,7 +643,8 @@ |
| 554 | return self._custom_format._serializer |
| 555 | |
| 556 | |
| 557 | -class RemoteRepository(_RpcHelper, lock._RelockDebugMixin): |
| 558 | +class RemoteRepository(_RpcHelper, lock._RelockDebugMixin, |
| 559 | + bzrdir.ControlComponent): |
| 560 | """Repository accessed over rpc. |
| 561 | |
| 562 | For the moment most operations are performed using local transport-backed |
| 563 | @@ -692,6 +693,17 @@ |
| 564 | # Additional places to query for data. |
| 565 | self._fallback_repositories = [] |
| 566 | |
| 567 | + @property |
| 568 | + def user_transport(self): |
| 569 | + return self.bzrdir.user_transport |
| 570 | + |
| 571 | + @property |
| 572 | + def control_transport(self): |
| 573 | + # XXX: Normally you shouldn't directly get at the remote repository |
| 574 | + # transport, but I'm not sure it's worth making this method |
| 575 | + # optional -- mbp 2010-04-21 |
| 576 | + return self.bzrdir.get_repository_transport(None) |
| 577 | + |
| 578 | def __str__(self): |
| 579 | return "%s(%s)" % (self.__class__.__name__, self.base) |
| 580 | |
| 581 | @@ -1234,9 +1246,9 @@ |
| 582 | # _real_branch had its get_stacked_on_url method called), then the |
| 583 | # repository to be added may already be in the _real_repositories list. |
| 584 | if self._real_repository is not None: |
| 585 | - fallback_locations = [repo.bzrdir.root_transport.base for repo in |
| 586 | + fallback_locations = [repo.user_url for repo in |
| 587 | self._real_repository._fallback_repositories] |
| 588 | - if repository.bzrdir.root_transport.base not in fallback_locations: |
| 589 | + if repository.user_url not in fallback_locations: |
| 590 | self._real_repository.add_fallback_repository(repository) |
| 591 | |
| 592 | def _check_fallback_repository(self, repository): |
| 593 | @@ -2181,7 +2193,8 @@ |
| 594 | self._real_branch = None |
| 595 | # Fill out expected attributes of branch for bzrlib API users. |
| 596 | self._clear_cached_state() |
| 597 | - self.base = self.bzrdir.root_transport.base |
| 598 | + # TODO: deprecate self.base in favor of user_url |
| 599 | + self.base = self.bzrdir.user_url |
| 600 | self._name = name |
| 601 | self._control_files = None |
| 602 | self._lock_mode = None |
| 603 | |
| 604 | === modified file 'bzrlib/repofmt/weaverepo.py' |
| 605 | --- bzrlib/repofmt/weaverepo.py 2010-04-26 13:51:08 +0000 |
| 606 | +++ bzrlib/repofmt/weaverepo.py 2010-04-28 07:06:33 +0000 |
| 607 | @@ -177,7 +177,7 @@ |
| 608 | :param new_value: True to restore the default, False to disable making |
| 609 | working trees. |
| 610 | """ |
| 611 | - raise errors.RepositoryUpgradeRequired(self.bzrdir.root_transport.base) |
| 612 | + raise errors.RepositoryUpgradeRequired(self.user_url) |
| 613 | |
| 614 | def make_working_trees(self): |
| 615 | """Returns the policy for making working trees on new branches.""" |
| 616 | |
| 617 | === modified file 'bzrlib/repository.py' |
| 618 | --- bzrlib/repository.py 2010-04-22 17:08:27 +0000 |
| 619 | +++ bzrlib/repository.py 2010-04-28 07:06:33 +0000 |
| 620 | @@ -864,7 +864,7 @@ |
| 621 | # Repositories |
| 622 | |
| 623 | |
| 624 | -class Repository(_RelockDebugMixin): |
| 625 | +class Repository(_RelockDebugMixin, bzrdir.ControlComponent): |
| 626 | """Repository holding history for one or more branches. |
| 627 | |
| 628 | The repository holds and retrieves historical information including |
| 629 | @@ -1291,11 +1291,10 @@ |
| 630 | |
| 631 | :param _format: The format of the repository on disk. |
| 632 | :param a_bzrdir: The BzrDir of the repository. |
| 633 | - |
| 634 | - In the future we will have a single api for all stores for |
| 635 | - getting file texts, inventories and revisions, then |
| 636 | - this construct will accept instances of those things. |
| 637 | """ |
| 638 | + # In the future we will have a single api for all stores for |
| 639 | + # getting file texts, inventories and revisions, then |
| 640 | + # this construct will accept instances of those things. |
| 641 | super(Repository, self).__init__() |
| 642 | self._format = _format |
| 643 | # the following are part of the public API for Repository: |
| 644 | @@ -1316,6 +1315,14 @@ |
| 645 | # rather copying them? |
| 646 | self._safe_to_return_from_cache = False |
| 647 | |
| 648 | + @property |
| 649 | + def user_transport(self): |
| 650 | + return self.bzrdir.user_transport |
| 651 | + |
| 652 | + @property |
| 653 | + def control_transport(self): |
| 654 | + return self._transport |
| 655 | + |
| 656 | def __repr__(self): |
| 657 | if self._fallback_repositories: |
| 658 | return '%s(%r, fallback_repositories=%r)' % ( |
| 659 | @@ -1469,7 +1476,7 @@ |
| 660 | |
| 661 | # now gather global repository information |
| 662 | # XXX: This is available for many repos regardless of listability. |
| 663 | - if self.bzrdir.root_transport.listable(): |
| 664 | + if self.user_transport.listable(): |
| 665 | # XXX: do we want to __define len__() ? |
| 666 | # Maybe the versionedfiles object should provide a different |
| 667 | # method to get the number of keys. |
| 668 | @@ -1507,7 +1514,7 @@ |
| 669 | |
| 670 | ret = [] |
| 671 | for branches, repository in bzrdir.BzrDir.find_bzrdirs( |
| 672 | - self.bzrdir.root_transport, evaluate=Evaluator()): |
| 673 | + self.user_transport, evaluate=Evaluator()): |
| 674 | if branches is not None: |
| 675 | ret.extend(branches) |
| 676 | if not using and repository is not None: |
| 677 | |
| 678 | === modified file 'bzrlib/smart/bzrdir.py' |
| 679 | --- bzrlib/smart/bzrdir.py 2010-02-17 17:11:16 +0000 |
| 680 | +++ bzrlib/smart/bzrdir.py 2010-04-28 07:06:33 +0000 |
| 681 | @@ -110,7 +110,7 @@ |
| 682 | """Get the relative path for repository from current_transport.""" |
| 683 | # the relpath of the bzrdir in the found repository gives us the |
| 684 | # path segments to pop-out. |
| 685 | - relpath = repository.bzrdir.root_transport.relpath( |
| 686 | + relpath = repository.user_transport.relpath( |
| 687 | current_transport.base) |
| 688 | if len(relpath): |
| 689 | segments = ['..'] * len(relpath.split('/')) |
| 690 | |
| 691 | === modified file 'bzrlib/tests/per_branch/test_branch.py' |
| 692 | --- bzrlib/tests/per_branch/test_branch.py 2010-03-02 22:25:58 +0000 |
| 693 | +++ bzrlib/tests/per_branch/test_branch.py 2010-04-28 07:06:33 +0000 |
| 694 | @@ -988,3 +988,16 @@ |
| 695 | merger.do_merge() |
| 696 | self.assertEqual('../branch/reference', |
| 697 | tree.branch.get_reference_info('file-id')[1]) |
| 698 | + |
| 699 | + |
| 700 | +class TestBranchControlComponent(per_branch.TestCaseWithBranch): |
| 701 | + """Branch implementations adequately implement ControlComponent.""" |
| 702 | + |
| 703 | + def test_urls(self): |
| 704 | + br = self.make_branch('branch') |
| 705 | + self.assertIsInstance(br.user_url, str) |
| 706 | + self.assertEqual(br.user_url, br.user_transport.base) |
| 707 | + # for all current bzrdir implementations the user dir must be |
| 708 | + # above the control dir but we might need to relax that? |
| 709 | + self.assertEqual(br.control_url.find(br.user_url), 0) |
| 710 | + self.assertEqual(br.control_url, br.control_transport.base) |
| 711 | |
| 712 | === modified file 'bzrlib/tests/per_bzrdir/test_bzrdir.py' |
| 713 | --- bzrlib/tests/per_bzrdir/test_bzrdir.py 2010-04-11 19:40:23 +0000 |
| 714 | +++ bzrlib/tests/per_bzrdir/test_bzrdir.py 2010-04-28 07:06:33 +0000 |
| 715 | @@ -1971,3 +1971,15 @@ |
| 716 | self.assertRaises(errors.NoRepositoryPresent, |
| 717 | made_control.find_repository) |
| 718 | |
| 719 | + |
| 720 | +class TestBzrDirControlComponent(TestCaseWithBzrDir): |
| 721 | + """BzrDir implementations adequately implement ControlComponent.""" |
| 722 | + |
| 723 | + def test_urls(self): |
| 724 | + bd = self.make_bzrdir('bd') |
| 725 | + self.assertIsInstance(bd.user_url, str) |
| 726 | + self.assertEqual(bd.user_url, bd.user_transport.base) |
| 727 | + # for all current bzrdir implementations the user dir must be |
| 728 | + # above the control dir but we might need to relax that? |
| 729 | + self.assertEqual(bd.control_url.find(bd.user_url), 0) |
| 730 | + self.assertEqual(bd.control_url, bd.control_transport.base) |
| 731 | |
| 732 | === modified file 'bzrlib/tests/per_repository/test_repository.py' |
| 733 | --- bzrlib/tests/per_repository/test_repository.py 2010-04-10 01:22:00 +0000 |
| 734 | +++ bzrlib/tests/per_repository/test_repository.py 2010-04-28 07:06:33 +0000 |
| 735 | @@ -1342,3 +1342,18 @@ |
| 736 | fileobj = StringIO() |
| 737 | wt.branch.repository.create_bundle( |
| 738 | 'rev1', _mod_revision.NULL_REVISION, fileobj) |
| 739 | + |
| 740 | + |
| 741 | + |
| 742 | + |
| 743 | +class TestRepositoryControlComponent(per_repository.TestCaseWithRepository): |
| 744 | + """Repository implementations adequately implement ControlComponent.""" |
| 745 | + |
| 746 | + def test_urls(self): |
| 747 | + repo = self.make_repository('repo') |
| 748 | + self.assertIsInstance(repo.user_url, str) |
| 749 | + self.assertEqual(repo.user_url, repo.user_transport.base) |
| 750 | + # for all current bzrdir implementations the user dir must be |
| 751 | + # above the control dir but we might need to relax that? |
| 752 | + self.assertEqual(repo.control_url.find(repo.user_url), 0) |
| 753 | + self.assertEqual(repo.control_url, repo.control_transport.base) |
| 754 | |
| 755 | === modified file 'bzrlib/tests/per_workingtree/test_workingtree.py' |
| 756 | --- bzrlib/tests/per_workingtree/test_workingtree.py 2010-03-02 22:25:58 +0000 |
| 757 | +++ bzrlib/tests/per_workingtree/test_workingtree.py 2010-04-28 07:06:33 +0000 |
| 758 | @@ -1091,3 +1091,16 @@ |
| 759 | # We should display the relative path |
| 760 | self.assertEqual('subdir/m\xb5', e.filename) |
| 761 | self.assertEqual(osutils._fs_enc, e.fs_encoding) |
| 762 | + |
| 763 | + |
| 764 | +class TestControlComponent(TestCaseWithWorkingTree): |
| 765 | + """WorkingTree implementations adequately implement ControlComponent.""" |
| 766 | + |
| 767 | + def test_urls(self): |
| 768 | + wt = self.make_branch_and_tree('wt') |
| 769 | + self.assertIsInstance(wt.user_url, str) |
| 770 | + self.assertEqual(wt.user_url, wt.user_transport.base) |
| 771 | + # for all current bzrdir implementations the user dir must be |
| 772 | + # above the control dir but we might need to relax that? |
| 773 | + self.assertEqual(wt.control_url.find(wt.user_url), 0) |
| 774 | + self.assertEqual(wt.control_url, wt.control_transport.base) |
| 775 | |
| 776 | === modified file 'bzrlib/tests/test_foreign.py' |
| 777 | --- bzrlib/tests/test_foreign.py 2010-03-02 22:25:58 +0000 |
| 778 | +++ bzrlib/tests/test_foreign.py 2010-04-28 07:06:33 +0000 |
| 779 | @@ -90,6 +90,7 @@ |
| 780 | self._format = _format |
| 781 | self._base = a_bzrdir.transport.base |
| 782 | self._ignore_fallbacks = False |
| 783 | + self.bzrdir = a_bzrdir |
| 784 | foreign.ForeignBranch.__init__(self, |
| 785 | DummyForeignVcsMapping(DummyForeignVcs())) |
| 786 | branch.BzrBranch6.__init__(self, _format, _control_files, a_bzrdir, |
| 787 | |
| 788 | === modified file 'bzrlib/upgrade.py' |
| 789 | --- bzrlib/upgrade.py 2010-03-25 07:34:15 +0000 |
| 790 | +++ bzrlib/upgrade.py 2010-04-28 07:06:33 +0000 |
| 791 | @@ -47,11 +47,10 @@ |
| 792 | def convert(self): |
| 793 | try: |
| 794 | branch = self.bzrdir.open_branch() |
| 795 | - if branch.bzrdir.root_transport.base != \ |
| 796 | - self.bzrdir.root_transport.base: |
| 797 | + if branch.user_url != self.bzrdir.user_url: |
| 798 | ui.ui_factory.note("This is a checkout. The branch (%s) needs to be " |
| 799 | "upgraded separately." % |
| 800 | - branch.bzrdir.root_transport.base) |
| 801 | + branch.user_url) |
| 802 | del branch |
| 803 | except (errors.NotBranchError, errors.IncompatibleRepositories): |
| 804 | # might not be a format we can open without upgrading; see e.g. |
| 805 | |
| 806 | === modified file 'bzrlib/workingtree.py' |
| 807 | --- bzrlib/workingtree.py 2010-04-08 06:05:44 +0000 |
| 808 | +++ bzrlib/workingtree.py 2010-04-28 07:06:33 +0000 |
| 809 | @@ -29,12 +29,6 @@ |
| 810 | WorkingTree.open(dir). |
| 811 | """ |
| 812 | |
| 813 | -# TODO: Give the workingtree sole responsibility for the working inventory; |
| 814 | -# remove the variable and references to it from the branch. This may require |
| 815 | -# updating the commit code so as to update the inventory within the working |
| 816 | -# copy, and making sure there's only one WorkingTree for any directory on disk. |
| 817 | -# At the moment they may alias the inventory and have old copies of it in |
| 818 | -# memory. (Now done? -- mbp 20060309) |
| 819 | |
| 820 | from cStringIO import StringIO |
| 821 | import os |
| 822 | @@ -174,7 +168,8 @@ |
| 823 | return '' |
| 824 | |
| 825 | |
| 826 | -class WorkingTree(bzrlib.mutabletree.MutableTree): |
| 827 | +class WorkingTree(bzrlib.mutabletree.MutableTree, |
| 828 | + bzrdir.ControlComponent): |
| 829 | """Working copy tree. |
| 830 | |
| 831 | The inventory is held in the `Branch` working-inventory, and the |
| 832 | @@ -253,6 +248,14 @@ |
| 833 | self._rules_searcher = None |
| 834 | self.views = self._make_views() |
| 835 | |
| 836 | + @property |
| 837 | + def user_transport(self): |
| 838 | + return self.bzrdir.user_transport |
| 839 | + |
| 840 | + @property |
| 841 | + def control_transport(self): |
| 842 | + return self._transport |
| 843 | + |
| 844 | def _detect_case_handling(self): |
| 845 | wt_trans = self.bzrdir.get_workingtree_transport(None) |
| 846 | try: |

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.