/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to brzlib/switch.py

  • Committer: Jelmer Vernooij
  • Date: 2017-05-21 12:41:27 UTC
  • mto: This revision was merged to the branch mainline in revision 6623.
  • Revision ID: jelmer@jelmer.uk-20170521124127-iv8etg0vwymyai6y
s/bzr/brz/ in apport config.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
16
16
 
 
17
from __future__ import absolute_import
 
18
 
17
19
# Original author: David Allouche
18
20
 
19
 
from . import (
 
21
from brzlib import (
20
22
    errors,
21
23
    lock,
22
24
    merge,
23
25
    revision
24
26
    )
25
 
from .branch import Branch
26
 
from .i18n import gettext
27
 
from .trace import note
28
 
 
 
27
from brzlib.branch import Branch
 
28
from brzlib.i18n import gettext
 
29
from brzlib.trace import note
29
30
 
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']
33
34
    if not hooks:
34
35
        return
36
37
    for hook in hooks:
37
38
        hook(params)
38
39
 
39
 
 
40
40
def switch(control_dir, to_branch, force=False, quiet=False, revision_id=None,
41
 
           store_uncommitted=False, possible_transports=None):
 
41
           store_uncommitted=False):
42
42
    """Switch the branch associated with a checkout.
43
43
 
44
44
    :param control_dir: ControlDir of the checkout to change
48
48
    :param store_uncommitted: If True, store uncommitted changes in the
49
49
        branch.
50
50
    """
51
 
    try:
52
 
        tree = control_dir.open_workingtree()
53
 
    except errors.NotBranchError as ex:
 
51
    _check_pending_merges(control_dir, force)
 
52
    try:
 
53
        source_repository = control_dir.open_branch().repository
 
54
    except errors.NotBranchError:
 
55
        source_repository = to_branch.repository
 
56
    if store_uncommitted:
 
57
        with lock.write_locked(control_dir.open_workingtree()) as tree:
 
58
            tree.store_uncommitted()
 
59
    to_branch.lock_read()
 
60
    try:
 
61
        _set_branch_location(control_dir, to_branch, force)
 
62
    finally:
 
63
        to_branch.unlock()
 
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)
 
67
 
 
68
def _check_pending_merges(control, force=False):
 
69
    """Check that there are no outstanding pending merges before switching.
 
70
 
 
71
    :param control: ControlDir of the branch to check
 
72
    """
 
73
    try:
 
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:
 
77
        if force:
 
78
            return
 
79
        else:
56
80
            raise ex
57
 
        else:
58
 
            tree = None
59
 
    else:
60
 
        if store_uncommitted or tree.branch.get_bound_location():
61
 
            tree.lock_write()
62
 
        else:
63
 
            tree.lock_tree_write()
64
 
    try:
65
 
        if tree is not None:
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.'))
71
 
 
72
 
        if store_uncommitted:
73
 
            tree.store_uncommitted()
74
 
        if tree is None:
75
 
            source_repository = to_branch.repository
76
 
            base_revision_id = None
77
 
        else:
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()
83
 
    finally:
84
 
        if tree is not None:
85
 
            tree.unlock()
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()
89
 
    if store_uncommitted:
90
 
        tree.lock_write()
91
 
    else:
92
 
        tree.lock_tree_write()
93
 
    try:
94
 
        if base_revision_id is None:
95
 
            # If we couldn't get to the tree's last_revision earlier, perhaps
96
 
            # we can now.
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:
101
 
            if not quiet:
102
 
                note(gettext("Tree is up to date at revision %d."),
103
 
                     to_branch.revno())
104
 
        else:
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)
109
 
            if not quiet:
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)
114
 
    finally:
115
 
        tree.unlock()
116
 
 
117
 
 
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.'))
 
86
 
 
87
 
 
88
def _set_branch_location(control, to_branch, force=False):
119
89
    """Set location value of a branch reference.
120
90
 
121
91
    :param control: ControlDir of the checkout to change
127
97
        # Lightweight checkout: update the branch reference
128
98
        branch_format.set_reference(control, None, to_branch)
129
99
    else:
130
 
        b = current_branch
 
100
        b = control.open_branch()
131
101
        bound_branch = b.get_bound_location()
132
102
        if bound_branch is not None:
133
103
            # Heavyweight checkout: check all local commits
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.') %
148
 
                    e.__dict__)
149
 
            with b.lock_write():
 
116
                        'Unable to connect to current master branch %(target)s: '
 
117
                        '%(error)s To switch anyway, use --force.') %
 
118
                        e.__dict__)
 
119
            b.lock_write()
 
120
            try:
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())
 
126
            finally:
 
127
                b.unlock()
155
128
        else:
156
129
            # If this is a standalone tree and the new branch
157
130
            # is derived from this one, create a lightweight checkout.
158
 
            with b.lock_read():
 
131
            b.lock_read()
 
132
            try:
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="")
165
139
                else:
166
 
                    raise errors.BzrCommandError(
167
 
                        gettext('Cannot switch a branch, only a checkout.'))
 
140
                    raise errors.BzrCommandError(gettext('Cannot switch a branch, '
 
141
                        'only a checkout.'))
 
142
            finally:
 
143
                b.unlock()
168
144
 
169
145
 
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()
 
153
        try:
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):
180
158
                return True
 
159
        finally:
 
160
            other_branch.unlock()
 
161
            this_branch.unlock()
181
162
    return False
 
163
 
 
164
 
 
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.
 
168
 
 
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.
 
172
    """
 
173
    if restore_uncommitted:
 
174
        tree.lock_write()
 
175
    else:
 
176
        tree.lock_tree_write()
 
177
    try:
 
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:
 
182
            if not quiet:
 
183
                note(gettext("Tree is up to date at revision %d."), to_branch.revno())
 
184
        else:
 
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())
 
189
            if not quiet:
 
190
                note(gettext('Updated to revision %d.') % to_branch.revno())
 
191
        if restore_uncommitted:
 
192
            tree.restore_uncommitted()
 
193
    finally:
 
194
        tree.unlock()