Merge lp:~jelmer/brz/git-config-branches into lp:brz

Proposed by Jelmer Vernooij on 2018-11-01
Status: Merged
Approved by: Jelmer Vernooij on 2019-03-04
Approved revision: 7148
Merge reported by: The Breezy Bot
Merged at revision: not available
Proposed branch: lp:~jelmer/brz/git-config-branches
Merge into: lp:brz
Diff against target: 302 lines (+139/-55)
6 files modified
breezy/git/branch.py (+68/-35)
breezy/git/tests/test_urls.py (+23/-4)
breezy/git/urls.py (+39/-12)
breezy/tests/per_branch/test_branch.py (+3/-1)
breezy/tests/per_branch/test_sprout.py (+4/-1)
breezy/urlutils.py (+2/-2)
To merge this branch: bzr merge lp:~jelmer/brz/git-config-branches
Reviewer Review Type Date Requested Status
Martin Packman 2018-11-01 Approve on 2018-11-16
Review via email: mp+358140@code.launchpad.net

Commit message

Support reading related branches from git configs.

Description of the change

Support reading related branches from git configs.

To post a comment you must log in.
Martin Packman (gz) wrote :

Looks good, see a couple of inline comments.

review: Approve
lp:~jelmer/brz/git-config-branches updated on 2019-03-04
7147. By Jelmer Vernooij on 2019-03-04

Merge trunk.

7148. By Jelmer Vernooij on 2019-03-04

