Merge lp:~jelmer/bzr/2a-supports-colo into lp:bzr/2.5

Proposed by Jelmer Vernooij
Status: Merged
Approved by: Vincent Ladeuil
Approved revision: no longer in the source branch.
Merged at revision: 6465
Proposed branch: lp:~jelmer/bzr/2a-supports-colo
Merge into: lp:bzr/2.5
Diff against target: 1135 lines (+321/-205)
14 files modified
bzrlib/builtins.py (+43/-19)
bzrlib/bzrdir.py (+100/-142)
bzrlib/remote.py (+24/-8)
bzrlib/switch.py (+18/-10)
bzrlib/tests/blackbox/test_branch.py (+3/-2)
bzrlib/tests/blackbox/test_info.py (+90/-0)
bzrlib/tests/per_branch/test_branch.py (+7/-1)
bzrlib/tests/per_bzrdir/test_bzrdir.py (+2/-3)
bzrlib/tests/per_controldir_colo/__init__.py (+22/-0)
bzrlib/tests/per_controldir_colo/test_unsupported.py (+2/-1)
bzrlib/tests/test_bzrdir.py (+2/-2)
bzrlib/tests/test_remote.py (+0/-12)
bzrlib/transport/__init__.py (+5/-5)
doc/en/release-notes/bzr-2.5.txt (+3/-0)
To merge this branch: bzr merge lp:~jelmer/bzr/2a-supports-colo
Reviewer Review Type Date Requested Status
Vincent Ladeuil Approve
Review via email: mp+89738@code.launchpad.net

Commit message

Merge colocated branch support back into the 2a format.

Description of the change

Merge colocated branch support back into the 2a format.

This also updates the upgrader for development-colo->2a to leave the branches alone and just update the format string.

To post a comment you must log in.
Revision history for this message
Gordon Tyler (doxxx) wrote :

What are the upgrade implications for users of the current 2a? When they install the new version of bzr that has the new 2a-with-colo, what happens to their existing 2a branches/repos?

Revision history for this message
Jelmer Vernooij (jelmer) wrote :

Am 23/01/12 18:14, schrieb Gordon Tyler:
> What are the upgrade implications for users of the current 2a? When they install the new version of bzr that has the new 2a-with-colo, what happens to their existing 2a branches/repos?
Nothing. :-) Older versions of bzr won't be able to see the colocated
branches (obviously), but they will be able to access the active branch.
Newer versions of bzr will be able to create colocated branches and
change the active branch.

Cheers,

Jelmer

Revision history for this message
Vincent Ladeuil (vila) :
review: Approve
Revision history for this message
Jelmer Vernooij (jelmer) wrote :

