/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.431.1 by Jelmer Vernooij
Start work on propose command.
1
# Copyright (C) 2018 Jelmer Vernooij <jelmer@jelmer.uk>
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
"""Propose command implementations."""
18
0.431.54 by Jelmer Vernooij
Include commit data in 'brz propose'.
19
from io import StringIO
20
0.431.1 by Jelmer Vernooij
Start work on propose command.
21
from ... import (
22
    branch as _mod_branch,
23
    controldir,
24
    errors,
0.431.54 by Jelmer Vernooij
Include commit data in 'brz propose'.
25
    log as _mod_log,
26
    missing as _mod_missing,
0.431.2 by Jelmer Vernooij
Add launchpad implementation.
27
    msgeditor,
0.432.2 by Jelmer Vernooij
Publish command sort of works.
28
    urlutils,
0.431.1 by Jelmer Vernooij
Start work on propose command.
29
    )
30
from ...i18n import gettext
31
from ...commands import Command
0.431.6 by Jelmer Vernooij
Initial gitlab support works.
32
from ...option import (
33
    ListOption,
0.432.2 by Jelmer Vernooij
Publish command sort of works.
34
    Option,
0.431.6 by Jelmer Vernooij
Initial gitlab support works.
35
    RegistryOption,
36
    )
7490.115.1 by Jelmer Vernooij
Raise UnexpectedHttpStatus rather than InvalidHttpResponse.
37
from ...trace import note, warning
7408.3.1 by Jelmer Vernooij
Move propose module into core.
38
from ... import (
0.431.1 by Jelmer Vernooij
Start work on propose command.
39
    propose as _mod_propose,
40
    )
41
42
0.432.2 by Jelmer Vernooij
Publish command sort of works.
43
def branch_name(branch):
44
    if branch.name:
45
        return branch.name
46
    return urlutils.basename(branch.user_url)
47
48
7490.54.2 by Jelmer Vernooij
Also run checks in 'brz publish'.
49
def _check_already_merged(branch, target):
50
    # TODO(jelmer): Check entire ancestry rather than just last revision?
51
    if branch.last_revision() == target.last_revision():
7490.61.1 by Jelmer Vernooij
Rename BzrCommandError to CommandError.
52
        raise errors.CommandError(gettext(
7490.54.2 by Jelmer Vernooij
Also run checks in 'brz publish'.
53
            'All local changes are already present in target.'))
54
55
0.431.18 by Jelmer Vernooij
Rename 'brz publish' to 'brz publish-derived'.
56
class cmd_publish_derived(Command):
57
    __doc__ = """Publish a derived branch.
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
58
0.431.18 by Jelmer Vernooij
Rename 'brz publish' to 'brz publish-derived'.
59
    Try to create a public copy of a local branch on a hosting site,
60
    derived from the specified base branch.
0.432.2 by Jelmer Vernooij
Publish command sort of works.
61
62
    Reasonable defaults are picked for owner name, branch name and project
63
    name, but they can also be overridden from the command-line.
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
64
    """
65
0.432.2 by Jelmer Vernooij
Publish command sort of works.
66
    takes_options = [
7211.13.7 by Jelmer Vernooij
Fix formatting.
67
        'directory',
68
        Option('owner', help='Owner of the new remote branch.', type=str),
69
        Option('project', help='Project name for the new remote branch.',
70
               type=str),
71
        Option('name', help='Name of the new remote branch.', type=str),
72
        Option('no-allow-lossy',
73
               help='Allow fallback to lossy push, if necessary.'),
74
        Option('overwrite', help="Overwrite existing commits."),
75
        ]
0.432.2 by Jelmer Vernooij
Publish command sort of works.
76
    takes_args = ['submit_branch?']
77
78
    def run(self, submit_branch=None, owner=None, name=None, project=None,
0.431.52 by Jelmer Vernooij
Add --overwrite flag to 'brz publish'.
79
            no_allow_lossy=False, overwrite=False, directory='.'):
0.432.2 by Jelmer Vernooij
Publish command sort of works.
80
        local_branch = _mod_branch.Branch.open_containing(directory)[0]
