Merge lp:~jelmer/bzr/colocated-names into lp:bzr

Proposed by Jelmer Vernooij
Status: Superseded
Proposed branch: lp:~jelmer/bzr/colocated-names
Merge into: lp:bzr
Diff against target: 336 lines (+55/-29)
11 files modified
bzrlib/branch.py (+14/-7)
bzrlib/builtins.py (+2/-2)
bzrlib/bzrdir.py (+13/-7)
bzrlib/controldir.py (+4/-4)
bzrlib/plugins/weave_fmt/branch.py (+3/-1)
bzrlib/remote.py (+7/-1)
bzrlib/smart/bzrdir.py (+1/-1)
bzrlib/tests/per_bzrdir/test_bzrdir.py (+1/-1)
bzrlib/tests/per_controldir/test_controldir.py (+2/-2)
bzrlib/tests/per_controldir_colo/test_unsupported.py (+1/-1)
bzrlib/tests/test_foreign.py (+7/-2)
To merge this branch: bzr merge lp:~jelmer/bzr/colocated-names
Reviewer Review Type Date Requested Status
Vincent Ladeuil Approve
Review via email: mp+87840@code.launchpad.net

This proposal has been superseded by a proposal from 2012-01-17.

Description of the change

Slightly tweak the naming of colocated branches.

Use "" for the name of the default branch - e.g. the branch in .bzr/branch
Use None for the name of the selected branch

The default and selected branch aren't necessarily the same; the selected
branch can be different if selected in the URL ("http://example.com/path/to/dir,branch=foo")

This is a slight API change, but one which only should affect bzr 2.5.

To post a comment you must log in.
Revision history for this message
Vincent Ladeuil (vila) wrote :

Hmm, 2.5 API is frozen :)

Now, if this is internal only I think it's fair enough to go in but the fallouts of having a distinctin between a selected branch and a default branch are unclear. Can you give some more examples of why it matters and where it's needed ?

A few nits:

