Merge lp:~jelmer/brz/switch-git-bug into lp:brz

Proposed by Jelmer Vernooij on 2019-04-13
Status: Superseded
Proposed branch: lp:~jelmer/brz/switch-git-bug
Merge into: lp:brz
Diff against target: 260 lines (+104/-32)
8 files modified
breezy/bzr/bzrdir.py (+3/-2)
breezy/controldir.py (+4/-4)
breezy/git/dir.py (+13/-0)
breezy/git/tests/test_blackbox.py (+25/-0)
breezy/git/workingtree.py (+19/-12)
breezy/switch.py (+1/-4)
breezy/tests/per_controldir_colo/test_supported.py (+38/-1)
setup.py (+1/-9)
To merge this branch: bzr merge lp:~jelmer/brz/switch-git-bug
Reviewer Review Type Date Requested Status
Breezy developers 2019-04-13 Pending
Review via email: mp+365989@code.launchpad.net

This proposal has been superseded by a proposal from 2019-04-13.

Description of the change

Fix switching between branches while preserving uncommitted changes in git.

To post a comment you must log in.
lp:~jelmer/brz/switch-git-bug updated on 2019-06-16
7308. By Jelmer Vernooij on 2019-05-28

Update release notes.

7309. By Jelmer Vernooij on 2019-05-28

Merge lp:brz/3.0.

7310. By Jelmer Vernooij on 2019-06-14

Merge lp:brz/3.0.

7311. By Jelmer Vernooij on 2019-06-16

Make some tests happy.

7312. By Jelmer Vernooij on 2019-06-16