81
        self.add_cleanup(local_branch.lock_write().unlock)
82
        if submit_branch is None:
83
            submit_branch = local_branch.get_submit_branch()
84
            note(gettext('Using submit branch %s') % submit_branch)
0.431.22 by Jelmer Vernooij
Add Hoster.get_derived_branch.
85
        if submit_branch is None:
86
            submit_branch = local_branch.get_parent()
87
            note(gettext('Using parent branch %s') % submit_branch)
0.432.2 by Jelmer Vernooij
Publish command sort of works.
88
        submit_branch = _mod_branch.Branch.open(submit_branch)
7490.54.2 by Jelmer Vernooij
Also run checks in 'brz publish'.
89
        _check_already_merged(local_branch, submit_branch)
0.432.2 by Jelmer Vernooij
Publish command sort of works.
90
        if name is None:
91
            name = branch_name(local_branch)
92
        hoster = _mod_propose.get_hoster(submit_branch)
0.431.20 by Jelmer Vernooij
publish -> publish_derived.
93
        remote_branch, public_url = hoster.publish_derived(
7211.13.7 by Jelmer Vernooij
Fix formatting.
94
            local_branch, submit_branch, name=name, project=project,
95
            owner=owner, allow_lossy=not no_allow_lossy,
96
            overwrite=overwrite)
0.432.2 by Jelmer Vernooij
Publish command sort of works.
97
        local_branch.set_push_location(remote_branch.user_url)
98
        local_branch.set_public_branch(public_url)
7342.1.2 by Jelmer Vernooij
Set the submit branch after 'brz publish' / 'brz propose'
99
        local_branch.set_submit_branch(submit_branch.user_url)
0.432.2 by Jelmer Vernooij
Publish command sort of works.
100
        note(gettext("Pushed to %s") % public_url)
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
101
102
0.431.56 by Jelmer Vernooij
Add support for prerequisite branches.
103
def summarize_unmerged(local_branch, remote_branch, target,
104
                       prerequisite_branch=None):
0.431.54 by Jelmer Vernooij
Include commit data in 'brz propose'.
105
    """Generate a text description of the unmerged revisions in branch.
106
107
    :param branch: The proposed branch
108
    :param target: Target branch
0.431.56 by Jelmer Vernooij
Add support for prerequisite branches.
109
    :param prerequisite_branch: Optional prerequisite branch
0.431.54 by Jelmer Vernooij
Include commit data in 'brz propose'.
110
    :return: A string
111
    """
0.431.55 by Jelmer Vernooij
Cope with lossy pushes better in `brz propose` texts.
112
    log_format = _mod_log.log_formatter_registry.get_default(local_branch)
0.431.54 by Jelmer Vernooij
Include commit data in 'brz propose'.
113
    to_file = StringIO()
114
    lf = log_format(to_file=to_file, show_ids=False, show_timezone='original')
0.431.56 by Jelmer Vernooij
Add support for prerequisite branches.
115
    if prerequisite_branch:
116
        local_extra = _mod_missing.find_unmerged(
117
            remote_branch, prerequisite_branch, restrict='local')[0]
118
    else:
119
        local_extra = _mod_missing.find_unmerged(
120
            remote_branch, target, restrict='local')[0]
0.431.54 by Jelmer Vernooij
Include commit data in 'brz propose'.
121
0.431.55 by Jelmer Vernooij
Cope with lossy pushes better in `brz propose` texts.
122
    if remote_branch.supports_tags():
123
        rev_tag_dict = remote_branch.tags.get_reverse_tag_dict()
0.431.54 by Jelmer Vernooij
Include commit data in 'brz propose'.
124
    else:
125
        rev_tag_dict = {}
126
127
    for revision in _mod_missing.iter_log_revisions(
0.431.55 by Jelmer Vernooij
Cope with lossy pushes better in `brz propose` texts.
128
            local_extra, local_branch.repository, False, rev_tag_dict):
0.431.54 by Jelmer Vernooij
Include commit data in 'brz propose'.
129
        lf.log_revision(revision)
130
    return to_file.getvalue()
