/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 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:
 
1
# Copyright (C) 2009, 2010 Canonical Ltd
 
2
#
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
14
# along with this program; if not, write to the Free Software
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
from __future__ import absolute_import
 
18
 
 
19
import os
 
20
import time
 
21
 
 
22
from bzrlib import (
 
23
    controldir,
 
24
    errors,
 
25
    osutils,
 
26
    registry,
 
27
    trace,
 
28
    )
 
29
from bzrlib.i18n import gettext
 
30
from bzrlib.branch import (
 
31
    Branch,
 
32
    )
 
33
from bzrlib.revision import (
 
34
    NULL_REVISION,
 
35
    )
 
36
 
 
37
 
 
38
format_registry = registry.Registry()
 
39
 
 
40
 
 
41
def send(target_branch, revision, public_branch, remember,
 
42
         format, no_bundle, no_patch, output, from_, mail_to, message, body,
 
43
         to_file, strict=None):
 
44
    tree, branch = controldir.ControlDir.open_containing_tree_or_branch(
 
45
        from_)[:2]
 
46
    possible_transports = [tree.bzrdir.transport, branch.bzrdir.transport]
 
47
    # we may need to write data into branch's repository to calculate
 
48
    # the data to send.
 
49
    branch.lock_write()
 
50
    try:
 
51
        if output is None:
 
52
            if mail_to is None:
 
53
                mail_to = branch.get_config_stack().get('submit_to')
 
54
            mail_client = branch.get_config().get_mail_client()
 
55
            if (not getattr(mail_client, 'supports_body', False)
 
56
                and body is not None):
 
57
                raise errors.BzrCommandError(gettext(
 
58
                    'Mail client "%s" does not support specifying body') %
 
59
                    mail_client.__class__.__name__)
 
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"
 
68
        else:
 
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))
 
84
 
 
85
        submit_branch = Branch.open(target_branch,
 
86
            possible_transports=possible_transports)
 
87
        possible_transports.append(submit_branch.bzrdir.root_transport)
 
88
        if mail_to is None or format is None:
 
89
            if mail_to is None:
 
90
                mail_to = submit_branch.get_config_stack().get(
 
91
                    'child_submit_to')
 
92
            if format is None:
 
93
                formatname = submit_branch.get_child_submit_format()
 
94
                try:
 
95
                    format = format_registry.get(formatname)
 
96
                except KeyError:
 
97
                    raise errors.BzrCommandError(
 
98
                        gettext("No such send format '%s'.") % formatname)
 
99
 
 
100
        stored_public_branch = branch.get_public_branch()
 
101
        if public_branch is None:
 
102
            public_branch = stored_public_branch
 
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)):
 
106
            branch.set_public_branch(public_branch)
 
107
        if no_bundle and public_branch is None:
 
108
            raise errors.BzrCommandError(gettext('No public branch specified or'
 
109
                                         ' known'))
 
110
        base_revision_id = None
 
111
        revision_id = None
 
112
        if revision is not None:
 
113
            if len(revision) > 2:
 
114
                raise errors.BzrCommandError(gettext('bzr send takes '
 
115
                    'at most two one revision identifiers'))
 
116
            revision_id = revision[-1].as_revision_id(branch)
 
117
            if len(revision) == 2:
 
118
                base_revision_id = revision[0].as_revision_id(branch)
 
119
        if revision_id is None:
 
120
            if tree is not None:
 
121
                tree.check_changed_or_out_of_date(
 
122
                    strict, 'send_strict',
 
123
                    more_error='Use --no-strict to force the send.',
 
124
                    more_warning='Uncommitted changes will not be sent.')
 
125
            revision_id = branch.last_revision()
 
126
        if revision_id == NULL_REVISION:
 
127
            raise errors.BzrCommandError(gettext('No revisions to submit.'))
 
128
        if format is None:
 
129
            format = format_registry.get()
 
130
        directive = format(branch, revision_id, target_branch,
 
131
            public_branch, no_patch, no_bundle, message, base_revision_id,
 
132
            submit_branch)
 
133
        if output is None:
 
134
            directive.compose_merge_request(mail_client, mail_to, body,
 
135
                                            branch, tree)
 
136
        else:
 
137
            if directive.multiple_output_files:
 
138
                if output == '-':
 
139
                    raise errors.BzrCommandError(gettext('- not supported for '
 
140
                        'merge directives that use more than one output file.'))
 
141
                if not os.path.exists(output):
 
142
                    os.mkdir(output, 0755)
 
143
                for (filename, lines) in directive.to_files():
 
144
                    path = os.path.join(output, filename)
 
145
                    outfile = open(path, 'wb')
 
146
                    try:
 
147
                        outfile.writelines(lines)
 
148
                    finally:
 
149
                        outfile.close()
 
150
            else:
 
151
                if output == '-':
 
152
                    outfile = to_file
 
153
                else:
 
154
                    outfile = open(output, 'wb')
 
155
                try:
 
156
                    outfile.writelines(directive.to_lines())
 
157
                finally:
 
158
                    if outfile is not to_file:
 
159
                        outfile.close()
 
160
    finally:
 
161
        branch.unlock()
 
162
 
 
163
 
 
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):
 
167
    from bzrlib import merge_directive
 
168
    return merge_directive.MergeDirective2.from_objects(
 
169
        branch.repository, revision_id, time.time(),
 
170
        osutils.local_time_offset(), target_branch,
 
171
        public_branch=public_branch,
 
172
        include_patch=not no_patch,
 
173
        include_bundle=not no_bundle, message=message,
 
174
        base_revision_id=base_revision_id,
 
175
        local_target_branch=local_target_branch)
 
176
 
 
177
 
 
178
def _send_0_9(branch, revision_id, submit_branch, public_branch,
 
179
              no_patch, no_bundle, message,
 
180
              base_revision_id, local_target_branch=None):
 
181
    if not no_bundle:
 
182
        if not no_patch:
 
183
            patch_type = 'bundle'
 
184
        else:
 
185
            raise errors.BzrCommandError(gettext('Format 0.9 does not'
 
186
                ' permit bundle with no patch'))
 
187
    else:
 
188
        if not no_patch:
 
189
            patch_type = 'diff'
 
190
        else:
 
191
            patch_type = None
 
192
    from bzrlib import merge_directive
 
193
    return merge_directive.MergeDirective.from_objects(
 
194
        branch.repository, revision_id, time.time(),
 
195
        osutils.local_time_offset(), submit_branch,
 
196
        public_branch=public_branch, patch_type=patch_type,
 
197
        message=message, local_target_branch=local_target_branch)
 
198
 
 
199
 
 
200
format_registry.register('4',
 
201
    _send_4, 'Bundle format 4, Merge Directive 2 (default)')
 
202
format_registry.register('0.9',
 
203
    _send_0_9, 'Bundle format 0.9, Merge Directive 1')
 
204
format_registry.default_key = '4'