~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/send.py

  • Committer: Vincent Ladeuil
  • Date: 2012-01-18 14:09:19 UTC
  • mto: This revision was merged to the branch mainline in revision 6468.
  • Revision ID: v.ladeuil+lp@free.fr-20120118140919-rlvdrhpc0nq1lbwi
Change set/remove to require a lock for the branch config files.

This means that tests (or any plugin for that matter) do not requires an
explicit lock on the branch anymore to change a single option. This also
means the optimisation becomes "opt-in" and as such won't be as
spectacular as it may be and/or harder to get right (nothing fails
anymore).

This reduces the diff by ~300 lines.

Code/tests that were updating more than one config option is still taking
a lock to at least avoid some IOs and demonstrate the benefits through
the decreased number of hpss calls.

The duplication between BranchStack and BranchOnlyStack will be removed
once the same sharing is in place for local config files, at which point
the Stack class itself may be able to host the changes.

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
17
18
 
18
19
import os
19
20
import time
20
21
 
21
22
from bzrlib import (
22
 
    bzrdir,
 
23
    controldir,
23
24
    errors,
24
25
    osutils,
25
26
    registry,
26
27
    trace,
27
28
    )
 
29
from bzrlib.i18n import gettext
28
30
from bzrlib.branch import (
29
31
    Branch,
30
32
    )
36
38
format_registry = registry.Registry()
37
39
 
38
40
 
39
 