131
132
0.431.1 by Jelmer Vernooij
Start work on propose command.
133
class cmd_propose_merge(Command):
134
    __doc__ = """Propose a branch for merging.
135
136
    This command creates a merge proposal for the local
137
    branch to the target branch. The format of the merge
138
    proposal depends on the submit branch.
139
    """
140
0.431.54 by Jelmer Vernooij
Include commit data in 'brz propose'.
141
    takes_options = [
7211.13.7 by Jelmer Vernooij
Fix formatting.
142
        'directory',
143
        RegistryOption(
144
            'hoster',
145
            help='Use the hoster.',
146
            lazy_registry=('breezy.plugins.propose.propose', 'hosters')),
7479.2.1 by Jelmer Vernooij
Drop python2 support.
147
        ListOption('reviewers', short_name='R', type=str,
7211.13.7 by Jelmer Vernooij
Fix formatting.
148
                   help='Requested reviewers.'),
149
        Option('name', help='Name of the new remote branch.', type=str),
150
        Option('description', help='Description of the change.', type=str),
151
        Option('prerequisite', help='Prerequisite branch.', type=str),
7467.3.2 by Jelmer Vernooij
Add --wip flag for 'brz propose'.
152
        Option('wip', help='Mark merge request as work-in-progress'),
7296.8.1 by Jelmer Vernooij
Add commit-message option to 'brz propose'.
153
        Option(
154
            'commit-message',
155
            help='Set commit message for merge, if supported', type=str),
7479.2.1 by Jelmer Vernooij
Drop python2 support.
156
        ListOption('labels', short_name='l', type=str,
7211.13.7 by Jelmer Vernooij
Fix formatting.
157
                   help='Labels to apply.'),
158
        Option('no-allow-lossy',
159
               help='Allow fallback to lossy push, if necessary.'),
7490.6.1 by Jelmer Vernooij
Add allow-collaboration flag.
160
        Option('allow-collaboration',
161
               help='Allow collaboration from target branch maintainer(s)'),
7490.54.1 by Jelmer Vernooij
Prevent empty proposals.
162
        Option('allow-empty',
163
               help='Do not prevent empty merge proposals.'),
7211.13.7 by Jelmer Vernooij
Fix formatting.
164
        ]
0.431.1 by Jelmer Vernooij
Start work on propose command.
165
    takes_args = ['submit_branch?']
166
167
    aliases = ['propose']
168
0.431.54 by Jelmer Vernooij
Include commit data in 'brz propose'.
169
    def run(self, submit_branch=None, directory='.', hoster=None,
170
            reviewers=None, name=None, no_allow_lossy=False, description=None,
7490.6.1 by Jelmer Vernooij
Add allow-collaboration flag.
171
            labels=None, prerequisite=None, commit_message=None, wip=False,
7490.54.1 by Jelmer Vernooij
Prevent empty proposals.
172
            allow_collaboration=False, allow_empty=False):
0.431.54 by Jelmer Vernooij
Include commit data in 'brz propose'.
173
        tree, branch, relpath = (
174
            controldir.ControlDir.open_containing_tree_or_branch(directory))
0.431.1 by Jelmer Vernooij
Start work on propose command.
175
        if submit_branch is None:
176
            submit_branch = branch.get_submit_branch()
177
        if submit_branch is None:
0.432.7 by Jelmer Vernooij
propose works \o/
178
            submit_branch = branch.get_parent()
179
        if submit_branch is None:
7490.61.1 by Jelmer Vernooij
Rename BzrCommandError to CommandError.
180
            raise errors.CommandError(
0.431.54 by Jelmer Vernooij
Include commit data in 'brz propose'.
181
                gettext("No target location specified or remembered"))
7490.54.1 by Jelmer Vernooij
Prevent empty proposals.
182
        target = _mod_branch.Branch.open(submit_branch)
7490.54.2 by Jelmer Vernooij
Also run checks in 'brz publish'.
183
        if not allow_empty:
184
            _check_already_merged(branch, target)
0.432.7 by Jelmer Vernooij
propose works \o/
185
        if hoster is None:
186
            hoster = _mod_propose.get_hoster(target)