sent to pqm by email

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bzrlib/builtins.py'
2--- bzrlib/builtins.py 2012-01-25 17:41:05 +0000
3+++ bzrlib/builtins.py 2012-01-28 02:10:28 +0000
4@@ -83,10 +83,11 @@
5 )
6
7
8-def _get_branch_location(control_dir):
9+def _get_branch_location(control_dir, possible_transports=None):
10 """Return location of branch for this control dir."""
11 try:
12- this_branch = control_dir.open_branch()
13+ this_branch = control_dir.open_branch(
14+ possible_transports=possible_transports)
15 # This may be a heavy checkout, where we want the master branch
16 master_location = this_branch.get_bound_location()
17 if master_location is not None:
18@@ -101,7 +102,34 @@
19 return control_dir.root_transport.base
20
21
22-def lookup_new_sibling_branch(control_dir, location):
23+def _is_colocated(control_dir, possible_transports=None):
24+ """Check if the branch in control_dir is colocated.
25+
26+ :param control_dir: Control directory
27+ :return: Boolean indicating whether
28+ """
29+ # This path is meant to be relative to the existing branch
30+ this_url = _get_branch_location(control_dir,
31+ possible_transports=possible_transports)
32+ # Perhaps the target control dir supports colocated branches?
33+ try:
34+ root = controldir.ControlDir.open(this_url,
35+ possible_transports=possible_transports)
36+ except errors.NotBranchError:
37+ return (False, this_url)
38+ else:
39+ try:
40+ wt = control_dir.open_workingtree()
41+ except (errors.NoWorkingTree, errors.NotLocalUrl):
42+ return (False, this_url)
43+ else:
44+ return (
45+ root._format.colocated_branches and
46+ control_dir.control_url == root.control_url,
47+ this_url)
48+
49+
50+def lookup_new_sibling_branch(control_dir, location, possible_transports=None):
51 """Lookup the location for a new sibling branch.
52
53 :param control_dir: Control directory relative to which to look up
54@@ -111,16 +139,7 @@
55 """
56 location = directory_service.directories.dereference(location)
57 if '/' not in location and '\\' not in location:
58- # This path is meant to be relative to the existing branch
59- this_url = _get_branch_location(control_dir)
60- # Perhaps the target control dir supports colocated branches?
61- try:
62- root = controldir.ControlDir.open(this_url,
63- possible_transports=[control_dir.user_transport])
64- except errors.NotBranchError:
65- colocated = False
66- else:
67- colocated = root._format.colocated_branches
68+ (colocated, this_url) = _is_colocated(control_dir, possible_transports)
69
70 if colocated:
71 return urlutils.join_segment_parameters(this_url,
72@@ -130,7 +149,7 @@
73 return location
74
75
76-def lookup_sibling_branch(control_dir, location):
77+def lookup_sibling_branch(control_dir, location, possible_transports=None):
78 """Lookup sibling branch.
79
80 :param control_dir: Control directory relative to which to lookup the
81@@ -140,7 +159,8 @@
82 """
83 try:
84 # Perhaps it's a colocated branch?
85- return control_dir.open_branch(location)
86+ return control_dir.open_branch(location,
87+ possible_transports=possible_transports)
88 except (errors.NotBranchError, errors.NoColocatedBranchSupport):
89 try:
90 return Branch.open(location)
91@@ -6201,14 +6221,17 @@
92 from bzrlib import switch
93 tree_location = directory
94 revision = _get_one_revision('switch', revision)
95- control_dir = controldir.ControlDir.open_containing(tree_location)[0]
96+ possible_transports = []
97+ control_dir = controldir.ControlDir.open_containing(tree_location,
98+ possible_transports=possible_transports)[0]
99 if to_location is None:
100 if revision is None:
101 raise errors.BzrCommandError(gettext('You must supply either a'
102 ' revision or a location'))
103 to_location = tree_location
104 try:
105- branch = control_dir.open_branch()
106+ branch = control_dir.open_branch(
107+ possible_transports=possible_transports)
108 had_explicit_nick = branch.get_config().has_explicit_nickname()
109 except errors.NotBranchError:
110 branch = None
111@@ -6217,9 +6240,10 @@
112 if branch is None:
113 raise errors.BzrCommandError(
114 gettext('cannot create branch without source branch'))
115- to_location = lookup_new_sibling_branch(control_dir, to_location)
116+ to_location = lookup_new_sibling_branch(control_dir, to_location,
117+ possible_transports=possible_transports)
118 to_branch = branch.bzrdir.sprout(to_location,
119- possible_transports=[branch.bzrdir.root_transport],
120+ possible_transports=possible_transports,
121 source_branch=branch).open_branch()
122 else:
123 to_branch = lookup_sibling_branch(control_dir, to_location)
124
125=== modified file 'bzrlib/bzrdir.py'
126--- bzrlib/bzrdir.py 2012-01-27 20:46:27 +0000
127+++ bzrlib/bzrdir.py 2012-01-28 02:10:28 +0000
128@@ -810,10 +810,51 @@
129 present within a BzrDir.
130 """
131
132+ def _get_branch_path(self, name):
133+ """Obtain the branch path to use.
134+
135+ This uses the API specified branch name first, and then falls back to
136+ the branch name specified in the URL. If neither of those is specified,
137+ it uses the default branch.
138+
139+ :param name: Optional branch name to use
140+ :return: Relative path to branch
141+ """
142+ if name == "":
143+ return 'branch'
144+ return urlutils.join('branches', name.encode("utf-8"))
145+
146+ def _read_branch_list(self):
147+ """Read the branch list.
148+
149+ :return: List of utf-8 encoded branch names.
150+ """
151+ try:
152+ f = self.control_transport.get('branch-list')
153+ except errors.NoSuchFile:
154+ return []
155+
156+ ret = []
157+ try:
158+ for name in f:
159+ ret.append(name.rstrip("\n"))
160+ finally:
161+ f.close()
162+ return ret
163+
164+ def _write_branch_list(self, branches):
165+ """Write out the branch list.
166+
167+ :param branches: List of utf-8 branch names to write
168+ """
169+ self.transport.put_bytes('branch-list',
170+ "".join([name+"\n" for name in branches]))
171+
172 def __init__(self, _transport, _format):
173 super(BzrDirMeta1, self).__init__(_transport, _format)
174- self.control_files = lockable_files.LockableFiles(self.control_transport,
175- self._format._lock_file_name, self._format._lock_class)
176+ self.control_files = lockable_files.LockableFiles(
177+ self.control_transport, self._format._lock_file_name,
178+ self._format._lock_class)
179
180 def can_convert_format(self):
181 """See BzrDir.can_convert_format()."""
182@@ -832,9 +873,19 @@
183 """See BzrDir.create_branch."""
184 if name is None:
185 name = self._get_selected_branch()
186+ path = self._get_branch_path(name)
187 if name != "":
188- raise errors.NoColocatedBranchSupport(self)
189- self.transport.delete_tree('branch')
190+ self.control_files.lock_write()
191+ try:
192+ branches = self._read_branch_list()
193+ try:
194+ branches.remove(name.encode("utf-8"))
195+ except ValueError:
196+ raise errors.NotBranchError(name)
197+ self._write_branch_list(branches)
198+ finally:
199+ self.control_files.unlock()
200+ self.transport.delete_tree(path)
201
202 def create_repository(self, shared=False):
203 """See BzrDir.create_repository."""
204@@ -896,21 +947,41 @@
205 """See BzrDir.get_branch_transport()."""
206 if name is None:
207 name = self._get_selected_branch()
208- if name != "":
209- raise errors.NoColocatedBranchSupport(self)
210+ path = self._get_branch_path(name)
211 # XXX: this shouldn't implicitly create the directory if it's just
212 # promising to get a transport -- mbp 20090727
213 if branch_format is None:
214- return self.transport.clone('branch')
215+ return self.transport.clone(path)
216 try:
217 branch_format.get_format_string()
218 except NotImplementedError:
219 raise errors.IncompatibleFormat(branch_format, self._format)
220+ if name != "":
221+ branches = self._read_branch_list()
222+ utf8_name = name.encode("utf-8")
223+ if not utf8_name in branches:
224+ self.control_files.lock_write()
225+ try:
226+ branches = self._read_branch_list()
227+ dirname = urlutils.dirname(utf8_name)
228+ if dirname != "" and dirname in branches:
229+ raise errors.ParentBranchExists(name)
230+ child_branches = [
231+ b.startswith(utf8_name+"/") for b in branches]
232+ if any(child_branches):
233+ raise errors.AlreadyBranchError(name)
234+ branches.append(utf8_name)
235+ self._write_branch_list(branches)
236+ finally:
237+ self.control_files.unlock()
238+ branch_transport = self.transport.clone(path)
239+ mode = self._get_mkdir_mode()
240+ branch_transport.create_prefix(mode=mode)
241 try:
242- self.transport.mkdir('branch', mode=self._get_mkdir_mode())
243+ self.transport.mkdir(path, mode=mode)
244 except errors.FileExists:
245 pass
246- return self.transport.clone('branch')
247+ return self.transport.clone(path)
248
249 def get_repository_transport(self, repository_format):
250 """See BzrDir.get_repository_transport()."""
251@@ -940,6 +1011,19 @@
252 pass
253 return self.transport.clone('checkout')
254
255+ def get_branches(self):
256+ """See ControlDir.get_branches."""
257+ ret = {}
258+ try:
259+ ret[""] = self.open_branch(name="")
260+ except (errors.NotBranchError, errors.NoRepositoryPresent):
261+ pass
262+
263+ for name in self._read_branch_list():
264+ ret[name] = self.open_branch(name=name.decode('utf-8'))
265+
266+ return ret
267+
268 def has_workingtree(self):
269 """Tell if this bzrdir contains a working tree.
270
271@@ -1013,124 +1097,6 @@
272 return config.TransportConfig(self.transport, 'control.conf')
273
274
275-class BzrDirMeta1Colo(BzrDirMeta1):
276- """BzrDirMeta1 with support for colocated branches.
277-
278- This format is experimental, and will eventually be merged back into
279- BzrDirMeta1.
280- """
281-
282- def _get_branch_path(self, name):
283- """Obtain the branch path to use.
284-
285- This uses the API specified branch name first, and then falls back to
286- the branch name specified in the URL. If neither of those is specified,
287- it uses the default branch.
288-
289- :param name: Optional branch name to use
290- :return: Relative path to branch
291- """
292- if name == "":
293- return 'branch'
294- return urlutils.join('branches', name.encode("utf-8"))
295-
296- def _read_branch_list(self):
297- """Read the branch list.
298-
299- :return: List of utf-8 encoded branch names.
300- """
301- try:
302- f = self.control_transport.get('branch-list')
303- except errors.NoSuchFile:
304- return []
305-
306- ret = []
307- try:
308- for name in f:
309- ret.append(name.rstrip("\n"))
310- finally:
311- f.close()
312- return ret
313-
314- def _write_branch_list(self, branches):
315- """Write out the branch list.
316-
317- :param branches: List of utf-8 branch names to write
318- """
319- self.transport.put_bytes('branch-list',
320- "".join([name+"\n" for name in branches]))
321-
322- def destroy_branch(self, name=None):
323- """See BzrDir.create_branch."""
324- if name is None:
325- name = self._get_selected_branch()
326- path = self._get_branch_path(name)
327- if name != "":
328- self.control_files.lock_write()
329- try:
330- branches = self._read_branch_list()
331- try:
332- branches.remove(name.encode("utf-8"))
333- except ValueError:
334- raise errors.NotBranchError(name)
335- self._write_branch_list(branches)
336- finally:
337- self.control_files.unlock()
338- self.transport.delete_tree(path)
339-
340- def get_branches(self):
341- """See ControlDir.get_branches."""
342- ret = {}
343- try:
344- ret[""] = self.open_branch(name="")
345- except (errors.NotBranchError, errors.NoRepositoryPresent):
346- pass
347-
348- for name in self._read_branch_list():
349- ret[name] = self.open_branch(name=name.decode('utf-8'))
350-
351- return ret
352-
353- def get_branch_transport(self, branch_format, name=None):
354- """See BzrDir.get_branch_transport()."""
355- if name is None:
356- name = self._get_selected_branch()
357- path = self._get_branch_path(name)
358- # XXX: this shouldn't implicitly create the directory if it's just
359- # promising to get a transport -- mbp 20090727
360- if branch_format is None:
361- return self.transport.clone(path)
362- try:
363- branch_format.get_format_string()
364- except NotImplementedError:
365- raise errors.IncompatibleFormat(branch_format, self._format)
366- if name != "":
367- branches = self._read_branch_list()
368- utf8_name = name.encode("utf-8")
369- if not utf8_name in branches:
370- self.control_files.lock_write()
371- try:
372- branches = self._read_branch_list()
373- dirname = urlutils.dirname(utf8_name)
374- if dirname != "" and dirname in branches:
375- raise errors.ParentBranchExists(name)
376- child_branches = [
377- b.startswith(utf8_name+"/") for b in branches]
378- if any(child_branches):
379- raise errors.AlreadyBranchError(name)
380- branches.append(utf8_name)
381- self._write_branch_list(branches)
382- finally:
383- self.control_files.unlock()
384- branch_transport = self.transport.clone(path)
385- branch_transport.create_prefix()
386- try:
387- self.transport.mkdir('.', mode=self._get_mkdir_mode())
388- except errors.FileExists:
389- pass
390- return branch_transport
391-
392-
393 class BzrFormat(object):
394 """Base class for all formats of things living in metadirs.
395
396@@ -1579,7 +1545,7 @@
397
398 fixed_components = False
399
400- colocated_branches = False
401+ colocated_branches = True
402
403 def __init__(self):
404 BzrDirFormat.__init__(self)
405@@ -1712,7 +1678,7 @@
406 return ConvertMetaToColo(format)
407 if (type(self) is BzrDirMetaFormat1Colo and
408 type(format) is BzrDirMetaFormat1):
409- return ConvertMetaRemoveColo(format)
410+ return ConvertMetaToColo(format)
411 if not isinstance(self, format.__class__):
412 # converting away from metadir is not implemented
413 raise NotImplementedError(self.get_converter)
414@@ -1814,7 +1780,7 @@
415 # problems.
416 format = BzrDirMetaFormat1Colo()
417 self._supply_sub_formats_to(format)
418- return BzrDirMeta1Colo(transport, format)
419+ return BzrDirMeta1(transport, format)
420
421
422 BzrProber.formats.register(BzrDirMetaFormat1Colo.get_format_string(),
423@@ -1916,12 +1882,12 @@
424 return BzrDir.open_from_transport(to_convert.root_transport)
425
426
427-class ConvertMetaRemoveColo(controldir.Converter):
428- """Remove colocated branch support from a bzrdir."""
429+class ConvertMetaToColo(controldir.Converter):
430+ """Convert a 'development-colo' bzrdir to a '2a' bzrdir."""
431
432 def __init__(self, target_format):
433- """Create a converter.that downgrades a colocated branch metadir
434- to a regular metadir.
435+ """Create a converter that converts a 'development-colo' metadir
436+ to a '2a' metadir.
437
438 :param target_format: The final metadir format that is desired.
439 """
440@@ -1929,14 +1895,6 @@
441
442 def convert(self, to_convert, pb):
443 """See Converter.convert()."""
444- to_convert.control_files.lock_write()
445- try:
446- branches = to_convert.list_branches()
447- if len(branches) > 1:
448- raise errors.BzrError("remove all but a single "
449- "colocated branch when downgrading")
450- finally:
451- to_convert.control_files.unlock()
452 to_convert.transport.put_bytes('branch-format',
453 self.target_format.as_string())
454 return BzrDir.open_from_transport(to_convert.root_transport)
455
456=== modified file 'bzrlib/remote.py'
457--- bzrlib/remote.py 2012-01-27 13:33:53 +0000
458+++ bzrlib/remote.py 2012-01-28 02:10:28 +0000
459@@ -59,7 +59,7 @@
460 from bzrlib.repository import RepositoryWriteLockResult, _LazyListJoin
461 from bzrlib.serializer import format_registry as serializer_format_registry
462 from bzrlib.trace import mutter, note, warning, log_exception_quietly
463-from bzrlib.versionedfile import ChunkedContentFactory, FulltextContentFactory
464+from bzrlib.versionedfile import FulltextContentFactory
465
466
467 _DEFAULT_SEARCH_DEPTH = 100
468@@ -113,6 +113,8 @@
469
470 supports_workingtrees = False
471
472+ colocated_branches = False
473+
474 def __init__(self):
475 _mod_bzrdir.BzrDirMetaFormat1.__init__(self)
476 # XXX: It's a bit ugly that the network name is here, because we'd
477@@ -627,6 +629,8 @@
478 append_revisions_only=None):
479 if name is None:
480 name = self._get_selected_branch()
481+ if name != "":
482+ raise errors.NoColocatedBranchSupport(self)
483 # as per meta1 formats - just delegate to the format object which may
484 # be parameterised.
485 real_branch = self._format.get_branch_format().initialize(self,
486@@ -651,9 +655,13 @@
487
488 def destroy_branch(self, name=None):
489 """See BzrDir.destroy_branch"""
490+ if name is None:
491+ name = self._get_selected_branch()
492+ if name != "":
493+ raise errors.NoColocatedBranchSupport(self)
494 path = self._path_for_remote_call(self._client)
495 try:
496- if name is not None:
497+ if name != "":
498 args = (name, )
499 else:
500 args = ()
501@@ -699,13 +707,18 @@
502
503 def set_branch_reference(self, target_branch, name=None):
504 """See BzrDir.set_branch_reference()."""
505+ if name is None:
506+ name = self._get_selected_branch()
507+ if name != "":
508+ raise errors.NoColocatedBranchSupport(self)
509 self._ensure_real()
510 return self._real_bzrdir.set_branch_reference(target_branch, name=name)
511
512 def get_branch_reference(self, name=None):
513 """See BzrDir.get_branch_reference()."""
514- if name is not None:
515- # XXX JRV20100304: Support opening colocated branches
516+ if name is None:
517+ name = self._get_selected_branch()
518+ if name != "":
519 raise errors.NoColocatedBranchSupport(self)
520 response = self._get_branch_reference()
521 if response[0] == 'ref':
522@@ -765,6 +778,10 @@
523
524 def open_branch(self, name=None, unsupported=False,
525 ignore_fallbacks=False, possible_transports=None):
526+ if name is None:
527+ name = self._get_selected_branch()
528+ if name != "":
529+ raise errors.NoColocatedBranchSupport(self)
530 if unsupported:
531 raise NotImplementedError('unsupported flag support not implemented yet.')
532 if self._next_open_branch_result is not None:
533@@ -773,8 +790,6 @@
534 self._next_open_branch_result = None
535 return result
536 response = self._get_branch_reference()
537- if name is None:
538- name = self._get_selected_branch()
539 return self._open_branch(name, response[0], response[1],
540 possible_transports=possible_transports,
541 ignore_fallbacks=ignore_fallbacks)
542@@ -3122,10 +3137,10 @@
543 if isinstance(a_bzrdir, RemoteBzrDir):
544 a_bzrdir._ensure_real()
545 result = self._custom_format.initialize(a_bzrdir._real_bzrdir,
546- name, append_revisions_only=append_revisions_only)
547+ name=name, append_revisions_only=append_revisions_only)
548 else:
549 # We assume the bzrdir is parameterised; it may not be.
550- result = self._custom_format.initialize(a_bzrdir, name,
551+ result = self._custom_format.initialize(a_bzrdir, name=name,
552 append_revisions_only=append_revisions_only)
553 if (isinstance(a_bzrdir, RemoteBzrDir) and
554 not isinstance(result, RemoteBranch)):
555@@ -3322,6 +3337,7 @@
556 # will try to assign to self.tags, which is a property in this subclass.
557 # And the parent's __init__ doesn't do much anyway.
558 self.bzrdir = remote_bzrdir
559+ self.name = name
560 if _client is not None:
561 self._client = _client
562 else:
563
564=== modified file 'bzrlib/switch.py'
565--- bzrlib/switch.py 2012-01-18 19:14:21 +0000
566+++ bzrlib/switch.py 2012-01-28 02:10:28 +0000
567@@ -45,7 +45,11 @@
568 source_repository = control_dir.open_branch().repository
569 except errors.NotBranchError:
570 source_repository = to_branch.repository
571- _set_branch_location(control_dir, to_branch, force)
572+ to_branch.lock_read()
573+ try:
574+ _set_branch_location(control_dir, to_branch, force)
575+ finally:
576+ to_branch.unlock()
577 tree = control_dir.open_workingtree()
578 _update(tree, source_repository, quiet, revision_id)
579 _run_post_switch_hooks(control_dir, to_branch, force, revision_id)
580@@ -109,15 +113,19 @@
581 else:
582 # If this is a standalone tree and the new branch
583 # is derived from this one, create a lightweight checkout.
584- graph = b.repository.get_graph(to_branch.repository)
585- if (b.bzrdir._format.colocated_branches and
586- (force or graph.is_ancestor(b.last_revision(),
587- to_branch.last_revision()))):
588- b.bzrdir.destroy_branch()
589- b.bzrdir.set_branch_reference(to_branch, name="")
590- else:
591- raise errors.BzrCommandError(gettext('Cannot switch a branch, '
592- 'only a checkout.'))
593+ b.lock_read()
594+ try:
595+ graph = b.repository.get_graph(to_branch.repository)
596+ if (b.bzrdir._format.colocated_branches and
597+ (force or graph.is_ancestor(b.last_revision(),
598+ to_branch.last_revision()))):
599+ b.bzrdir.destroy_branch()
600+ b.bzrdir.set_branch_reference(to_branch, name="")
601+ else:
602+ raise errors.BzrCommandError(gettext('Cannot switch a branch, '
603+ 'only a checkout.'))
604+ finally:
605+ b.unlock()
606
607
608 def _any_local_commits(this_branch, possible_transports):
609
610=== modified file 'bzrlib/tests/blackbox/test_branch.py'
611--- bzrlib/tests/blackbox/test_branch.py 2012-01-25 17:41:05 +0000
612+++ bzrlib/tests/blackbox/test_branch.py 2012-01-28 02:10:28 +0000
613@@ -155,14 +155,15 @@
614 # => new branch will be created, but switch fails and the current
615 # branch is unmodified
616 self.example_branch('a')
617- self.make_branch_and_tree('current')
618+ tree = self.make_branch_and_tree('current')
619+ c1 = tree.commit('some diverged change')
620 self.run_bzr_error(['Cannot switch a branch, only a checkout'],
621 'branch --switch ../a ../b', working_dir='current')
622 a = branch.Branch.open('a')
623 b = branch.Branch.open('b')
624 self.assertEqual(a.last_revision(), b.last_revision())
625 work = branch.Branch.open('current')
626- self.assertEqual(work.last_revision(), _mod_revision.NULL_REVISION)
627+ self.assertEqual(work.last_revision(), c1)
628
629 def test_branch_into_empty_dir(self):
630 t = self.example_branch('source')
631
632=== modified file 'bzrlib/tests/blackbox/test_info.py'
633--- bzrlib/tests/blackbox/test_info.py 2012-01-19 16:51:39 +0000
634+++ bzrlib/tests/blackbox/test_info.py 2012-01-28 02:10:28 +0000
635@@ -99,6 +99,9 @@
636 branch: Branch format 5
637 repository: Knit repository format 1
638
639+Control directory:
640+ 1 branches
641+
642 In the working tree:
643 0 unchanged
644 0 modified
645@@ -130,6 +133,9 @@
646 branch: Branch format 5
647 repository: Knit repository format 1
648
649+Control directory:
650+ 1 branches
651+
652 In the working tree:
653 0 unchanged
654 0 modified
655@@ -184,6 +190,9 @@
656 branch: Branch format 5
657 repository: Knit repository format 1
658
659+Control directory:
660+ 1 branches
661+
662 In the working tree:
663 1 unchanged
664 0 modified
665@@ -230,6 +239,9 @@
666 branch: %s
667 repository: %s
668
669+Control directory:
670+ 1 branches
671+
672 In the working tree:
673 1 unchanged
674 0 modified
675@@ -273,6 +285,9 @@
676 branch: Branch format 5
677 repository: %s
678
679+Control directory:
680+ 1 branches
681+
682 In the working tree:
683 1 unchanged
684 0 modified
685@@ -316,6 +331,9 @@
686 branch: Branch format 5
687 repository: Knit repository format 1
688
689+Control directory:
690+ 1 branches
691+
692 In the working tree:
693 1 unchanged
694 0 modified
695@@ -361,6 +379,9 @@
696 branch: Branch format 5
697 repository: Knit repository format 1
698
699+Control directory:
700+ 1 branches
701+
702 In the working tree:
703 1 unchanged
704 0 modified
705@@ -400,6 +421,9 @@
706 branch: Branch format 5
707 repository: %s
708
709+Control directory:
710+ 1 branches
711+
712 Branch is out of date: missing 1 revision.
713
714 In the working tree:
715@@ -439,6 +463,9 @@
716 branch: Branch format 5
717 repository: %s
718
719+Control directory:
720+ 1 branches
721+
722 Branch is out of date: missing 1 revision.
723
724 In the working tree:
725@@ -478,6 +505,9 @@
726 branch: Branch format 5
727 repository: Knit repository format 1
728
729+Control directory:
730+ 1 branches
731+
732 Working tree is out of date: missing 1 revision.
733
734 In the working tree:
735@@ -517,6 +547,9 @@
736 branch: %s
737 repository: %s
738
739+Control directory:
740+ 1 branches
741+
742 Branch history:
743 0 revisions
744
745@@ -545,6 +578,9 @@
746 control: Meta directory format 1
747 repository: %s
748
749+Control directory:
750+ 0 branches
751+
752 Repository:
753 0 revisions
754 """ % ('repo', format.repository_format.get_format_description(),
755@@ -567,6 +603,9 @@
756 branch: %s
757 repository: %s
758
759+Control directory:
760+ 1 branches
761+
762 Branch history:
763 0 revisions
764
765@@ -611,6 +650,9 @@
766 branch: %s
767 repository: %s
768
769+Control directory:
770+ 1 branches
771+
772 In the working tree:
773 1 unchanged
774 0 modified
775@@ -649,6 +691,9 @@
776 branch: %s
777 repository: %s
778
779+Control directory:
780+ 1 branches
781+
782 Branch is out of date: missing 1 revision.
783
784 In the working tree:
785@@ -688,6 +733,9 @@
786 branch: %s
787 repository: %s
788
789+Control directory:
790+ 1 branches
791+
792 In the working tree:
793 1 unchanged
794 0 modified
795@@ -730,6 +778,9 @@
796 branch: %s
797 repository: %s
798
799+Control directory:
800+ 1 branches
801+
802 Working tree is out of date: missing 1 revision.
803
804 In the working tree:
805@@ -769,6 +820,9 @@
806 branch: %s
807 repository: %s
808
809+Control directory:
810+ 1 branches
811+
812 Branch history:
813 2 revisions
814 0 days old
815@@ -794,6 +848,9 @@
816 control: Meta directory format 1
817 repository: %s
818
819+Control directory:
820+ 0 branches
821+
822 Repository:
823 2 revisions
824 """ % (format.repository_format.get_format_description(),
825@@ -817,6 +874,9 @@
826 control: Meta directory format 1
827 repository: %s
828
829+Control directory:
830+ 0 branches
831+
832 Create working tree for new branches inside the repository.
833
834 Repository:
835@@ -845,6 +905,9 @@
836 branch: %s
837 repository: %s
838
839+Control directory:
840+ 1 branches
841+
842 In the working tree:
843 0 unchanged
844 0 modified
845@@ -885,6 +948,9 @@
846 branch: %s
847 repository: %s
848
849+Control directory:
850+ 1 branches
851+
852 In the working tree:
853 1 unchanged
854 0 modified
855@@ -926,6 +992,9 @@
856 branch: %s
857 repository: %s
858
859+Control directory:
860+ 1 branches
861+
862 In the working tree:
863 0 unchanged
864 0 modified
865@@ -965,6 +1034,9 @@
866 branch: %s
867 repository: %s
868
869+Control directory:
870+ 1 branches
871+
872 In the working tree:
873 1 unchanged
874 0 modified
875@@ -1000,6 +1072,9 @@
876 control: Meta directory format 1
877 repository: %s
878
879+Control directory:
880+ 0 branches
881+
882 Create working tree for new branches inside the repository.
883
884 Repository:
885@@ -1026,6 +1101,9 @@
886 control: Meta directory format 1
887 repository: %s
888
889+Control directory:
890+ 0 branches
891+
892 Create working tree for new branches inside the repository.
893
894 Repository:
895@@ -1051,6 +1129,9 @@
896 branch: %s
897 repository: %s
898
899+Control directory:
900+ 1 branches
901+
902 In the working tree:
903 0 unchanged
904 0 modified
905@@ -1088,6 +1169,9 @@
906 control: Meta directory format 1
907 repository: %s
908
909+Control directory:
910+ 0 branches
911+
912 Create working tree for new branches inside the repository.
913
914 Repository:
915@@ -1227,6 +1311,9 @@
916 branch: %s
917 repository: %s
918 %s
919+Control directory:
920+ 1 branches
921+
922 In the working tree:
923 0 unchanged
924 0 modified
925@@ -1403,6 +1490,9 @@
926 branch: Branch format 7
927 repository: Repository format 2a - rich roots, group compression and chk inventories
928
929+Control directory:
930+ 1 branches
931+
932 In the working tree:
933 0 unchanged
934 0 modified
935
936=== modified file 'bzrlib/tests/per_branch/test_branch.py'
937--- bzrlib/tests/per_branch/test_branch.py 2012-01-04 17:12:42 +0000
938+++ bzrlib/tests/per_branch/test_branch.py 2012-01-28 02:10:28 +0000
939@@ -318,11 +318,17 @@
940 repo = self.make_repository('.', shared=True)
941 except errors.IncompatibleFormat:
942 return
943+ if repo.bzrdir._format.colocated_branches:
944+ raise tests.TestNotApplicable(
945+ "control dir does not support colocated branches")
946 self.assertEquals(0, len(repo.bzrdir.list_branches()))
947+ if not self.bzrdir_format.colocated_branches:
948+ raise tests.TestNotApplicable("control dir format does not support "
949+ "colocated branches")
950 try:
951 child_branch1 = self.branch_format.initialize(repo.bzrdir,
952 name='branch1')
953- except (errors.UninitializableFormat, errors.NoColocatedBranchSupport):
954+ except errors.UninitializableFormat:
955 # branch references are not default init'able and
956 # not all bzrdirs support colocated branches.
957 return
958
959=== modified file 'bzrlib/tests/per_bzrdir/test_bzrdir.py'
960--- bzrlib/tests/per_bzrdir/test_bzrdir.py 2012-01-27 14:36:00 +0000
961+++ bzrlib/tests/per_bzrdir/test_bzrdir.py 2012-01-28 02:10:28 +0000
962@@ -685,10 +685,9 @@
963
964 def test_get_branches(self):
965 repo = self.make_repository('branch-1')
966- try:
967- target_branch = repo.bzrdir.create_branch(name='foo')
968- except errors.NoColocatedBranchSupport:
969+ if not repo.bzrdir._format.colocated_branches:
970 raise TestNotApplicable('Format does not support colocation')
971+ target_branch = repo.bzrdir.create_branch(name='foo')
972 repo.bzrdir.set_branch_reference(target_branch)
973 self.assertEqual(set(["", 'foo']),
974 set(repo.bzrdir.get_branches().keys()))
975
976=== modified file 'bzrlib/tests/per_controldir_colo/__init__.py'
977--- bzrlib/tests/per_controldir_colo/__init__.py 2010-08-21 16:06:24 +0000
978+++ bzrlib/tests/per_controldir_colo/__init__.py 2012-01-28 02:10:28 +0000
979@@ -27,17 +27,23 @@
980 from bzrlib.tests import (
981 default_transport,
982 multiply_tests,
983+ test_server,
984 )
985 from bzrlib.tests.per_controldir import (
986 TestCaseWithControlDir,
987 make_scenarios,
988 )
989+from bzrlib.transport import memory
990
991
992 def load_tests(standard_tests, module, loader):
993 colo_supported_formats = []
994 colo_unsupported_formats = []
995+ # This will always add scenarios using the smart server.
996+ from bzrlib.remote import RemoteBzrDirFormat
997 for format in ControlDirFormat.known_formats():
998+ if isinstance(format, RemoteBzrDirFormat):
999+ continue
1000 if format.colocated_branches:
1001 colo_supported_formats.append(format)
1002 else:
1003@@ -46,6 +52,22 @@
1004 colo_supported_formats)
1005 unsupported_scenarios = make_scenarios(default_transport, None, None,
1006 colo_unsupported_formats)
1007+ # test the remote server behaviour when backed with a MemoryTransport
1008+ # Once for the current version
1009+ unsupported_scenarios.extend(make_scenarios(
1010+ memory.MemoryServer,
1011+ test_server.SmartTCPServer_for_testing,
1012+ test_server.ReadonlySmartTCPServer_for_testing,
1013+ [(RemoteBzrDirFormat())],
1014+ name_suffix='-default'))
1015+ # And once with < 1.6 - the 'v2' protocol.
1016+ unsupported_scenarios.extend(make_scenarios(
1017+ memory.MemoryServer,
1018+ test_server.SmartTCPServer_for_testing_v2_only,
1019+ test_server.ReadonlySmartTCPServer_for_testing_v2_only,
1020+ [(RemoteBzrDirFormat())],
1021+ name_suffix='-v2'))
1022+
1023 result = loader.suiteClass()
1024 supported_tests = loader.loadTestsFromModuleNames([
1025 'bzrlib.tests.per_controldir_colo.test_supported'])
1026
1027=== modified file 'bzrlib/tests/per_controldir_colo/test_unsupported.py'
1028--- bzrlib/tests/per_controldir_colo/test_unsupported.py 2012-01-18 17:37:38 +0000
1029+++ bzrlib/tests/per_controldir_colo/test_unsupported.py 2012-01-28 02:10:28 +0000
1030@@ -40,9 +40,10 @@
1031 raise tests.TestNotApplicable('Control dir format not supported')
1032 t = self.get_transport()
1033 try:
1034- made_control = self.bzrdir_format.initialize(t.base)
1035+ made_control = self.make_bzrdir('.', format=self.bzrdir_format)
1036 except errors.UninitializableFormat:
1037 raise tests.TestNotApplicable('Control dir format not initializable')
1038+ self.assertEquals(made_control._format, self.bzrdir_format)
1039 made_repo = made_control.create_repository()
1040 return made_control
1041
1042
1043=== modified file 'bzrlib/tests/test_bzrdir.py'
1044--- bzrlib/tests/test_bzrdir.py 2012-01-27 15:47:12 +0000
1045+++ bzrlib/tests/test_bzrdir.py 2012-01-28 02:10:28 +0000
1046@@ -1447,8 +1447,8 @@
1047 tree.bzrdir.create_branch(name="another-colocated-branch")
1048 converter = tree.bzrdir._format.get_converter(
1049 bzrdir.BzrDirMetaFormat1())
1050- self.assertRaises(errors.BzrError, converter.convert, tree.bzrdir,
1051- None)
1052+ result = converter.convert(tree.bzrdir, bzrdir.BzrDirMetaFormat1())
1053+ self.assertIsInstance(result._format, bzrdir.BzrDirMetaFormat1)
1054
1055 def test_nested(self):
1056 tree = self.make_branch_and_tree('.', format='development-colo')
1057
1058=== modified file 'bzrlib/tests/test_remote.py'
1059--- bzrlib/tests/test_remote.py 2012-01-06 22:06:36 +0000
1060+++ bzrlib/tests/test_remote.py 2012-01-28 02:10:28 +0000
1061@@ -589,18 +589,6 @@
1062 a_bzrdir.destroy_branch()
1063 self.assertFinished(client)
1064
1065- def test_destroy_named(self):
1066- transport = self.get_transport('quack')
1067- referenced = self.make_branch('referenced')
1068- client = FakeClient(transport.base)
1069- client.add_expected_call(
1070- 'BzrDir.destroy_branch', ('quack/', "foo"),
1071- 'success', ('ok',)),
1072- a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1073- _client=client)
1074- a_bzrdir.destroy_branch("foo")
1075- self.assertFinished(client)
1076-
1077
1078 class TestBzrDirHasWorkingTree(TestRemote):
1079
1080
1081=== modified file 'bzrlib/transport/__init__.py'
1082--- bzrlib/transport/__init__.py 2012-01-20 13:15:15 +0000
1083+++ bzrlib/transport/__init__.py 2012-01-28 02:10:28 +0000
1084@@ -364,7 +364,7 @@
1085 """
1086 raise NotImplementedError(self.clone)
1087
1088- def create_prefix(self):
1089+ def create_prefix(self, mode=None):
1090 """Create all the directories leading down to self.base."""
1091 cur_transport = self
1092 needed = [cur_transport]
1093@@ -376,7 +376,7 @@
1094 "Failed to create path prefix for %s."
1095 % cur_transport.base)
1096 try:
1097- new_transport.mkdir('.')
1098+ new_transport.mkdir('.', mode=mode)
1099 except errors.NoSuchFile:
1100 needed.append(new_transport)
1101 cur_transport = new_transport
1102@@ -387,9 +387,9 @@
1103 # Now we only need to create child directories
1104 while needed:
1105 cur_transport = needed.pop()
1106- cur_transport.ensure_base()
1107+ cur_transport.ensure_base(mode=mode)
1108
1109- def ensure_base(self):
1110+ def ensure_base(self, mode=None):
1111 """Ensure that the directory this transport references exists.
1112
1113 This will create a directory if it doesn't exist.
1114@@ -399,7 +399,7 @@
1115 # than permission". We attempt to create the directory, and just
1116 # suppress FileExists and PermissionDenied (for Windows) exceptions.
1117 try:
1118- self.mkdir('.')
1119+ self.mkdir('.', mode=mode)
1120 except (errors.FileExists, errors.PermissionDenied):
1121 return False
1122 else:
1123
1124=== modified file 'doc/en/release-notes/bzr-2.5.txt'
1125--- doc/en/release-notes/bzr-2.5.txt 2012-01-27 21:40:55 +0000
1126+++ doc/en/release-notes/bzr-2.5.txt 2012-01-28 02:10:28 +0000
1127@@ -20,6 +20,9 @@
1128
1129 .. New commands, options, etc that users may wish to try out.
1130
1131+* Support for colocated branches is now available in the default
1132+ format ("2a"). (Jelmer Vernooij)
1133+
1134 Improvements
1135 ************
1136

Subscribers

People subscribed via source and target branches