~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/switch.py

(jameinel) Allow 'bzr serve' to interpret SIGHUP as a graceful shutdown.
 (bug #795025) (John A Meinel)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006, 2007 Canonical Ltd.
 
1
# Copyright (C) 2007, 2009, 2010 Canonical Ltd.
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
# Original author: David Allouche
18
18
 
19
19
from bzrlib import errors, merge, revision
20
 
from bzrlib.branch import Branch, BranchFormat, BranchReferenceFormat
21
 
from bzrlib.bzrdir import BzrDir
 
20
from bzrlib.branch import Branch
 
21
from bzrlib.i18n import gettext
22
22
from bzrlib.trace import note
23
23
 
 
24
def _run_post_switch_hooks(control_dir, to_branch, force, revision_id):
 
25
    from bzrlib.branch import SwitchHookParams
 
26
    hooks = Branch.hooks['post_switch']
 
27
    if not hooks:
 
28
        return
 
29
    params = SwitchHookParams(control_dir, to_branch, force, revision_id)
 
30
    for hook in hooks:
 
31
        hook(params)
24
32
 
25
 
def switch(control_dir, to_branch, force=False):
 
33
def switch(control_dir, to_branch, force=False, quiet=False, revision_id=None):
26
34
    """Switch the branch associated with a checkout.
27
35
 
28
36
    :param control_dir: BzrDir of the checkout to change
29
37
    :param to_branch: branch that the checkout is to reference
30
38
    :param force: skip the check for local commits in a heavy checkout
 
39
    :param revision_id: revision ID to switch to.
31
40
    """
32
41
    _check_pending_merges(control_dir, force)
33
42
    try:
36
45
        source_repository = to_branch.repository
37
46
    _set_branch_location(control_dir, to_branch, force)
38
47
    tree = control_dir.open_workingtree()
39
 
    _update(tree, source_repository)
40
 
 
 
48
    _update(tree, source_repository, quiet, revision_id)
 
49
    _run_post_switch_hooks(control_dir, to_branch, force, revision_id)
41
50
 
42
51
def _check_pending_merges(control, force=False):
43
52
    """Check that there are no outstanding pending merges before switching.
55
64
    # XXX: Should the tree be locked for get_parent_ids?
56
65
    existing_pending_merges = tree.get_parent_ids()[1:]
57
66
    if len(existing_pending_merges) > 0:
58
 
        raise errors.BzrCommandError('Pending merges must be '
59
 
            'committed or reverted before using switch.')
 
67
        raise errors.BzrCommandError(gettext('Pending merges must be '
 
68
            'committed or reverted before using switch.'))
60
69
 
61
70
 
62
71
def _set_branch_location(control, to_branch, force=False):
69
78
    branch_format = control.find_branch_format()
70
79
    if branch_format.get_reference(control) is not None:
71
80
        # Lightweight checkout: update the branch reference
72
 
        branch_format.set_reference(control, to_branch)
 
81
        branch_format.set_reference(control, None, to_branch)
73
82
    else:
74
83
        b = control.open_branch()
75
84
        bound_branch = b.get_bound_location()
79
88
            # synchronise the local branch with the new remote branch
80
89
            # and bind to it
81
90
            possible_transports = []
82
 
            if not force and _any_local_commits(b, possible_transports):
83
 
                raise errors.BzrCommandError(
84
 
                    'Cannot switch as local commits found in the checkout. '
85
 
                    'Commit these to the bound branch or use --force to '
86
 
                    'throw them away.')
 
91
            try:
 
92
                if not force and _any_local_commits(b, possible_transports):
 
93
                    raise errors.BzrCommandError(gettext(
 
94
                        'Cannot switch as local commits found in the checkout. '
 
95
                        'Commit these to the bound branch or use --force to '
 
96
                        'throw them away.'))
 
97
            except errors.BoundBranchConnectionFailure, e:
 
98
                raise errors.BzrCommandError(gettext(
 
99
                        'Unable to connect to current master branch %(target)s: '
 
100
                        '%(error)s To switch anyway, use --force.') %
 
101
                        e.__dict__)
87
102
            b.set_bound_location(None)
88
103
            b.pull(to_branch, overwrite=True,
89
104
                possible_transports=possible_transports)
90
105
            b.set_bound_location(to_branch.base)
 
106
            b.set_parent(b.get_master_branch().get_parent())
91
107
        else:
92
 
            raise errors.BzrCommandError('Cannot switch a branch, '
93
 
                'only a checkout.')
 
108
            raise errors.BzrCommandError(gettext('Cannot switch a branch, '
 
109
                'only a checkout.'))
94
110
 
95
111
 
96
112
def _any_local_commits(this_branch, possible_transports):
112
128
    return False
113
129
 
114
130
 
115
 
def _update(tree, source_repository):
 
131
def _update(tree, source_repository, quiet=False, revision_id=None):
116
132
    """Update a working tree to the latest revision of its branch.
117
133
 
118
134
    :param tree: the working tree
121
137
    tree.lock_tree_write()
122
138
    try:
123
139
        to_branch = tree.branch
124
 
        if tree.last_revision() == to_branch.last_revision():
125
 
            note("Tree is up to date at revision %d.", to_branch.revno())
 
140
        if revision_id is None:
 
141
            revision_id = to_branch.last_revision()
 
142
        if tree.last_revision() == revision_id:
 
143
            if not quiet:
 
144
                note(gettext("Tree is up to date at revision %d."), to_branch.revno())
126
145
            return
127
146
        base_tree = source_repository.revision_tree(tree.last_revision())
128
 
        merge.Merge3Merger(tree, tree, base_tree, to_branch.basis_tree())
 
147
        merge.Merge3Merger(tree, tree, base_tree, to_branch.repository.revision_tree(revision_id))
129
148
        tree.set_last_revision(to_branch.last_revision())
130
 
        note('Updated to revision %d.' % to_branch.revno())
 
149
        if not quiet:
 
150
            note(gettext('Updated to revision %d.') % to_branch.revno())
131
151
    finally:
132
152
        tree.unlock()