Fine, we'll not reuse the transport - it runs into concurrency issues.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'breezy/bzr/bzrdir.py'
2--- breezy/bzr/bzrdir.py 2018-11-18 19:48:57 +0000
3+++ breezy/bzr/bzrdir.py 2019-04-13 21:38:37 +0000
4@@ -448,8 +448,9 @@
5
6 # Create/update the result working tree
7 if (create_tree_if_local and not result.has_workingtree()
8- and isinstance(target_transport, local.LocalTransport)
9- and (result_repo is None or result_repo.make_working_trees())):
10+ and isinstance(target_transport, local.LocalTransport)
11+ and (result_repo is None or result_repo.make_working_trees())
12+ and result.open_branch(name="").name == result_branch.name):
13 wt = result.create_workingtree(
14 accelerator_tree=accelerator_tree, hardlink=hardlink,
15 from_branch=result_branch)
16
17=== modified file 'breezy/controldir.py'
18--- breezy/controldir.py 2018-11-12 01:41:38 +0000
19+++ breezy/controldir.py 2019-04-13 21:38:37 +0000
20@@ -443,12 +443,12 @@
21 try:
22 tree_to = self.open_workingtree()
23 except errors.NotLocalUrl:
24- push_result.branch_push_result = source.push(br_to,
25- overwrite, stop_revision=revision_id, lossy=lossy)
26+ push_result.branch_push_result = source.push(
27+ br_to, overwrite, stop_revision=revision_id, lossy=lossy)
28 push_result.workingtree_updated = False
29 except errors.NoWorkingTree:
30- push_result.branch_push_result = source.push(br_to,
31- overwrite, stop_revision=revision_id, lossy=lossy)
32+ push_result.branch_push_result = source.push(
33+ br_to, overwrite, stop_revision=revision_id, lossy=lossy)
34 push_result.workingtree_updated = None # Not applicable
35 else:
36 with tree_to.lock_write():
37
38=== modified file 'breezy/git/dir.py'
39--- breezy/git/dir.py 2018-11-16 11:37:47 +0000
40+++ breezy/git/dir.py 2019-04-13 21:38:37 +0000
41@@ -182,6 +182,7 @@
42 result_branch = source_branch.sprout(
43 result, revision_id=revision_id, repository=result_repo)
44 if (create_tree_if_local and
45+ result.open_branch(name="").name == result_branch.name and
46 isinstance(target_transport, LocalTransport) and
47 (result_repo is None or result_repo.make_working_trees())):
48 result.create_workingtree(
49@@ -302,6 +303,18 @@
50 lossy=lossy)
51 push_result.new_revid = push_result.branch_push_result.new_revid
52 push_result.old_revid = push_result.branch_push_result.old_revid
53+ try:
54+ wt = self.open_workingtree()
55+ except brz_errors.NoWorkingTree:
56+ push_result.workingtree_updated = None
57+ else:
58+ if self.open_branch(name="").name == target.name:
59+ wt._update_git_tree(
60+ old_revision=push_result.old_revid,
61+ new_revision=push_result.new_revid)
62+ push_result.workingtree_updated = True
63+ else:
64+ push_result.workingtree_updated = False
65 push_result.target_branch = target
66 if source.get_push_location() is None or remember:
67 source.set_push_location(push_result.target_branch.base)
68
69=== modified file 'breezy/git/tests/test_blackbox.py'
70--- breezy/git/tests/test_blackbox.py 2019-02-17 04:08:56 +0000
71+++ breezy/git/tests/test_blackbox.py 2019-04-13 21:38:37 +0000
72@@ -35,6 +35,7 @@
73 from .. import (
74 tests,
75 )
76+from ...tests.script import TestCaseWithTransportAndScript
77 from ...tests.features import PluginLoadedFeature
78
79
80@@ -393,6 +394,30 @@
81 self.assertEqual([], list(tree.iter_changes(basis_tree)))
82
83
84+class SwitchScriptTests(TestCaseWithTransportAndScript):
85+
86+ def test_switch_preserves(self):
87+ # See https://bugs.launchpad.net/brz/+bug/1820606
88+ self.run_script("""
89+$ brz init --git r
90+Created a standalone tree (format: git)
91+$ cd r
92+$ echo original > file.txt
93+$ brz add
94+adding file.txt
95+$ brz ci -q -m "Initial"
96+$ echo "entered on master branch" > file.txt
97+$ brz stat
98+modified:
99+ file.txt
100+$ brz switch -b other
101+2>Tree is up to date at revision 1.
102+2>Switched to branch other
103+$ cat file.txt
104+entered on master branch
105+""")
106+
107+
108 class GrepTests(ExternalBase):
109
110 def test_simple_grep(self):
111
112=== modified file 'breezy/git/workingtree.py'
113--- breezy/git/workingtree.py 2019-02-05 04:00:02 +0000
114+++ breezy/git/workingtree.py 2019-04-13 21:38:37 +0000
115@@ -1202,26 +1202,33 @@
116 (index, subpath) = self._lookup_index(entry.path)
117 index[subpath] = index_entry_from_stat(st, entry.sha, 0)
118
119+ def _update_git_tree(self, old_revision, new_revision, change_reporter=None,
120+ show_base=False):
121+ basis_tree = self.revision_tree(old_revision)
122+ if new_revision != old_revision:
123+ with basis_tree.lock_read():
124+ new_basis_tree = self.branch.basis_tree()
125+ merge.merge_inner(
126+ self.branch,
127+ new_basis_tree,
128+ basis_tree,
129+ this_tree=self,
130+ change_reporter=change_reporter,
131+ show_base=show_base)
132+
133 def pull(self, source, overwrite=False, stop_revision=None,
134 change_reporter=None, possible_transports=None, local=False,
135 show_base=False):
136 with self.lock_write(), source.lock_read():
137 old_revision = self.branch.last_revision()
138- basis_tree = self.basis_tree()
139 count = self.branch.pull(source, overwrite, stop_revision,
140 possible_transports=possible_transports,
141 local=local)
142- new_revision = self.branch.last_revision()
143- if new_revision != old_revision:
144- with basis_tree.lock_read():
145- new_basis_tree = self.branch.basis_tree()
146- merge.merge_inner(
147- self.branch,
148- new_basis_tree,
149- basis_tree,
150- this_tree=self,
151- change_reporter=change_reporter,
152- show_base=show_base)
153+ self._update_git_tree(
154+ old_revision=old_revision,
155+ new_revision=self.branch.last_revision(),
156+ change_reporter=change_reporter,
157+ show_base=show_base)
158 return count
159
160 def add_reference(self, sub_tree):
161
162=== modified file 'breezy/switch.py'
163--- breezy/switch.py 2018-11-16 23:28:26 +0000
164+++ breezy/switch.py 2019-04-13 21:38:37 +0000
165@@ -148,15 +148,12 @@
166 'Unable to connect to current master branch %(target)s: '
167 '%(error)s To switch anyway, use --force.') %
168 e.__dict__)
169- b.lock_write()
170- try:
171+ with b.lock_write():
172 b.set_bound_location(None)
173 b.pull(to_branch, overwrite=True,
174 possible_transports=possible_transports)
175 b.set_bound_location(to_branch.base)
176 b.set_parent(b.get_master_branch().get_parent())
177- finally:
178- b.unlock()
179 else:
180 # If this is a standalone tree and the new branch
181 # is derived from this one, create a lightweight checkout.
182
183=== modified file 'breezy/tests/per_controldir_colo/test_supported.py'
184--- breezy/tests/per_controldir_colo/test_supported.py 2018-11-11 04:08:32 +0000
185+++ breezy/tests/per_controldir_colo/test_supported.py 2019-04-13 21:38:37 +0000
186@@ -114,10 +114,47 @@
187 'Control dir does not support creating new branches.')
188 to_dir = from_tree.controldir.sprout(
189 urlutils.join_segment_parameters(
190- other_branch.controldir.user_url, {"branch": "target"}))
191+ other_branch.user_url, {"branch": "target"}))
192 to_branch = to_dir.open_branch(name="target")
193 self.assertEqual(revid, to_branch.last_revision())
194
195+ def test_sprout_into_colocated_leaves_workingtree(self):
196+ # a bzrdir can construct a branch and repository for itself.
197+ if not self.bzrdir_format.is_supported():
198+ # unsupported formats are not loopback testable
199+ # because the default open will not open them and
200+ # they may not be initializable.
201+ raise tests.TestNotApplicable('Control dir format not supported')
202+ if not self.bzrdir_format.supports_workingtrees:
203+ raise tests.TestNotApplicable(
204+ 'Control dir format does not support working trees')
205+ from_tree = self.make_branch_and_tree('from')
206+ self.build_tree_contents([('from/foo', 'contents')])
207+ from_tree.add(['foo'])
208+ revid1 = from_tree.commit("rev1")
209+ self.build_tree_contents([('from/foo', 'new contents')])
210+ revid2 = from_tree.commit("rev2")
211+ try:
212+ other_branch = self.make_branch_and_tree("to")
213+ except errors.UninitializableFormat:
214+ raise tests.TestNotApplicable(
215+ 'Control dir does not support creating new branches.')
216+
217+ result = other_branch.controldir.push_branch(
218+ from_tree.branch, revision_id=revid1)
219+ self.assertTrue(result.workingtree_updated)
220+ self.assertFileEqual('contents', 'to/foo')
221+
222+ from_tree.controldir.sprout(
223+ urlutils.join_segment_parameters(
224+ other_branch.user_url, {"branch": "target"}),
225+ revision_id=revid2)
226+ active_branch = other_branch.controldir.open_branch(name="")
227+ self.assertEqual(revid1, active_branch.last_revision())
228+ to_branch = other_branch.controldir.open_branch(name="target")
229+ self.assertEqual(revid2, to_branch.last_revision())
230+ self.assertFileEqual('contents', 'to/foo')
231+
232 def test_unicode(self):
233 self.requireFeature(UnicodeFilenameFeature)
234 if not self.bzrdir_format.is_supported():
235
236=== modified file 'setup.py'
237--- setup.py 2019-03-04 10:39:09 +0000
238+++ setup.py 2019-04-13 21:38:37 +0000
239@@ -149,8 +149,7 @@
240 script_path = self._quoted_path(os.path.join(scripts_dir,
241 "brz"))
242 python_exe = self._quoted_path(sys.executable)
243- args = self._win_batch_args()
244- batch_str = "@%s %s %s" % (python_exe, script_path, args)
245+ batch_str = "@%s %s %%*" % (python_exe, script_path)
246 batch_path = os.path.join(self.install_dir, "brz.bat")
247 with open(batch_path, "w") as f:
248 f.write(batch_str)
249@@ -164,13 +163,6 @@
250 return '"' + path + '"'
251 else:
252 return path
253-
254- def _win_batch_args(self):
255- from breezy.win32utils import winver
256- if winver == 'Windows NT':
257- return '%*'
258- else:
259- return '%1 %2 %3 %4 %5 %6 %7 %8 %9'
260 #/class my_install_scripts
261
262

Subscribers

People subscribed via source and target branches