/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.434.1 by Jelmer Vernooij
Use absolute_import.
19
from __future__ import absolute_import
20
0.431.54 by Jelmer Vernooij
Include commit data in 'brz propose'.
21
from io import StringIO
22
0.431.1 by Jelmer Vernooij
Start work on propose command.
23
from ... import (
24
    branch as _mod_branch,
25
    controldir,
26
    errors,
0.431.54 by Jelmer Vernooij
Include commit data in 'brz propose'.
27
    log as _mod_log,
28
    missing as _mod_missing,
0.431.2 by Jelmer Vernooij
Add launchpad implementation.
29
    msgeditor,
0.432.2 by Jelmer Vernooij
Publish command sort of works.
30
    urlutils,
0.431.1 by Jelmer Vernooij
Start work on propose command.
31
    )
32
from ...i18n import gettext
33
from ...commands import Command
0.431.6 by Jelmer Vernooij
Initial gitlab support works.
34
from ...option import (
35
    ListOption,
0.432.2 by Jelmer Vernooij
Publish command sort of works.
36
    Option,
0.431.6 by Jelmer Vernooij
Initial gitlab support works.
37
    RegistryOption,
38
    )
39
from ...sixish import text_type
0.432.2 by Jelmer Vernooij
Publish command sort of works.
40
from ...trace import note
0.431.1 by Jelmer Vernooij
Start work on propose command.
41
from . import (
42
    propose as _mod_propose,
43
    )
44
45
0.432.2 by Jelmer Vernooij
Publish command sort of works.
46
def branch_name(branch):
47
    if branch.name:
48
        return branch.name
49
    return urlutils.basename(branch.user_url)
50
51
0.431.18 by Jelmer Vernooij
Rename 'brz publish' to 'brz publish-derived'.
52
class cmd_publish_derived(Command):
53
    __doc__ = """Publish a derived branch.
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
54
0.431.18 by Jelmer Vernooij
Rename 'brz publish' to 'brz publish-derived'.
55
    Try to create a public copy of a local branch on a hosting site,
56
    derived from the specified base branch.
0.432.2 by Jelmer Vernooij
Publish command sort of works.
57
58
    Reasonable defaults are picked for owner name, branch name and project
59
    name, but they can also be overridden from the command-line.
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
60
    """
61
0.432.2 by Jelmer Vernooij
Publish command sort of works.
62
    takes_options = [
63
            'directory',
0.432.7 by Jelmer Vernooij
propose works \o/
64
            Option('owner', help='Owner of the new remote branch.', type=str),
0.431.55 by Jelmer Vernooij
Cope with lossy pushes better in `brz propose` texts.
65
            Option('project', help='Project name for the new remote branch.',
66
                   type=str),
0.432.7 by Jelmer Vernooij
propose works \o/
67
            Option('name', help='Name of the new remote branch.', type=str),
0.431.55 by Jelmer Vernooij
Cope with lossy pushes better in `brz propose` texts.
68
            Option('no-allow-lossy',
69
                   help='Allow fallback to lossy push, if necessary.'),
0.431.52 by Jelmer Vernooij
Add --overwrite flag to 'brz publish'.
70
            Option('overwrite', help="Overwrite existing commits."),
0.432.2 by Jelmer Vernooij
Publish command sort of works.
71
            ]
72
    takes_args = ['submit_branch?']
73
74
    def run(self, submit_branch=None, owner=None, name=None, project=None,
0.431.52 by Jelmer Vernooij
Add --overwrite flag to 'brz publish'.
75
            no_allow_lossy=False, overwrite=False, directory='.'):
0.432.2 by Jelmer Vernooij
Publish command sort of works.
76
        local_branch = _mod_branch.Branch.open_containing(directory)[0]
77
        self.add_cleanup(local_branch.lock_write().unlock)
78
        if submit_branch is None:
79
            submit_branch = local_branch.get_submit_branch()
80
            note(gettext('Using submit branch %s') % submit_branch)
0.431.22 by Jelmer Vernooij
Add Hoster.get_derived_branch.
81
        if submit_branch is None:
82
            submit_branch = local_branch.get_parent()
83
            note(gettext('Using parent branch %s') % submit_branch)
0.432.2 by Jelmer Vernooij
Publish command sort of works.
84
        submit_branch = _mod_branch.Branch.open(submit_branch)
85
        if name is None:
86
            name = branch_name(local_branch)
87
        hoster = _mod_propose.get_hoster(submit_branch)
0.431.20 by Jelmer Vernooij
publish -> publish_derived.
88
        remote_branch, public_url = hoster.publish_derived(
0.432.2 by Jelmer Vernooij
Publish command sort of works.
89
                local_branch, submit_branch, name=name, project=project,
0.431.52 by Jelmer Vernooij
Add --overwrite flag to 'brz publish'.
90
                owner=owner, allow_lossy=not no_allow_lossy,
91
                overwrite=overwrite)
0.432.2 by Jelmer Vernooij
Publish command sort of works.
92
        local_branch.set_push_location(remote_branch.user_url)
93
        local_branch.set_public_branch(public_url)