0.431.5 by Jelmer Vernooij
Initial work on gitlab support.
187
        else:
0.432.7 by Jelmer Vernooij
propose works \o/
188
            hoster = hoster.probe(target)
189
        if name is None:
190
            name = branch_name(branch)
0.431.20 by Jelmer Vernooij
publish -> publish_derived.
191
        remote_branch, public_branch_url = hoster.publish_derived(
7211.13.7 by Jelmer Vernooij
Fix formatting.
192
            branch, target, name=name, allow_lossy=not no_allow_lossy)
0.431.37 by Jelmer Vernooij
add a find-merge-proposal command.
193
        branch.set_push_location(remote_branch.user_url)
7342.1.2 by Jelmer Vernooij
Set the submit branch after 'brz publish' / 'brz propose'
194
        branch.set_submit_branch(target.user_url)
0.432.7 by Jelmer Vernooij
propose works \o/
195
        note(gettext('Published branch to %s') % public_branch_url)
0.431.56 by Jelmer Vernooij
Add support for prerequisite branches.
196
        if prerequisite is not None:
197
            prerequisite_branch = _mod_branch.Branch.open(prerequisite)
198
        else:
199
            prerequisite_branch = None
0.432.7 by Jelmer Vernooij
propose works \o/
200
        proposal_builder = hoster.get_proposer(remote_branch, target)
0.432.10 by Jelmer Vernooij
More test fixes.
201
        if description is None:
202
            body = proposal_builder.get_initial_body()
203
            info = proposal_builder.get_infotext()
0.431.56 by Jelmer Vernooij
Add support for prerequisite branches.
204
            info += "\n\n" + summarize_unmerged(
205
                branch, remote_branch, target, prerequisite_branch)
0.431.54 by Jelmer Vernooij
Include commit data in 'brz propose'.
206
            description = msgeditor.edit_commit_message(
207
                info, start_message=body)
0.431.2 by Jelmer Vernooij
Add launchpad implementation.
208
        try:
0.432.7 by Jelmer Vernooij
propose works \o/
209
            proposal = proposal_builder.create_proposal(
0.431.56 by Jelmer Vernooij
Add support for prerequisite branches.
210
                description=description, reviewers=reviewers,
7296.8.1 by Jelmer Vernooij
Add commit-message option to 'brz propose'.
211
                prerequisite_branch=prerequisite_branch, labels=labels,
7467.3.2 by Jelmer Vernooij
Add --wip flag for 'brz propose'.
212
                commit_message=commit_message,
7490.6.1 by Jelmer Vernooij
Add allow-collaboration flag.
213
                work_in_progress=wip, allow_collaboration=allow_collaboration)
0.431.2 by Jelmer Vernooij
Add launchpad implementation.
214
        except _mod_propose.MergeProposalExists as e:
7359.1.3 by Jelmer Vernooij
Fix GitHub API interaction.
215
            note(gettext('There is already a branch merge proposal: %s'), e.url)
216
        else:
217
            note(gettext('Merge proposal created: %s') % proposal.url)
0.431.37 by Jelmer Vernooij
add a find-merge-proposal command.
218
219
220
class cmd_find_merge_proposal(Command):
221
    __doc__ = """Find a merge proposal.
222
223
    """
224
225
    takes_options = ['directory']
226
    takes_args = ['submit_branch?']
227
    aliases = ['find-proposal']
228
229
    def run(self, directory='.', submit_branch=None):
230
        tree, branch, relpath = controldir.ControlDir.open_containing_tree_or_branch(
231
            directory)
232
        public_location = branch.get_public_branch()
233
        if public_location:
234
            branch = _mod_branch.Branch.open(public_location)
235
        if submit_branch is None:
236
            submit_branch = branch.get_submit_branch()
237
        if submit_branch is None:
238
            submit_branch = branch.get_parent()
239
        if submit_branch is None:
7490.61.1 by Jelmer Vernooij
Rename BzrCommandError to CommandError.
240
            raise errors.CommandError(
0.431.55 by Jelmer Vernooij
Cope with lossy pushes better in `brz propose` texts.
241
                gettext("No target location specified or remembered"))