def send(submit_branch, revision, public_branch, remember, format,
40
 
         no_bundle, no_patch, output, from_, mail_to, message, body,
 
41
def send(target_branch, revision, public_branch, remember,
 
42
         format, no_bundle, no_patch, output, from_, mail_to, message, body,
41
43
         to_file, strict=None):
42
 
    tree, branch = bzrdir.BzrDir.open_containing_tree_or_branch(from_)[:2]
 
44
    tree, branch = controldir.ControlDir.open_containing_tree_or_branch(
 
45
        from_)[:2]
 
46
    possible_transports = [tree.bzrdir.transport, branch.bzrdir.transport]
43
47
    # we may need to write data into branch's repository to calculate
44
48
    # the data to send.
45
49
    branch.lock_write()
46
50
    try:
47
51
        if output is None:
48
 
            config = branch.get_config()
49
52
            if mail_to is None:
50
 
                mail_to = config.get_user_option('submit_to')
51
 
            mail_client = config.get_mail_client()
 
53
                mail_to = branch.get_config_stack().get('submit_to')
 
54
            mail_client = branch.get_config().get_mail_client()
52
55
            if (not getattr(mail_client, 'supports_body', False)
53
56
                and body is not None):
54
 
                raise errors.BzrCommandError(
55
 
                    'Mail client "%s" does not support specifying body' %
 
57
                raise errors.BzrCommandError(gettext(
 
58
                    'Mail client "%s" does not support specifying body') %
56
59
                    mail_client.__class__.__name__)
57
 
        if remember and submit_branch is None:
58
 
            raise errors.BzrCommandError(
59
 
                '--remember requires a branch to be specified.')
60
 
        stored_submit_branch = branch.get_submit_branch()
61
 
        remembered_submit_branch = None
62
 
        if submit_branch is None:
63
 
            submit_branch = stored_submit_branch
64
 
            remembered_submit_branch = "submit"
 
60
        if remember and target_branch is None:
 
61
            raise errors.BzrCommandError(gettext(
 
62
                '--remember requires a branch to be specified.'))
 
63
        stored_target_branch = branch.get_submit_branch()
 
64
        remembered_target_branch = None
 
65
        if target_branch is None:
 
66
            target_branch = stored_target_branch
 
67
            remembered_target_branch = "submit"
65
68
        else:
66
 
            if stored_submit_branch is None or remember:
67
 
                branch.set_submit_branch(submit_branch)
68
 
        if submit_branch is None:
69
 
            submit_branch = branch.get_parent()
70
 
            remembered_submit_branch = "parent"
71
 
        if submit_branch is None:
72
 
            raise errors.BzrCommandError('No submit branch known or'
73
 
                                         ' specified')
74
 
        if remembered_submit_branch is not None:
75
 
            trace.note('Using saved %s location "%s" to determine what '
76
 
                       'changes to submit.', remembered_submit_branch,
77
 
                       submit_branch)
 
69
            # Remembers if asked explicitly or no previous location is set
 
70
            if remember or (
 
71
                    remember is None and stored_target_branch is None):
 
72
                branch.set_submit_branch(target_branch)
 
73
        if target_branch is None:
 
74
            target_branch = branch.get_parent()
 
75
            remembered_target_branch = "parent"
 
76
        if target_branch is None:
 
77
            raise errors.BzrCommandError(gettext('No submit branch known or'
 
78
                                         ' specified'))
 
79
        if remembered_target_branch is not None:
 
80
            trace.note(gettext('Using saved {0} location "{1}" to determine '
 
81
                       'what changes to submit.').format(
 
82
                                    remembered_target_branch,
 
83
                                    target_branch))
78
84
 
 
85
        submit_branch = Branch.open(target_branch,
 
86
            possible_transports=possible_transports)
 
87
        possible_transports.append(submit_branch.bzrdir.root_transport)
79
88
        if mail_to is None or format is None:
80
 
            # TODO: jam 20090716 we open the submit_branch here, but we *don't*
81
 
            #       pass it down into the format creation, so it will have to
82
 
            #       open it again
83
 
            submit_br = Branch.open(submit_branch)
84
 
            submit_config = submit_br.get_config()
85
89
            if mail_to is None:
86
 
                mail_to = submit_config.get_user_option("child_submit_to")
 
90
                mail_to = submit_branch.get_config_stack().get(
 
91
                    'child_submit_to')
87
92
            if format is None:
88
 
                formatname = submit_br.get_child_submit_format()
 
93
                formatname = submit_branch.get_child_submit_format()
89
94
                try:
90
95
                    format = format_registry.get(formatname)
91
96
                except KeyError:
92
 
                    raise errors.BzrCommandError("No such send format '%s'." % 
93
 
                                                 formatname)
 
97
                    raise errors.BzrCommandError(
 
98
                        gettext("No such send format '%s'.") % formatname)
94
99
 
95
100
        stored_public_branch = branch.get_public_branch()
96
101
        if public_branch is None:
97
102
            public_branch = stored_public_branch
98
 
        elif stored_public_branch is None or remember:
 
103
        # Remembers if asked explicitly or no previous location is set
 
104
        elif (remember
 
105
              or (remember is None and stored_public_branch is None)):
99
106
            branch.set_public_branch(public_branch)
100
107
        if no_bundle and public_branch is None:
101
 
            raise errors.BzrCommandError('No public branch specified or'
102
 
                                         ' known')
 
108
            raise errors.BzrCommandError(gettext('No public branch specified or'
 
109
                                         ' known'))
103
110
        base_revision_id = None
104
111
        revision_id = None
105
112
        if revision is not None:
106
113
            if len(revision) > 2:
107
 
                raise errors.BzrCommandError('bzr send takes '
108
 
                    'at most two one revision identifiers')
 
114
                raise errors.BzrCommandError(gettext('bzr send takes '
 
115
                    'at most two one revision identifiers'))
109
116
            revision_id = revision[-1].as_revision_id(branch)
110
117
            if len(revision) == 2:
111
118
                base_revision_id = revision[0].as_revision_id(branch)
117
124
                    more_warning='Uncommitted changes will not be sent.')
118
125
            revision_id = branch.last_revision()
119
126
        if revision_id == NULL_REVISION:
120
 
            raise errors.BzrCommandError('No revisions to submit.')
 
127
            raise errors.BzrCommandError(gettext('No revisions to submit.'))
121
128
        if format is None:
122
129
            format = format_registry.get()
123
 
        directive = format(branch, revision_id, submit_branch,
124
 
            public_branch, no_patch, no_bundle, message, base_revision_id)
 
130
        directive = format(branch, revision_id, target_branch,
 
131
            public_branch, no_patch, no_bundle, message, base_revision_id,
 
132
            submit_branch)
125
133
        if output is None:
126
134
            directive.compose_merge_request(mail_client, mail_to, body,
127
135
                                            branch, tree)
128
136
        else:
129
137
            if directive.multiple_output_files:
130
138
                if output == '-':
131
 
                    raise errors.BzrCommandError('- not supported for '
132
 
                        'merge directives that use more than one output file.')
 
139
                    raise errors.BzrCommandError(gettext('- not supported for '
 
140
                        'merge directives that use more than one output file.'))
133
141
                if not os.path.exists(output):
134
142
                    os.mkdir(output, 0755)
135
143
                for (filename, lines) in directive.to_files():
153
161
        branch.unlock()
154
162
 
155
163
 
156
 
def _send_4(branch, revision_id, submit_branch, public_branch,
157
 
            no_patch, no_bundle, message, base_revision_id):
 
164
def _send_4(branch, revision_id, target_branch, public_branch,
 
165
            no_patch, no_bundle, message,
 
166
            base_revision_id, local_target_branch=None):
158
167
    from bzrlib import merge_directive
159
168
    return merge_directive.MergeDirective2.from_objects(
160
169
        branch.repository, revision_id, time.time(),
161
 
        osutils.local_time_offset(), submit_branch,
162
 
        public_branch=public_branch, include_patch=not no_patch,
 
170
        osutils.local_time_offset(), target_branch,
 
171
        public_branch=public_branch,
 
172
        include_patch=not no_patch,
163
173
        include_bundle=not no_bundle, message=message,
164
 
        base_revision_id=base_revision_id)
 
174
        base_revision_id=base_revision_id,
 
175
        local_target_branch=local_target_branch)
165
176
 
166
177
 
167
178
def _send_0_9(branch, revision_id, submit_branch, public_branch,
168
 
              no_patch, no_bundle, message, base_revision_id):
 
179
              no_patch, no_bundle, message,
 
180
              base_revision_id, local_target_branch=None):
169
181
    if not no_bundle:
170
182
        if not no_patch:
171
183
            patch_type = 'bundle'
172
184
        else:
173
 
            raise errors.BzrCommandError('Format 0.9 does not'
174
 
                ' permit bundle with no patch')
 
185
            raise errors.BzrCommandError(gettext('Format 0.9 does not'
 
186
                ' permit bundle with no patch'))
175
187
    else:
176
188
        if not no_patch:
177
189
            patch_type = 'diff'
182
194
        branch.repository, revision_id, time.time(),
183
195
        osutils.local_time_offset(), submit_branch,
184
196
        public_branch=public_branch, patch_type=patch_type,
185
 
        message=message)
186
 
 
187
 
 
188
 
format_registry.register('4', 
 
197
        message=message, local_target_branch=local_target_branch)
 
198
 
 
199
 
 
200
format_registry.register('4',
189
201
    _send_4, 'Bundle format 4, Merge Directive 2 (default)')
190
202
format_registry.register('0.9',
191
203
    _send_0_9, 'Bundle format 0.9, Merge Directive 1')