Fix tests.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'breezy/git/branch.py'
2--- breezy/git/branch.py 2019-01-19 17:13:53 +0000
3+++ breezy/git/branch.py 2019-03-04 05:19:37 +0000
4@@ -76,7 +76,10 @@
5 from .unpeel_map import (
6 UnpeelMap,
7 )
8-from .urls import git_url_to_bzr_url
9+from .urls import (
10+ git_url_to_bzr_url,
11+ bzr_url_to_git_url,
12+ )
13
14
15 class GitPullResult(branch.PullResult):
16@@ -464,49 +467,76 @@
17 # Git doesn't do stacking (yet...)
18 raise branch.UnstackableBranchFormat(self._format, self.base)
19
20+ def _get_push_origin(self, cs):
21+ """Get the name for the push origin.
22+
23+ The exact behaviour is documented in the git-config(1) manpage.
24+ """
25+ try:
26+ return cs.get((b'branch', self.name.encode('utf-8')), b'pushRemote')
27+ except KeyError:
28+ try:
29+ return cs.get((b'branch', ), b'remote')
30+ except KeyError:
31+ try:
32+ return cs.get((b'branch', self.name.encode('utf-8')), b'remote')
33+ except KeyError:
34+ return b'origin'
35+
36+ def _get_origin(self, cs):
37+ try:
38+ return cs.get((b'branch', self.name.encode('utf-8')), b'remote')
39+ except KeyError:
40+ return b'origin'
41+
42+ def _get_related_push_branch(self, cs):
43+ remote = self._get_push_origin(cs)
44+ try:
45+ location = cs.get((b"remote", remote), b"url")
46+ except KeyError:
47+ return None
48+
49+ return git_url_to_bzr_url(location.decode('utf-8'), ref=self.ref)
50+
51+ def _get_related_merge_branch(self, cs):
52+ remote = self._get_origin(cs)
53+ try:
54+ location = cs.get((b"remote", remote), b"url")
55+ except KeyError:
56+ return None
57+
58+ try:
59+ ref = cs.get((b"branch", remote), b"merge")
60+ except KeyError:
61+ ref = self.ref
62+
63+ return git_url_to_bzr_url(location.decode('utf-8'), ref=ref)
64+
65 def _get_parent_location(self):
66 """See Branch.get_parent()."""
67- # FIXME: Set "origin" url from .git/config ?
68 cs = self.repository._git.get_config_stack()
69- try:
70- location = cs.get((b"remote", b'origin'), b"url")
71- except KeyError:
72- return None
73-
74- params = {}
75- try:
76- ref = cs.get((b"remote", b"origin"), b"merge")
77- except KeyError:
78- pass
79- else:
80- if ref != b'HEAD':
81- try:
82- params['branch'] = urlutils.escape(ref_to_branch_name(ref))
83- except ValueError:
84- params['ref'] = urlutils.quote_from_bytes(ref)
85-
86- url = git_url_to_bzr_url(location.decode('utf-8'))
87- return urlutils.join_segment_parameters(url, params)
88+ return self._get_related_merge_branch(cs)
89+
90+ def _write_git_config(self, cs):
91+ f = BytesIO()
92+ cs.write_to_file(f)
93+ self.repository._git._put_named_file('config', f.getvalue())
94
95 def set_parent(self, location):
96- # FIXME: Set "origin" url in .git/config ?
97 cs = self.repository._git.get_config()
98+ remote = self._get_origin(cs)
99 this_url = urlutils.split_segment_parameters(self.user_url)[0]
100- target_url, target_params = urlutils.split_segment_parameters(location)
101+ target_url, branch, ref = bzr_url_to_git_url(location)
102 location = urlutils.relative_url(this_url, target_url)
103- cs.set((b"remote", b"origin"), b"url", location)
104- if 'branch' in target_params:
105- cs.set((b"remote", b"origin"), b"merge",
106- branch_name_to_ref(target_params['branch']))
107- elif 'ref' in target_params:
108- cs.set((b"remote", b"origin"), b"merge",
109- target_params['ref'])
110+ cs.set((b"remote", remote), b"url", location)
111+ if branch:
112+ cs.set((b"branch", remote), b"merge", branch_name_to_ref(branch))
113+ elif ref:
114+ cs.set((b"branch", remote), b"merge", ref)
115 else:
116 # TODO(jelmer): Maybe unset rather than setting to HEAD?
117- cs.set((b"remote", b"origin"), b"merge", 'HEAD')
118- f = BytesIO()
119- cs.write_to_file(f)
120- self.repository._git._put_named_file('config', f.getvalue())
121+ cs.set((b"branch", remote), b"merge", b'HEAD')
122+ self._write_git_config(cs)
123
124 def break_lock(self):
125 raise NotImplementedError(self.break_lock)
126@@ -720,7 +750,10 @@
127 def get_push_location(self):
128 """See Branch.get_push_location."""
129 push_loc = self.get_config_stack().get('push_location')
130- return push_loc
131+ if push_loc is not None:
132+ return push_loc
133+ cs = self.repository._git.get_config_stack()
134+ return self._get_related_push_branch(cs)
135
136 def set_push_location(self, location):
137 """See Branch.set_push_location."""
138
139=== modified file 'breezy/git/tests/test_urls.py'
140--- breezy/git/tests/test_urls.py 2018-11-11 04:08:32 +0000
141+++ breezy/git/tests/test_urls.py 2019-03-04 05:19:37 +0000
142@@ -42,7 +42,26 @@
143 ('git+ssh://user@foo/bar/path'))
144
145 def test_path(self):
146- self.assertEqual(
147- git_url_to_bzr_url(
148- '/bar/path'),
149- ('/bar/path'))
150+ self.assertEqual(git_url_to_bzr_url('/bar/path'), ('/bar/path'))
151+
152+ def test_with_ref(self):
153+ self.assertEqual(
154+ git_url_to_bzr_url('foo:bar/path', ref=b'HEAD'),
155+ 'git+ssh://foo/bar/path')
156+ self.assertEqual(
157+ git_url_to_bzr_url('foo:bar/path', ref=b'refs/heads/blah'),
158+ 'git+ssh://foo/bar/path,branch=blah')
159+ self.assertEqual(
160+ git_url_to_bzr_url('foo:bar/path', ref=b'refs/tags/blah'),
161+ 'git+ssh://foo/bar/path,ref=refs%2Ftags%2Fblah')
162+
163+ def test_with_branch(self):
164+ self.assertEqual(
165+ git_url_to_bzr_url('foo:bar/path', branch=''),
166+ 'git+ssh://foo/bar/path')
167+ self.assertEqual(
168+ git_url_to_bzr_url('foo:bar/path', branch='foo/blah'),
169+ 'git+ssh://foo/bar/path,branch=foo%2Fblah')
170+ self.assertEqual(
171+ git_url_to_bzr_url('foo:bar/path', branch='blah'),
172+ 'git+ssh://foo/bar/path,branch=blah')
173
174=== modified file 'breezy/git/urls.py'
175--- breezy/git/urls.py 2018-11-11 14:23:06 +0000
176+++ breezy/git/urls.py 2019-03-04 05:19:37 +0000
177@@ -18,7 +18,10 @@
178
179 from __future__ import absolute_import
180
181-from breezy.urlutils import URL, quote
182+from .. import urlutils
183+from .refs import (
184+ ref_to_branch_name,
185+ )
186
187 from dulwich.client import parse_rsync_url
188
189@@ -26,22 +29,46 @@
190 KNOWN_GIT_SCHEMES = ['git+ssh', 'git', 'http', 'https', 'ftp']
191
192
193-def git_url_to_bzr_url(location):
194- url = URL.from_string(location)
195- if (url.scheme not in KNOWN_GIT_SCHEMES
196- and not url.scheme.startswith('chroot-')):
197+def git_url_to_bzr_url(location, branch=None, ref=None):
198+ if branch is not None and ref is not None:
199+ raise ValueError('only specify one of branch or ref')
200+ url = urlutils.URL.from_string(location)
201+ if (url.scheme not in KNOWN_GIT_SCHEMES and
202+ not url.scheme.startswith('chroot-')):
203 try:
204 (username, host, path) = parse_rsync_url(location)
205 except ValueError:
206 return location
207 else:
208- url = URL(
209+ url = urlutils.URL(
210 scheme='git+ssh',
211- quoted_user=(quote(username) if username else None),
212+ quoted_user=(urlutils.quote(username) if username else None),
213 quoted_password=None,
214- quoted_host=quote(host),
215+ quoted_host=urlutils.quote(host),
216 port=None,
217- quoted_path=quote(path, safe="/~"))
218- return str(url)
219- else:
220- return location
221+ quoted_path=urlutils.quote(path, safe="/~"))
222+ location = str(url)
223+ if ref == b'HEAD':
224+ ref = branch = None
225+ if ref:
226+ try:
227+ branch = ref_to_branch_name(ref)
228+ except ValueError:
229+ branch = None
230+ else:
231+ ref = None
232+ if ref or branch:
233+ params = {}
234+ if ref:
235+ params['ref'] = urlutils.quote_from_bytes(ref, safe='')
236+ if branch:
237+ params['branch'] = urlutils.escape(branch, safe='')
238+ location = urlutils.join_segment_parameters(location, params)
239+ return location
240+
241+
242+def bzr_url_to_git_url(location):
243+ target_url, target_params = urlutils.split_segment_parameters(location)
244+ branch = target_params.get('branch')
245+ ref = target_params.get('ref')
246+ return target_url, branch, ref
247
248=== modified file 'breezy/tests/per_branch/test_branch.py'
249--- breezy/tests/per_branch/test_branch.py 2018-11-11 04:08:32 +0000
250+++ breezy/tests/per_branch/test_branch.py 2019-03-04 05:19:37 +0000
251@@ -164,7 +164,9 @@
252
253 branch_b = wt_a.branch.controldir.sprout(
254 'b', revision_id=rev1).open_branch()
255- self.assertEqual(wt_a.branch.user_url, branch_b.get_parent())
256+ self.assertEqual(
257+ urlutils.split_segment_parameters(wt_a.branch.user_url)[0],
258+ urlutils.split_segment_parameters(branch_b.get_parent())[0])
259 return branch_b
260
261 def test_clone_branch_nickname(self):
262
263=== modified file 'breezy/tests/per_branch/test_sprout.py'
264--- breezy/tests/per_branch/test_sprout.py 2018-11-11 04:08:32 +0000
265+++ breezy/tests/per_branch/test_sprout.py 2019-03-04 05:19:37 +0000
266@@ -23,6 +23,7 @@
267 osutils,
268 revision as _mod_revision,
269 tests,
270+ urlutils,
271 )
272 from breezy.bzr import (
273 branch as _mod_bzrbranch,
274@@ -43,7 +44,9 @@
275 def test_sprout_branch_parent(self):
276 source = self.make_branch('source')
277 target = source.controldir.sprout(self.get_url('target')).open_branch()
278- self.assertEqual(source.user_url, target.get_parent())
279+ self.assertEqual(
280+ urlutils.split_segment_parameters(source.user_url)[0],
281+ urlutils.split_segment_parameters(target.get_parent())[0])
282
283 def test_sprout_uses_bzrdir_branch_format(self):
284 # branch.sprout(bzrdir) is defined as using the branch format selected
285
286=== modified file 'breezy/urlutils.py'
287--- breezy/urlutils.py 2018-11-12 01:41:38 +0000
288+++ breezy/urlutils.py 2019-03-04 05:19:37 +0000
289@@ -162,11 +162,11 @@
290 unquote = urlparse.unquote
291
292
293-def escape(relpath):
294+def escape(relpath, safe='/~'):
295 """Escape relpath to be a valid url."""
296 if not isinstance(relpath, str) and sys.version_info[0] == 2:
297 relpath = relpath.encode('utf-8')
298- return quote(relpath, safe='/~')
299+ return quote(relpath, safe=safe)
300
301
302 def file_relpath(base, path):

Subscribers

People subscribed via source and target branches