Merge lp:~jelmer/brz/git-follow-symref into lp:brz

Proposed by Jelmer Vernooij
Status: Merged
Approved by: Jelmer Vernooij
Approved revision: no longer in the source branch.
Merge reported by: The Breezy Bot
Merged at revision: not available
Proposed branch: lp:~jelmer/brz/git-follow-symref
Merge into: lp:brz
Diff against target: 177 lines (+78/-22)
3 files modified
breezy/git/remote.py (+39/-22)
breezy/git/tests/test_remote.py (+36/-0)
doc/en/release-notes/brz-3.1.txt (+3/-0)
To merge this branch: bzr merge lp:~jelmer/brz/git-follow-symref
Reviewer Review Type Date Requested Status
Jelmer Vernooij Approve
Review via email: mp+378769@code.launchpad.net

Commit message

Follow symrefs when pushing to git repositories.

Description of the change

Follow symrefs when pushing to git repositories.

To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) :
review: Approve
Revision history for this message
The Breezy Bot (the-breezy-bot) wrote :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'breezy/git/remote.py'
2--- breezy/git/remote.py 2020-01-12 15:16:27 +0000
3+++ breezy/git/remote.py 2020-02-08 18:52:28 +0000
4@@ -48,6 +48,7 @@
5 PermissionDenied,
6 UninitializableFormat,
7 )
8+from ..revision import NULL_REVISION
9 from ..revisiontree import RevisionTree
10 from ..sixish import (
11 text_type,
12@@ -452,10 +453,10 @@
13 else:
14 pb = None
15
16- def get_changed_refs_wrapper(refs):
17- # TODO(jelmer): This drops symref information
18- self._refs = remote_refs_dict_to_container(refs)
19- return get_changed_refs(refs)
20+ def get_changed_refs_wrapper(remote_refs):
21+ if self._refs is not None:
22+ update_refs_container(self._refs, remote_refs)
23+ return get_changed_refs(remote_refs)
24 try:
25 return self._client.send_pack(
26 self._client_path, get_changed_refs_wrapper,
27@@ -471,11 +472,10 @@
28 refname = self._get_selected_ref(name, ref)
29 if refname != b'HEAD' and refname in self.get_refs_container():
30 raise AlreadyBranchError(self.user_url)
31- if refname in self.get_refs_container():
32- ref_chain, unused_sha = self.get_refs_container().follow(
33- self._get_selected_ref(None))
34- if ref_chain[0] == b'HEAD':
35- refname = ref_chain[1]
36+ ref_chain, unused_sha = self.get_refs_container().follow(
37+ self._get_selected_ref(name))
38+ if ref_chain and ref_chain[0] == b'HEAD':
39+ refname = ref_chain[1]
40 repo = self.open_repository()
41 return RemoteGitBranch(self, repo, refname)
42
43@@ -570,12 +570,18 @@
44 push_result.branch_push_result = None
45 repo = self.find_repository()
46 refname = self._get_selected_ref(name)
47+ ref_chain, old_sha = self.get_refs_container().follow(refname)
48+ if ref_chain:
49+ actual_refname = ref_chain[-1]
50+ else:
51+ actual_refname = refname
52 if isinstance(source, GitBranch) and lossy:
53 raise errors.LossyPushToSameVCS(source.controldir, self)
54 source_store = get_object_store(source.repository)
55 fetch_tags = source.get_config_stack().get('branch.fetch_tags')
56- def get_changed_refs(refs):
57- self._refs = remote_refs_dict_to_container(refs)
58+ def get_changed_refs(remote_refs):
59+ if self._refs is not None:
60+ update_refs_container(self._refs, remote_refs)
61 ret = {}
62 # TODO(jelmer): Unpeel if necessary
63 push_result.new_original_revid = revision_id
64@@ -588,11 +594,10 @@
65 raise errors.NoRoundtrippingSupport(
66 source, self.open_branch(name=name, nascent_ok=True))
67 if not overwrite:
68- if remote_divergence(ret.get(refname), new_sha,
69- source_store):
70+ if remote_divergence(old_sha, new_sha, source_store):
71 raise DivergedBranches(
72 source, self.open_branch(name, nascent_ok=True))
73- ret[refname] = new_sha
74+ ret[actual_refname] = new_sha
75 if fetch_tags:
76 for tagname, revid in viewitems(source.tags.get_tag_dict()):
77 if lossy:
78@@ -611,15 +616,15 @@
79 generate_pack_data = source_store.generate_pack_data
80 new_refs = self.send_pack(get_changed_refs, generate_pack_data)
81 push_result.new_revid = repo.lookup_foreign_revision_id(
82- new_refs[refname])
83- try:
84- old_remote = self._refs[refname]
85- except KeyError:
86- old_remote = ZERO_SHA
87- push_result.old_revid = repo.lookup_foreign_revision_id(old_remote)
88- self._refs = remote_refs_dict_to_container(new_refs)
89+ new_refs[actual_refname])
90+ if old_sha is not None:
91+ push_result.old_revid = repo.lookup_foreign_revision_id(old_sha)
92+ else:
93+ push_result.old_revid = NULL_REVISION
94+ if self._refs is not None:
95+ update_refs_container(self._refs, new_refs)
96 push_result.target_branch = self.open_branch(name)
97- if old_remote != ZERO_SHA:
98+ if old_sha is not None:
99 push_result.branch_push_result = GitBranchPushResult()
100 push_result.branch_push_result.source_branch = source
101 push_result.branch_push_result.target_branch = (
102@@ -1029,3 +1034,15 @@
103 ret = DictRefsContainer(base)
104 ret._peeled = peeled
105 return ret
106+
107+
108+def update_refs_container(container, refs_dict):
109+ peeled = {}
110+ base = {}
111+ for k, v in refs_dict.items():
112+ if is_peeled(k):
113+ peeled[k[:-3]] = v
114+ else:
115+ base[k] = v
116+ container._peeled = peeled
117+ container._refs.update(base)
118
119=== modified file 'breezy/git/tests/test_remote.py'
120--- breezy/git/tests/test_remote.py 2019-11-19 18:10:28 +0000
121+++ breezy/git/tests/test_remote.py 2020-02-08 18:52:28 +0000
122@@ -357,6 +357,42 @@
123 },
124 self.remote_real.get_refs())
125
126+ def test_push_branch_symref(self):
127+ cfg = self.remote_real.get_config()
128+ cfg.set((b'core', ), b'bare', True)
129+ cfg.write_to_path()
130+ self.remote_real.refs.set_symbolic_ref(b'HEAD', b'refs/heads/master')
131+ c1 = self.remote_real.do_commit(
132+ message=b'message',
133+ committer=b'committer <committer@example.com>',
134+ author=b'author <author@example.com>',
135+ ref=b'refs/heads/master')
136+ remote = ControlDir.open(self.remote_url)
137+ wt = self.make_branch_and_tree('local', format=self._from_format)
138+ self.build_tree(['local/blah'])
139+ wt.add(['blah'])
140+ revid = wt.commit('blah')
141+
142+ if self._from_format == 'git':
143+ result = remote.push_branch(wt.branch, overwrite=True)
144+ else:
145+ result = remote.push_branch(wt.branch, lossy=True, overwrite=True)
146+
147+ self.assertEqual(None, result.old_revno)
148+ if self._from_format == 'git':
149+ self.assertEqual(1, result.new_revno)
150+ else:
151+ self.assertIs(None, result.new_revno)
152+
153+ result.report(BytesIO())
154+
155+ self.assertEqual(
156+ {
157+ b'HEAD': self.remote_real.refs[b'refs/heads/master'],
158+ b'refs/heads/master': self.remote_real.refs[b'refs/heads/master'],
159+ },
160+ self.remote_real.get_refs())
161+
162 def test_push_branch_new_with_tags(self):
163 remote = ControlDir.open(self.remote_url)
164 builder = self.make_branch_builder('local', format=self._from_format)
165
166=== modified file 'doc/en/release-notes/brz-3.1.txt'
167--- doc/en/release-notes/brz-3.1.txt 2020-01-31 17:43:44 +0000
168+++ doc/en/release-notes/brz-3.1.txt 2020-02-08 18:52:28 +0000
169@@ -70,6 +70,9 @@
170 attempt to access Fossil repositories.
171 (Jelmer Vernooij, #1848821)
172
173+ * When pushing to Git repositories, symrefs are now followed.
174+ (Jelmer Vernooij, #1800393)
175+
176 Improvements
177 ************
178

Subscribers

People subscribed via source and target branches