94
        note(gettext("Pushed to %s") % public_url)
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
95
96
0.431.55 by Jelmer Vernooij
Cope with lossy pushes better in `brz propose` texts.
97
def summarize_unmerged(local_branch, remote_branch, target):
0.431.54 by Jelmer Vernooij
Include commit data in 'brz propose'.
98
    """Generate a text description of the unmerged revisions in branch.
99
100
    :param branch: The proposed branch
101
    :param target: Target branch
102
    :return: A string
103
    """
0.431.55 by Jelmer Vernooij
Cope with lossy pushes better in `brz propose` texts.
104
    log_format = _mod_log.log_formatter_registry.get_default(local_branch)
0.431.54 by Jelmer Vernooij
Include commit data in 'brz propose'.
105
    to_file = StringIO()
106
    lf = log_format(to_file=to_file, show_ids=False, show_timezone='original')
107
    local_extra = _mod_missing.find_unmerged(
0.431.55 by Jelmer Vernooij
Cope with lossy pushes better in `brz propose` texts.
108
        remote_branch, target, restrict='local')[0]
0.431.54 by Jelmer Vernooij
Include commit data in 'brz propose'.
109
0.431.55 by Jelmer Vernooij
Cope with lossy pushes better in `brz propose` texts.
110
    if remote_branch.supports_tags():
111
        rev_tag_dict = remote_branch.tags.get_reverse_tag_dict()
0.431.54 by Jelmer Vernooij
Include commit data in 'brz propose'.
112
    else:
113
        rev_tag_dict = {}
114
115
    for revision in _mod_missing.iter_log_revisions(
0.431.55 by Jelmer Vernooij
Cope with lossy pushes better in `brz propose` texts.
116
            local_extra, local_branch.repository, False, rev_tag_dict):
0.431.54 by Jelmer Vernooij
Include commit data in 'brz propose'.
117
        lf.log_revision(revision)
118
    return to_file.getvalue()
119
120
0.431.1 by Jelmer Vernooij
Start work on propose command.
121
class cmd_propose_merge(Command):
122
    __doc__ = """Propose a branch for merging.
123
124
    This command creates a merge proposal for the local
125
    branch to the target branch. The format of the merge
126
    proposal depends on the submit branch.
127
    """
128
0.431.54 by Jelmer Vernooij
Include commit data in 'brz propose'.
129
    takes_options = [
130
            'directory',
0.431.5 by Jelmer Vernooij
Initial work on gitlab support.
131
            RegistryOption(
0.432.7 by Jelmer Vernooij
propose works \o/
132
                'hoster',
133
                help='Use the hoster.',
134
                lazy_registry=('breezy.plugins.propose.propose', 'hosters')),
0.431.5 by Jelmer Vernooij
Initial work on gitlab support.
135
            ListOption('reviewers', short_name='R', type=text_type,
0.431.54 by Jelmer Vernooij
Include commit data in 'brz propose'.
136
                       help='Requested reviewers.'),
0.432.7 by Jelmer Vernooij
propose works \o/
137
            Option('name', help='Name of the new remote branch.', type=str),
0.432.10 by Jelmer Vernooij
More test fixes.
138
            Option('description', help='Description of the change.', type=str),
0.431.13 by Jelmer Vernooij
Add support for labels on merge proposals.
139
            ListOption('labels', short_name='l', type=text_type,
0.431.54 by Jelmer Vernooij
Include commit data in 'brz propose'.
140
                       help='Labels to apply.'),
141
            Option('no-allow-lossy',
142
                   help='Allow fallback to lossy push, if necessary.'),
0.431.5 by Jelmer Vernooij
Initial work on gitlab support.
143
            ]
0.431.1 by Jelmer Vernooij
Start work on propose command.
144
    takes_args = ['submit_branch?']
145
146
    aliases = ['propose']
147
0.431.54 by Jelmer Vernooij
Include commit data in 'brz propose'.
148
    def run(self, submit_branch=None, directory='.', hoster=None,
149
            reviewers=None, name=None, no_allow_lossy=False, description=None,
150
            labels=None):
151
        tree, branch, relpath = (
152
            controldir.ControlDir.open_containing_tree_or_branch(directory))
0.431.1 by Jelmer Vernooij
Start work on propose command.
153
        if submit_branch is None:
154
            submit_branch = branch.get_submit_branch()
155
        if submit_branch is None:
0.432.7 by Jelmer Vernooij
propose works \o/
156
            submit_branch = branch.get_parent()
157
        if submit_branch is None:
0.431.54 by Jelmer Vernooij
Include commit data in 'brz propose'.
158
            raise errors.BzrCommandError(
159
                gettext("No target location specified or remembered"))
0.431.1 by Jelmer Vernooij
Start work on propose command.
160
        else:
161
            target = _mod_branch.Branch.open(submit_branch)
0.432.7 by Jelmer Vernooij
propose works \o/
162
        if hoster is None:
163
            hoster = _mod_propose.get_hoster(target)
0.431.5 by Jelmer Vernooij
Initial work on gitlab support.
164
        else:
