Merge lp:~jelmer/brz/git-switch 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-switch
Merge into: lp:brz
Diff against target: 218 lines (+98/-67)
3 files modified
breezy/git/tests/test_blackbox.py (+32/-0)
breezy/switch.py (+64/-65)
breezy/tests/blackbox/test_switch.py (+2/-2)
To merge this branch: bzr merge lp:~jelmer/brz/git-switch
Reviewer Review Type Date Requested Status
Martin Packman Approve
Review via email: mp+358603@code.launchpad.net

Commit message

Fix 'brz switch' in git repositories.

Description of the change

Fix 'brz switch' in git repositories.

To post a comment you must log in.
Revision history for this message
Martin Packman (gz) wrote :

Okay. This is pretty hairy but was previously as well.

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/tests/test_blackbox.py'
2--- breezy/git/tests/test_blackbox.py 2018-11-16 19:47:19 +0000
3+++ breezy/git/tests/test_blackbox.py 2018-11-16 23:29:29 +0000
4@@ -30,6 +30,7 @@
5 )
6
7 from ...tests.blackbox import ExternalBase
8+from ...workingtree import WorkingTree
9
10 from .. import (
11 tests,
12@@ -338,6 +339,37 @@
13 self.assertEqual(output, 'VERSION_INFO \n')
14
15
16+class SwitchTests(ExternalBase):
17+
18+ def test_switch_branch(self):
19+ # Create a git repository with a revision.
20+ repo = GitRepo.init(self.test_dir)
21+ builder = tests.GitBranchBuilder()
22+ builder.set_branch(b'refs/heads/oldbranch')
23+ builder.set_file('a', b'text for a\n', False)
24+ builder.commit(b'Joe Foo <joe@foo.com>', u'<The commit message>')
25+ builder.set_branch(b'refs/heads/newbranch')
26+ builder.reset()
27+ builder.set_file('a', b'text for new a\n', False)
28+ builder.commit(b'Joe Foo <joe@foo.com>', u'<The commit message>')
29+ builder.finish()
30+
31+ repo.refs.set_symbolic_ref(b'HEAD', b'refs/heads/newbranch')
32+
33+ repo.reset_index()
34+
35+ output, error = self.run_bzr('switch oldbranch')
36+ self.assertEqual(output, '')
37+ self.assertTrue(error.startswith('Updated to revision 1.\n'), error)
38+
39+ self.assertFileEqual("text for a\n", 'a')
40+ tree = WorkingTree.open('.')
41+ with tree.lock_read():
42+ basis_tree = tree.basis_tree()
43+ with basis_tree.lock_read():
44+ self.assertEqual([], list(tree.iter_changes(basis_tree)))
45+
46+
47 class GrepTests(ExternalBase):
48
49 def test_simple_grep(self):
50
51=== modified file 'breezy/switch.py'
52--- breezy/switch.py 2018-11-12 01:41:38 +0000
53+++ breezy/switch.py 2018-11-16 23:29:29 +0000
54@@ -50,42 +50,74 @@
55 :param store_uncommitted: If True, store uncommitted changes in the
56 branch.
57 """
58- _check_pending_merges(control_dir, force)
59- try:
60- source_repository = control_dir.open_branch().repository
61- except errors.NotBranchError:
62- source_repository = to_branch.repository
63- if store_uncommitted:
64- with lock.write_locked(control_dir.open_workingtree()) as tree:
65+ try:
66+ tree = control_dir.open_workingtree()
67+ except errors.NotBranchError as ex:
68+ # Lightweight checkout and branch is no longer there
69+ if not force or store_uncommitted:
70+ raise ex
71+ else:
72+ tree = None
73+ else:
74+ if store_uncommitted or tree.branch.get_bound_location():
75+ tree.lock_write()
76+ else:
77+ tree.lock_tree_write()
78+ try:
79+ if tree is not None:
80+ parent_ids = tree.get_parent_ids()
81+ if len(parent_ids) > 1:
82+ raise errors.BzrCommandError(
83+ gettext('Pending merges must be '
84+ 'committed or reverted before using switch.'))
85+
86+ if store_uncommitted:
87 tree.store_uncommitted()
88+ if tree is None:
89+ source_repository = to_branch.repository
90+ base_revision_id = None
91+ else:
92+ source_repository = tree.branch.repository
93+ # Attempt to retrieve the base_revision_id now, since some
94+ # working tree formats (i.e. git) don't have their own
95+ # last_revision but just use that of the currently active branch.
96+ base_revision_id = tree.last_revision()
97+ finally:
98+ if tree is not None:
99+ tree.unlock()
100 with to_branch.lock_read():
101- _set_branch_location(control_dir, to_branch, force)
102+ _set_branch_location(control_dir, to_branch, tree.branch if tree else None, force)
103 tree = control_dir.open_workingtree()
104- _update(tree, source_repository, quiet, revision_id, store_uncommitted)
105- _run_post_switch_hooks(control_dir, to_branch, force, revision_id)
106-
107-
108-def _check_pending_merges(control, force=False):
109- """Check that there are no outstanding pending merges before switching.
110-
111- :param control: ControlDir of the branch to check
112- """
113+ if store_uncommitted:
114+ tree.lock_write()
115+ else:
116+ tree.lock_tree_write()
117 try:
118- tree = control.open_workingtree()
119- except errors.NotBranchError as ex:
120- # Lightweight checkout and branch is no longer there
121- if force:
122- return
123+ if base_revision_id is None:
124+ # If we couldn't get to the tree's last_revision earlier, perhaps
125+ # we can now.
126+ base_revision_id = tree.last_revision()
127+ if revision_id is None:
128+ revision_id = to_branch.last_revision()
129+ if base_revision_id == revision_id:
130+ if not quiet:
131+ note(gettext("Tree is up to date at revision %d."),
132+ to_branch.revno())
133 else:
134- raise ex
135- # XXX: Should the tree be locked for get_parent_ids?
136- existing_pending_merges = tree.get_parent_ids()[1:]
137- if len(existing_pending_merges) > 0:
138- raise errors.BzrCommandError(gettext('Pending merges must be '
139- 'committed or reverted before using switch.'))
140-
141-
142-def _set_branch_location(control, to_branch, force=False):
143+ base_tree = source_repository.revision_tree(base_revision_id)
144+ target_tree = to_branch.repository.revision_tree(revision_id)
145+ merge.Merge3Merger(tree, tree, base_tree, target_tree)
146+ tree.set_last_revision(revision_id)
147+ if not quiet:
148+ note(gettext('Updated to revision %d.') % to_branch.revno())
149+ if store_uncommitted:
150+ tree.restore_uncommitted()
151+ _run_post_switch_hooks(control_dir, to_branch, force, revision_id)
152+ finally:
153+ tree.unlock()
154+
155+
156+def _set_branch_location(control, to_branch, current_branch, force=False):
157 """Set location value of a branch reference.
158
159 :param control: ControlDir of the checkout to change
160@@ -97,7 +129,7 @@
161 # Lightweight checkout: update the branch reference
162 branch_format.set_reference(control, None, to_branch)
163 else:
164- b = control.open_branch()
165+ b = current_branch
166 bound_branch = b.get_bound_location()
167 if bound_branch is not None:
168 # Heavyweight checkout: check all local commits
169@@ -152,36 +184,3 @@
170 if not graph.is_ancestor(last_rev, other_last_rev):
171 return True
172 return False
173-
174-
175-def _update(tree, source_repository, quiet=False, revision_id=None,
176- restore_uncommitted=False):
177- """Update a working tree to the latest revision of its branch.
178-
179- :param tree: the working tree
180- :param source_repository: repository holding the revisions
181- :param restore_uncommitted: restore any uncommitted changes in the branch.
182- """
183- if restore_uncommitted:
184- tree.lock_write()
185- else:
186- tree.lock_tree_write()
187- try:
188- to_branch = tree.branch
189- if revision_id is None:
190- revision_id = to_branch.last_revision()
191- if tree.last_revision() == revision_id:
192- if not quiet:
193- note(gettext("Tree is up to date at revision %d."),
194- to_branch.revno())
195- else:
196- base_tree = source_repository.revision_tree(tree.last_revision())
197- merge.Merge3Merger(tree, tree, base_tree,
198- to_branch.repository.revision_tree(revision_id))
199- tree.set_last_revision(to_branch.last_revision())
200- if not quiet:
201- note(gettext('Updated to revision %d.') % to_branch.revno())
202- if restore_uncommitted:
203- tree.restore_uncommitted()
204- finally:
205- tree.unlock()
206
207=== modified file 'breezy/tests/blackbox/test_switch.py'
208--- breezy/tests/blackbox/test_switch.py 2018-11-16 11:37:47 +0000
209+++ breezy/tests/blackbox/test_switch.py 2018-11-16 23:29:29 +0000
210@@ -492,8 +492,8 @@
211 # being too low. If rpc_count increases, more network roundtrips have
212 # become necessary for this use case. Please do not adjust this number
213 # upwards without agreement from bzr's network support maintainers.
214- self.assertLength(24, self.hpss_calls)
215- self.assertLength(4, self.hpss_connections)
216+ self.assertLength(21, self.hpss_calls)
217+ self.assertLength(3, self.hpss_connections)
218 self.assertThat(self.hpss_calls, ContainsNoVfsCalls)
219
220

Subscribers

People subscribed via source and target branches