51 - result = real_bzrdir.open_branch(name=name,
52 - ignore_fallbacks=ignore_fallbacks,
53 + result = real_bzrdir.open_branch(ignore_fallbacks=ignore_fallbacks,

Err, wait, you got 'name' a few lines above why force the callee to get it
again ?

63 + if name is None:
64 + raise ValueError('name must be supplied')
65 + self.bzrdir = a_bzrdir

Sounds like a good time to document 'name' in the ivars few lines above ;)

But going further, why not change the 'name' default value to "" ?

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

> Now, if this is internal only I think it's fair enough to go in but the fallouts of having a distinctin between a >
> selected branch and a default branch are unclear. Can you give some more examples of why it matters and where it's
> needed ?
I think this is a necessary bug fix, because without it it is impossible to open the current branch through the control directory if the user has already selected a different branch. I.e. we want:

BzrDir.open_from_url("file:foo,branch=bar").open_branch(name=None) to return branch ".bzr/branches/bar" and
BzrDir.open_from_url("file:foo,branch=bar").open_branch(name="") to return ".bzr/branch".

> A few nits:

> 51 - result = real_bzrdir.open_branch(name=name,
> 52 - ignore_fallbacks=ignore_fallbacks,
> 53 + result = real_bzrdir.open_branch(ignore_fallbacks=ignore_fallbacks,

> Err, wait, you got 'name' a few lines above why force the callee to get it
> again ?

real_bzrdir is for the branch we're referencing. name is the name of *our* branch (the referencing branch), not the name of the branch that's referenced. The previous code was wrong.

63 + if name is None:
64 + raise ValueError('name must be supplied')
65 + self.bzrdir = a_bzrdir

> Sounds like a good time to document 'name' in the ivars few lines above ;)
name isn't an instance variable, so I'm not sure I follow what you mean?

> But going further, why not change the 'name' default value to "" ?
Because we don't want to default to "", we want to use "" only IFF the user hasn't specified a branch in the URL.

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

> > Now, if this is internal only I think it's fair enough to go in but the
> fallouts of having a distinctin between a >
> > selected branch and a default branch are unclear. Can you give some more
> examples of why it matters and where it's
> > needed ?
> I think this is a necessary bug fix, because without it it is impossible to
> open the current branch through the control directory if the user has already
> selected a different branch. I.e. we want:
>
> BzrDir.open_from_url("file:foo,branch=bar").open_branch(name=None) to return
> branch ".bzr/branches/bar" and
> BzrDir.open_from_url("file:foo,branch=bar").open_branch(name="") to return
> ".bzr/branch".

Excellent, I smelled something but couldn't put my finger on it.

>
> > A few nits:
>
> > 51 - result = real_bzrdir.open_branch(name=name,
> > 52 - ignore_fallbacks=ignore_fallbacks,
> > 53 + result = real_bzrdir.open_branch(ignore_fallbacks=ignore_fallbacks,
>
> > Err, wait, you got 'name' a few lines above why force the callee to get it
> > again ?
>
> real_bzrdir is for the branch we're referencing. name is the name of *our*
> branch (the referencing branch), not the name of the branch that's referenced.
> The previous code was wrong.

Ok.

>
> 63 + if name is None:
> 64 + raise ValueError('name must be supplied')
> 65 + self.bzrdir = a_bzrdir
>
> > Sounds like a good time to document 'name' in the ivars few lines above ;)
> name isn't an instance variable, so I'm not sure I follow what you mean?

self.name = name a few lines below ?

>
> > But going further, why not change the 'name' default value to "" ?
> Because we don't want to default to "", we want to use "" only IFF the user
> hasn't specified a branch in the URL.

Ok, don't forget to target lp:bzr/2.5 and probably a news entry in the bug fixes section.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bzrlib/branch.py'
2--- bzrlib/branch.py 2012-01-04 17:12:42 +0000
3+++ bzrlib/branch.py 2012-01-07 01:57:25 +0000
4@@ -2038,6 +2038,8 @@
5 :param name: Name of colocated branch to create, if any
6 :return: a branch in this format
7 """
8+ if name is None:
9+ name = a_bzrdir._get_selected_branch()
10 mutter('creating branch %r in %s', self, a_bzrdir.user_url)
11 branch_transport = a_bzrdir.get_branch_transport(self, name=name)
12 control_files = lockable_files.LockableFiles(branch_transport,
13@@ -2060,6 +2062,8 @@
14 def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False,
15 found_repository=None, possible_transports=None):
16 """See BranchFormat.open()."""
17+ if name is None:
18+ name = a_bzrdir._get_selected_branch()
19 if not _found:
20 format = BranchFormatMetadir.find_format(a_bzrdir, name=name)
21 if format.__class__ != self.__class__:
22@@ -2305,12 +2309,13 @@
23 mutter('creating branch reference in %s', a_bzrdir.user_url)
24 if a_bzrdir._format.fixed_components:
25 raise errors.IncompatibleFormat(self, a_bzrdir._format)
26+ if name is None:
27+ name = a_bzrdir._get_selected_branch()
28 branch_transport = a_bzrdir.get_branch_transport(self, name=name)
29 branch_transport.put_bytes('location',
30 target_branch.user_url)
31 branch_transport.put_bytes('format', self.as_string())
32- branch = self.open(
33- a_bzrdir, name, _found=True,
34+ branch = self.open(a_bzrdir, name, _found=True,
35 possible_transports=[target_branch.bzrdir.root_transport])
36 self._run_post_branch_init_hooks(a_bzrdir, name, branch)
37 return branch
38@@ -2342,6 +2347,8 @@
39 a_bzrdir.
40 :param possible_transports: An optional reusable transports list.
41 """
42+ if name is None:
43+ name = a_bzrdir._get_selected_branch()
44 if not _found:
45 format = BranchFormatMetadir.find_format(a_bzrdir, name=name)
46 if format.__class__ != self.__class__:
47@@ -2351,8 +2358,7 @@
48 location = self.get_reference(a_bzrdir, name)
49 real_bzrdir = controldir.ControlDir.open(
50 location, possible_transports=possible_transports)
51- result = real_bzrdir.open_branch(name=name,
52- ignore_fallbacks=ignore_fallbacks,
53+ result = real_bzrdir.open_branch(ignore_fallbacks=ignore_fallbacks,
54 possible_transports=possible_transports)
55 # this changes the behaviour of result.clone to create a new reference
56 # rather than a copy of the content of the branch.
57@@ -2445,10 +2451,11 @@
58 """Create new branch object at a particular location."""
59 if a_bzrdir is None:
60 raise ValueError('a_bzrdir must be supplied')
61- else:
62- self.bzrdir = a_bzrdir
63+ if name is None:
64+ raise ValueError('name must be supplied')
65+ self.bzrdir = a_bzrdir
66 self._user_transport = self.bzrdir.transport.clone('..')
67- if name is not None:
68+ if name != "":
69 self._user_transport.set_segment_parameter(
70 "branch", urlutils.escape(name))
71 self._base = self._user_transport.base
72
73=== modified file 'bzrlib/builtins.py'
74--- bzrlib/builtins.py 2012-01-05 09:50:04 +0000
75+++ bzrlib/builtins.py 2012-01-07 01:57:25 +0000
76@@ -1444,13 +1444,13 @@
77 else:
78 dir = controldir.ControlDir.open_containing(location)[0]
79 try:
80- active_branch = dir.open_branch(name=None)
81+ active_branch = dir.open_branch(name="")
82 except errors.NotBranchError:
83 active_branch = None
84 branches = dir.get_branches()
85 names = {}
86 for name, branch in branches.iteritems():
87- if name is None:
88+ if name == "":
89 continue
90 active = (active_branch is not None and
91 active_branch.base == branch.base)
92
93=== modified file 'bzrlib/bzrdir.py'
94--- bzrlib/bzrdir.py 2011-12-22 19:54:56 +0000
95+++ bzrlib/bzrdir.py 2012-01-07 01:57:25 +0000
96@@ -829,7 +829,9 @@
97
98 def destroy_branch(self, name=None):
99 """See BzrDir.create_branch."""
100- if name is not None:
101+ if name is None:
102+ name = self._get_selected_branch()
103+ if name != "":
104 raise errors.NoColocatedBranchSupport(self)
105 self.transport.delete_tree('branch')
106
107@@ -887,7 +889,9 @@
108
109 def get_branch_transport(self, branch_format, name=None):
110 """See BzrDir.get_branch_transport()."""
111- if name is not None:
112+ if name is None:
113+ name = self._get_selected_branch()
114+ if name != "":
115 raise errors.NoColocatedBranchSupport(self)
116 # XXX: this shouldn't implicitly create the directory if it's just
117 # promising to get a transport -- mbp 20090727
118@@ -1021,7 +1025,7 @@
119 :param name: Optional branch name to use
120 :return: Relative path to branch
121 """
122- if name is None:
123+ if name == "":
124 return 'branch'
125 return urlutils.join('branches', name.encode("utf-8"))
126
127@@ -1056,7 +1060,7 @@
128 if name is None:
129 name = self._get_selected_branch()
130 path = self._get_branch_path(name)
131- if name is not None:
132+ if name != "":
133 self.control_files.lock_write()
134 try:
135 branches = self._read_branch_list()
136@@ -1073,17 +1077,19 @@
137 """See ControlDir.get_branches."""
138 ret = {}
139 try:
140- ret[None] = self.open_branch()
141+ ret[""] = self.open_branch(name="")
142 except (errors.NotBranchError, errors.NoRepositoryPresent):
143 pass
144
145 for name in self._read_branch_list():
146- ret[name] = self.open_branch(name.decode('utf-8'))
147+ ret[name] = self.open_branch(name=name.decode('utf-8'))
148
149 return ret
150
151 def get_branch_transport(self, branch_format, name=None):
152 """See BzrDir.get_branch_transport()."""
153+ if name is None:
154+ name = self._get_selected_branch()
155 path = self._get_branch_path(name)
156 # XXX: this shouldn't implicitly create the directory if it's just
157 # promising to get a transport -- mbp 20090727
158@@ -1093,7 +1099,7 @@
159 branch_format.get_format_string()
160 except NotImplementedError:
161 raise errors.IncompatibleFormat(branch_format, self._format)
162- if name is not None:
163+ if name != "":
164 try:
165 self.transport.mkdir('branches', mode=self._get_mkdir_mode())
166 except errors.FileExists:
167
168=== modified file 'bzrlib/controldir.py'
169--- bzrlib/controldir.py 2012-01-03 13:47:01 +0000
170+++ bzrlib/controldir.py 2012-01-07 01:57:25 +0000
171@@ -116,7 +116,7 @@
172 :return: Dictionary mapping branch names to instances.
173 """
174 try:
175- return { None: self.open_branch() }
176+ return { "": self.open_branch() }
177 except (errors.NotBranchError, errors.NoRepositoryPresent):
178 return {}
179
180@@ -294,9 +294,9 @@
181 :return: Name of the branch selected by the user, or None.
182 """
183 branch = self.root_transport.get_segment_parameters().get("branch")
184- if branch is not None:
185- branch = urlutils.unescape(branch)
186- return branch
187+ if branch is None:
188+ branch = ""
189+ return urlutils.unescape(branch)
190
191 def has_workingtree(self):
192 """Tell if this controldir contains a working tree.
193
194=== modified file 'bzrlib/plugins/weave_fmt/branch.py'
195--- bzrlib/plugins/weave_fmt/branch.py 2011-12-19 13:23:58 +0000
196+++ bzrlib/plugins/weave_fmt/branch.py 2012-01-07 01:57:25 +0000
197@@ -138,7 +138,9 @@
198 def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False,
199 found_repository=None, possible_transports=None):
200 """See BranchFormat.open()."""
201- if name is not None:
202+ if name is None:
203+ name = a_bzrdir._get_selected_branch()
204+ if name != "":
205 raise errors.NoColocatedBranchSupport(self)
206 if not _found:
207 # we are being called directly and must probe.
208
209=== modified file 'bzrlib/remote.py'
210--- bzrlib/remote.py 2012-01-04 16:02:14 +0000
211+++ bzrlib/remote.py 2012-01-07 01:57:25 +0000
212@@ -625,6 +625,8 @@
213
214 def create_branch(self, name=None, repository=None,
215 append_revisions_only=None):
216+ if name is None:
217+ name = self._get_selected_branch()
218 # as per meta1 formats - just delegate to the format object which may
219 # be parameterised.
220 real_branch = self._format.get_branch_format().initialize(self,
221@@ -724,6 +726,8 @@
222
223 def open_branch(self, name=None, unsupported=False,
224 ignore_fallbacks=False, possible_transports=None):
225+ if name is None:
226+ name = self._get_selected_branch()
227 if unsupported:
228 raise NotImplementedError('unsupported flag support not implemented yet.')
229 if self._next_open_branch_result is not None:
230@@ -3102,6 +3106,8 @@
231
232 def initialize(self, a_bzrdir, name=None, repository=None,
233 append_revisions_only=None):
234+ if name is None:
235+ name = a_bzrdir._get_selected_branch()
236 # 1) get the network name to use.
237 if self._custom_format:
238 network_name = self._custom_format.network_name()
239@@ -3122,7 +3128,7 @@
240 # Creating on a remote bzr dir.
241 # 2) try direct creation via RPC
242 path = a_bzrdir._path_for_remote_call(a_bzrdir._client)
243- if name is not None:
244+ if name != "":
245 # XXX JRV20100304: Support creating colocated branches
246 raise errors.NoColocatedBranchSupport(self)
247 verb = 'BzrDir.create_branch'
248
249=== modified file 'bzrlib/smart/bzrdir.py'
250--- bzrlib/smart/bzrdir.py 2011-12-19 13:23:58 +0000
251+++ bzrlib/smart/bzrdir.py 2012-01-07 01:57:25 +0000
252@@ -268,7 +268,7 @@
253 self.transport_from_client_path(path))
254 format = branch.network_format_registry.get(network_name)
255 bzrdir.branch_format = format
256- result = format.initialize(bzrdir)
257+ result = format.initialize(bzrdir, name="")
258 rich_root, tree_ref, external_lookup = self._format_to_capabilities(
259 result.repository._format)
260 branch_format = result._format.network_name()
261
262=== modified file 'bzrlib/tests/per_bzrdir/test_bzrdir.py'
263--- bzrlib/tests/per_bzrdir/test_bzrdir.py 2011-12-12 12:09:50 +0000
264+++ bzrlib/tests/per_bzrdir/test_bzrdir.py 2012-01-07 01:57:25 +0000
265@@ -693,5 +693,5 @@
266 raise TestNotApplicable('Format does not support colocation')
267 reference = branch.BranchReferenceFormat().initialize(
268 repo.bzrdir, target_branch=target_branch)
269- self.assertEqual(set([None, 'foo']),
270+ self.assertEqual(set(["", 'foo']),
271 set(repo.bzrdir.get_branches().keys()))
272
273=== modified file 'bzrlib/tests/per_controldir/test_controldir.py'
274--- bzrlib/tests/per_controldir/test_controldir.py 2011-12-27 12:18:36 +0000
275+++ bzrlib/tests/per_controldir/test_controldir.py 2012-01-07 01:57:25 +0000
276@@ -1195,7 +1195,7 @@
277 def test_get_branches(self):
278 repo = self.make_repository('branch-1')
279 target_branch = repo.bzrdir.create_branch()
280- self.assertEqual([None], repo.bzrdir.get_branches().keys())
281+ self.assertEqual([""], repo.bzrdir.get_branches().keys())
282
283 def test_create_repository(self):
284 # a bzrdir can construct a repository for itself.
285@@ -1342,7 +1342,7 @@
286 raise TestSkipped("Can't initialize %r on transport %r"
287 % (self.bzrdir_format, t))
288 dir = bzrdir.BzrDir.open(t.base)
289- self.assertIs(None, dir._get_selected_branch())
290+ self.assertEqual(u"", dir._get_selected_branch())
291
292 def test_root_transport(self):
293 dir = self.make_bzrdir('.')
294
295=== modified file 'bzrlib/tests/per_controldir_colo/test_unsupported.py'
296--- bzrlib/tests/per_controldir_colo/test_unsupported.py 2011-12-11 04:07:08 +0000
297+++ bzrlib/tests/per_controldir_colo/test_unsupported.py 2012-01-07 01:57:25 +0000
298@@ -73,4 +73,4 @@
299 made_control = self.make_bzrdir_with_repo()
300 made_control.create_branch()
301 self.assertEqual(made_control.get_branches().keys(),
302- [None])
303+ [""])
304
305=== modified file 'bzrlib/tests/test_foreign.py'
306--- bzrlib/tests/test_foreign.py 2011-12-19 19:15:58 +0000
307+++ bzrlib/tests/test_foreign.py 2012-01-07 01:57:25 +0000
308@@ -240,6 +240,8 @@
309
310 def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False,
311 found_repository=None):
312+ if name is None:
313+ name = a_bzrdir._get_selected_branch()
314 if not _found:
315 raise NotImplementedError
316 try:
317@@ -251,7 +253,8 @@
318 return DummyForeignVcsBranch(_format=self,
319 _control_files=control_files,
320 a_bzrdir=a_bzrdir,
321- _repository=found_repository)
322+ _repository=found_repository,
323+ name=name)
324 except errors.NoSuchFile:
325 raise errors.NotBranchError(path=transport.base)
326
327@@ -317,7 +320,9 @@
328
329 def open_branch(self, name=None, unsupported=False, ignore_fallbacks=True,
330 possible_transports=None):
331- if name is not None:
332+ if name is None:
333+ name = self._get_selected_branch()
334+ if name != "":
335 raise errors.NoColocatedBranchSupport(self)
336 return self._format.get_branch_format().open(self, _found=True)
337