0.432.7 by Jelmer Vernooij
propose works \o/
165
            hoster = hoster.probe(target)
166
        if name is None:
167
            name = branch_name(branch)
0.431.20 by Jelmer Vernooij
publish -> publish_derived.
168
        remote_branch, public_branch_url = hoster.publish_derived(
0.431.51 by Jelmer Vernooij
Allow fallback to lossy by default.
169
                branch, target, name=name, allow_lossy=not no_allow_lossy)
0.431.37 by Jelmer Vernooij
add a find-merge-proposal command.
170
        branch.set_push_location(remote_branch.user_url)
0.432.7 by Jelmer Vernooij
propose works \o/
171
        note(gettext('Published branch to %s') % public_branch_url)
172
        proposal_builder = hoster.get_proposer(remote_branch, target)
0.432.10 by Jelmer Vernooij
More test fixes.
173
        if description is None:
174
            body = proposal_builder.get_initial_body()
175
            info = proposal_builder.get_infotext()
0.431.55 by Jelmer Vernooij
Cope with lossy pushes better in `brz propose` texts.
176
            info += "\n\n" + summarize_unmerged(branch, remote_branch, target)
0.431.54 by Jelmer Vernooij
Include commit data in 'brz propose'.
177
            description = msgeditor.edit_commit_message(
178
                info, start_message=body)
0.431.2 by Jelmer Vernooij
Add launchpad implementation.
179
        try:
0.432.7 by Jelmer Vernooij
propose works \o/
180
            proposal = proposal_builder.create_proposal(
0.431.13 by Jelmer Vernooij
Add support for labels on merge proposals.
181
                description=description, reviewers=reviewers, labels=labels)
0.431.2 by Jelmer Vernooij
Add launchpad implementation.
182
        except _mod_propose.MergeProposalExists as e:
183
            raise errors.BzrCommandError(gettext(
184
                'There is already a branch merge proposal: %s') % e.url)
0.432.10 by Jelmer Vernooij
More test fixes.
185
        note(gettext('Merge proposal created: %s') % proposal.url)
0.431.37 by Jelmer Vernooij
add a find-merge-proposal command.
186
187
188
class cmd_find_merge_proposal(Command):
189
    __doc__ = """Find a merge proposal.
190
191
    """
192
193
    takes_options = ['directory']
194
    takes_args = ['submit_branch?']
195
    aliases = ['find-proposal']
196
197
    def run(self, directory='.', submit_branch=None):
198
        tree, branch, relpath = controldir.ControlDir.open_containing_tree_or_branch(
199
            directory)
200
        public_location = branch.get_public_branch()
201
        if public_location:
202
            branch = _mod_branch.Branch.open(public_location)
203
        if submit_branch is None:
204
            submit_branch = branch.get_submit_branch()
205
        if submit_branch is None:
206
            submit_branch = branch.get_parent()
207
        if submit_branch is None:
0.431.55 by Jelmer Vernooij
Cope with lossy pushes better in `brz propose` texts.
208
            raise errors.BzrCommandError(
209
                gettext("No target location specified or remembered"))
0.431.37 by Jelmer Vernooij
add a find-merge-proposal command.
210
        else:
211
            target = _mod_branch.Branch.open(submit_branch)
212
        hoster = _mod_propose.get_hoster(branch)
213
        mp = hoster.get_proposal(branch, target)
214
        self.outf.write(gettext('Merge proposal: %s\n') % mp.url)
0.431.47 by Jelmer Vernooij
Add github login command.
215
216
217
class cmd_github_login(Command):
218
    __doc__ = """Log into GitHub.
219
220
    """
221
222
    takes_args = ['username?']
223
224
    def run(self, username=None):
225
        from github import Github, GithubException
226
        from breezy.config import AuthenticationConfig
227
        authconfig = AuthenticationConfig()
228
        if username is None:
229
            username = authconfig.get_user(
0.431.48 by Jelmer Vernooij
Python3 compat.
230
                    'https', 'github.com', prompt=u'GitHub username', ask=True)
0.431.47 by Jelmer Vernooij
Add github login command.
231
        password = authconfig.get_password('https', 'github.com', username)
232
        client = Github(username, password)
233
        user = client.get_user()
234
        try:
235
            authorization = user.create_authorization(
236
                    scopes=['user', 'repo', 'delete_repo'], note='Breezy',
237
                    note_url='https://github.com/breezy-team/breezy')
238
        except GithubException as e:
0.431.49 by Jelmer Vernooij
Store GitHub tokens in a magic file, for now.
239
            errs = e.data.get('errors', [])
240
            if errs:
241
                err_code = errs[0].get('code')
242
                if err_code == u'already_exists':
243
                    raise errors.BzrCommandError('token already exists')
0.431.47 by Jelmer Vernooij
Add github login command.
244
            raise errors.BzrCommandError(e.data['message'])
0.431.49 by Jelmer Vernooij
Store GitHub tokens in a magic file, for now.
245
        # TODO(jelmer): This should really use something in
246
        # AuthenticationConfig
247
        from .github import store_github_token
248
        store_github_token(scheme='https', host='github.com',
249
                           token=authorization.token)