14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
from __future__ import absolute_import
17
19
# Original author: David Allouche
25
from .branch import Branch
26
from .i18n import gettext
27
from .trace import note
27
from brzlib.branch import Branch
28
from brzlib.i18n import gettext
29
from brzlib.trace import note
30
31
def _run_post_switch_hooks(control_dir, to_branch, force, revision_id):
31
from .branch import SwitchHookParams
32
from brzlib.branch import SwitchHookParams
32
33
hooks = Branch.hooks['post_switch']
48
48
:param store_uncommitted: If True, store uncommitted changes in the
52
tree = control_dir.open_workingtree()
53
except errors.NotBranchError as ex:
51
_check_pending_merges(control_dir, force)
53
source_repository = control_dir.open_branch().repository
54
except errors.NotBranchError:
55
source_repository = to_branch.repository
57
with lock.write_locked(control_dir.open_workingtree()) as tree:
58
tree.store_uncommitted()
61
_set_branch_location(control_dir, to_branch, force)
64
tree = control_dir.open_workingtree()
65
_update(tree, source_repository, quiet, revision_id, store_uncommitted)
66
_run_post_switch_hooks(control_dir, to_branch, force, revision_id)
68
def _check_pending_merges(control, force=False):
69
"""Check that there are no outstanding pending merges before switching.
71
:param control: ControlDir of the branch to check
74
tree = control.open_workingtree()
75
except errors.NotBranchError, ex:
54
76
# Lightweight checkout and branch is no longer there
55
if not force or store_uncommitted:
60
if store_uncommitted or tree.branch.get_bound_location():
63
tree.lock_tree_write()
66
parent_ids = tree.get_parent_ids()
67
if len(parent_ids) > 1:
68
raise errors.BzrCommandError(
69
gettext('Pending merges must be '
70
'committed or reverted before using switch.'))
73
tree.store_uncommitted()
75
source_repository = to_branch.repository
76
base_revision_id = None
78
source_repository = tree.branch.repository
79
# Attempt to retrieve the base_revision_id now, since some
80
# working tree formats (i.e. git) don't have their own
81
# last_revision but just use that of the currently active branch.
82
base_revision_id = tree.last_revision()
86
with to_branch.lock_read():
87
_set_branch_location(control_dir, to_branch, tree.branch if tree else None, force)
88
tree = control_dir.open_workingtree()
92
tree.lock_tree_write()
94
if base_revision_id is None:
95
# If we couldn't get to the tree's last_revision earlier, perhaps
97
base_revision_id = tree.last_revision()
98
if revision_id is None:
99
revision_id = to_branch.last_revision()
100
if base_revision_id == revision_id:
102
note(gettext("Tree is up to date at revision %d."),
105
base_tree = source_repository.revision_tree(base_revision_id)
106
target_tree = to_branch.repository.revision_tree(revision_id)
107
merge.Merge3Merger(tree, tree, base_tree, target_tree)
108
tree.set_last_revision(revision_id)
110
note(gettext('Updated to revision %d.') % to_branch.revno())
111
if store_uncommitted:
112
tree.restore_uncommitted()
113
_run_post_switch_hooks(control_dir, to_branch, force, revision_id)
118
def _set_branch_location(control, to_branch, current_branch, force=False):
81
# XXX: Should the tree be locked for get_parent_ids?
82
existing_pending_merges = tree.get_parent_ids()[1:]
83
if len(existing_pending_merges) > 0:
84
raise errors.BzrCommandError(gettext('Pending merges must be '
85
'committed or reverted before using switch.'))
88
def _set_branch_location(control, to_branch, force=False):
119
89
"""Set location value of a branch reference.
121
91
:param control: ControlDir of the checkout to change
141
111
'Cannot switch as local commits found in the checkout. '
142
112
'Commit these to the bound branch or use --force to '
143
113
'throw them away.'))
144
except errors.BoundBranchConnectionFailure as e:
114
except errors.BoundBranchConnectionFailure, e:
145
115
raise errors.BzrCommandError(gettext(
146
'Unable to connect to current master branch %(target)s: '
147
'%(error)s To switch anyway, use --force.') %
116
'Unable to connect to current master branch %(target)s: '
117
'%(error)s To switch anyway, use --force.') %
150
121
b.set_bound_location(None)
151
122
b.pull(to_branch, overwrite=True,
152
123
possible_transports=possible_transports)
153
124
b.set_bound_location(to_branch.base)
154
125
b.set_parent(b.get_master_branch().get_parent())
156
129
# If this is a standalone tree and the new branch
157
130
# is derived from this one, create a lightweight checkout.
159
133
graph = b.repository.get_graph(to_branch.repository)
160
if (b.controldir._format.colocated_branches and
161
(force or graph.is_ancestor(
162
b.last_revision(), to_branch.last_revision()))):
163
b.controldir.destroy_branch()
164
b.controldir.set_branch_reference(to_branch, name="")
134
if (b.bzrdir._format.colocated_branches and
135
(force or graph.is_ancestor(b.last_revision(),
136
to_branch.last_revision()))):
137
b.bzrdir.destroy_branch()
138
b.bzrdir.set_branch_reference(to_branch, name="")
166
raise errors.BzrCommandError(
167
gettext('Cannot switch a branch, only a checkout.'))
140
raise errors.BzrCommandError(gettext('Cannot switch a branch, '
170
146
def _any_local_commits(this_branch, possible_transports):
172
148
last_rev = revision.ensure_null(this_branch.last_revision())
173
149
if last_rev != revision.NULL_REVISION:
174
150
other_branch = this_branch.get_master_branch(possible_transports)
175
with this_branch.lock_read(), other_branch.lock_read():
151
this_branch.lock_read()
152
other_branch.lock_read()
176
154
other_last_rev = other_branch.last_revision()
177
155
graph = this_branch.repository.get_graph(
178
156
other_branch.repository)
179
157
if not graph.is_ancestor(last_rev, other_last_rev):
160
other_branch.unlock()
165
def _update(tree, source_repository, quiet=False, revision_id=None,
166
restore_uncommitted=False):
167
"""Update a working tree to the latest revision of its branch.
169
:param tree: the working tree
170
:param source_repository: repository holding the revisions
171
:param restore_uncommitted: restore any uncommitted changes in the branch.
173
if restore_uncommitted:
176
tree.lock_tree_write()
178
to_branch = tree.branch
179
if revision_id is None:
180
revision_id = to_branch.last_revision()
181
if tree.last_revision() == revision_id:
183
note(gettext("Tree is up to date at revision %d."), to_branch.revno())
185
base_tree = source_repository.revision_tree(tree.last_revision())
186
merge.Merge3Merger(tree, tree, base_tree,
187
to_branch.repository.revision_tree(revision_id))
188
tree.set_last_revision(to_branch.last_revision())
190
note(gettext('Updated to revision %d.') % to_branch.revno())
191
if restore_uncommitted:
192
tree.restore_uncommitted()