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 |
Related bugs: |
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.
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.
Vincent Ladeuil (vila) wrote : | # |
Sounds good, please land.
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']
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.