0.431.37 by Jelmer Vernooij
add a find-merge-proposal command.
242
        else:
243
            target = _mod_branch.Branch.open(submit_branch)
244
        hoster = _mod_propose.get_hoster(branch)
0.431.67 by Jelmer Vernooij
Support multiple merge proposals per branch.
245
        for mp in hoster.iter_proposals(branch, target):
246
            self.outf.write(gettext('Merge proposal: %s\n') % mp.url)
0.431.47 by Jelmer Vernooij
Add github login command.
247
248
0.431.63 by Jelmer Vernooij
Add 'brz my-proposals' command.
249
class cmd_my_merge_proposals(Command):
0.431.66 by Jelmer Vernooij
Add support for status argument.
250
    __doc__ = """List all merge proposals owned by the logged-in user.
0.431.63 by Jelmer Vernooij
Add 'brz my-proposals' command.
251
252
    """
253
0.431.69 by Jelmer Vernooij
Make 'brz my-proposals' hidden for the moment.
254
    hidden = True
255
0.431.66 by Jelmer Vernooij
Add support for status argument.
256
    takes_options = [
7296.10.3 by Jelmer Vernooij
More fixes.
257
        'verbose',
0.431.66 by Jelmer Vernooij
Add support for status argument.
258
        RegistryOption.from_kwargs(
259
            'status',
260
            title='Proposal Status',
261
            help='Only include proposals with specified status.',
262
            value_switches=True,
263
            enum_switch=True,
264
            all='All merge proposals',
265
            open='Open merge proposals',
266
            merged='Merged merge proposals',
267
            closed='Closed merge proposals')]
268
7296.10.3 by Jelmer Vernooij
More fixes.
269
    def run(self, status='open', verbose=False):
7490.105.1 by Jelmer Vernooij
Add some hoster metadata fields.
270
        for instance in _mod_propose.iter_hoster_instances():
7490.115.1 by Jelmer Vernooij
Raise UnexpectedHttpStatus rather than InvalidHttpResponse.
271
            try:
272
                for mp in instance.iter_my_proposals(status=status):
273
                    self.outf.write('%s\n' % mp.url)
274
                    if verbose:
275
                        self.outf.write(
276
                            '(Merging %s into %s)\n' %
277
                            (mp.get_source_branch_url(),
278
                             mp.get_target_branch_url()))
279
                        description = mp.get_description()
280
                        if description:
281
                            self.outf.writelines(
282
                                ['\t%s\n' % l
283
                                 for l in description.splitlines()])
284
                        self.outf.write('\n')
285
            except _mod_propose.HosterLoginRequired as e:
286
                warning('Skipping %r, login required.', instance)
7296.9.1 by Jelmer Vernooij
Add 'brz land' subcommand.
287
288
289
class cmd_land_merge_proposal(Command):
290
    __doc__ = """Land a merge proposal."""
291
292
    takes_args = ['url']
293
    takes_options = [
294
        Option('message', help='Commit message to use.', type=str)]
295
296
    def run(self, url, message=None):
7408.3.1 by Jelmer Vernooij
Move propose module into core.
297
        proposal = _mod_propose.get_proposal_by_url(url)
7296.9.1 by Jelmer Vernooij
Add 'brz land' subcommand.
298
        proposal.merge(commit_message=message)
7490.105.1 by Jelmer Vernooij
Add some hoster metadata fields.
299
300
301
class cmd_hosters(Command):
302
    __doc__ = """List all known hosting sites and user details."""
303
304
    hidden = True
305
306
    def run(self):
307
        for instance in _mod_propose.iter_hoster_instances():
308
            current_user = instance.get_current_user()
7490.114.1 by Jelmer Vernooij
Print hoster instances with credentials.
309
            if current_user is not None:
310
                self.outf.write(
311
                    gettext('%s (%s) - user: %s (%s)\n') % (
312
                        instance.name, instance.base_url,
313
                        current_user, instance.get_user_url(current_user)))
314
            else:
315
                self.outf.write(
316
                    gettext('%s (%s) - not logged in\n') % (
317
                        instance.name, instance.base_url))