Skip to content

Commit da25174

Browse files
committed
🚧 Updates Github/Gitlab request create
* fixed from project vs onto project handling * proper support of argumentless call * more information about what's going on * better determinism
1 parent 5f92f4c commit da25174

File tree

3 files changed

+109
-49
lines changed

3 files changed

+109
-49
lines changed

git_repo/repo.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -376,13 +376,13 @@ def do_request_list(self):
376376

377377
@register_action('request', 'create')
378378
def do_request_create(self):
379-
def request_edition(repository, from_branch):
379+
def request_edition(repository, from_branch, onto_target):
380380
try:
381381
commit = repository.commit(from_branch)
382382
title, *body = commit.message.split('\n')
383383
except BadName:
384384
log.error('Couldn\'t find local source branch {}'.format(from_branch))
385-
return None
385+
return None, None
386386
from tempfile import NamedTemporaryFile
387387
from subprocess import call
388388
with NamedTemporaryFile(
@@ -399,9 +399,13 @@ def request_edition(repository, from_branch):
399399
'## Filled with commit:\n'
400400
'## {}\n'
401401
'####################################################\n'
402+
'## To be applied:\n'
403+
'## from branch: {}\n'
404+
'## onto project: {}\n'
405+
'####################################################\n'
402406
'## * All lines starting with # will be ignored.\n'
403407
'## * First non-ignored line is the title of the request.\n'
404-
).format(title, '\n'.join(body), commit.name_rev).encode('utf-8'))
408+
).format(title, '\n'.join(body), commit.name_rev, from_branch, onto_target).encode('utf-8'))
405409
request_file.flush()
406410
rv = call("{} {}".format(os.environ['EDITOR'], request_file.name), shell=True)
407411
if rv != 0:
@@ -428,10 +432,7 @@ def request_edition(repository, from_branch):
428432
self.message,
429433
self._auto_slug,
430434
request_edition)
431-
log.info('Successfully created request of `{local}` onto `{}:{remote}`, with id `{ref}`!'.format(
432-
'/'.join([self.user_name, self.repo_name]),
433-
**new_request)
434-
)
435+
log.info('Successfully created request of `{local}` onto `{project}:{remote}`, with id `{ref}`!'.format(**new_request))
435436
if 'url' in new_request:
436437
log.info('available at: {url}'.format(**new_request))
437438
return 0

git_repo/services/ext/github.py

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -221,41 +221,65 @@ def gist_delete(self, gist_id):
221221
raise ResourceNotFoundError('Could not find gist')
222222
gist.delete()
223223

224-
def request_create(self, user, repo, from_branch, onto_branch, title=None, description=None, auto_slug=False, edit=None):
225-
repository = self.gh.repository(user, repo)
226-
if not repository:
227-
raise ResourceNotFoundError('Could not find repository `{}/{}`!'.format(user, repo))
224+
def request_create(self, onto_user, onto_repo, from_branch, onto_branch, title=None, description=None, auto_slug=False, edit=None):
225+
onto_project = self.gh.repository(onto_user, onto_repo)
226+
227+
if not onto_project:
228+
raise ResourceNotFoundError('Could not find project `{}/{}`!'.format(onto_user, onto_repo))
229+
230+
from_reposlug = self.guess_repo_slug(self.repository, self)
231+
if from_reposlug:
232+
from_user, from_repo = from_reposlug.split('/')
233+
if (onto_user, onto_repo) == (from_user, from_repo):
234+
from_project = onto_project
235+
else:
236+
from_project = self.gh.repository(from_user, from_repo)
237+
else:
238+
from_project = None
239+
240+
if not from_project:
241+
raise ResourceNotFoundError('Could not find project `{}`!'.format(from_user, from_repo))
242+
228243
# when no repo slug has been given to `git-repo X request create`
229-
if auto_slug:
230-
# then chances are current repository is a fork of the target
231-
# repository we want to push to
232-
if repository.fork:
233-
user = repository.parent.owner.login
234-
repo = repository.parent.name
235-
from_branch = from_branch or repository.parent.default_branch
244+
# then chances are current project is a fork of the target
245+
# project we want to push to
246+
if auto_slug and onto_project.fork:
247+
onto_user = onto_project.parent.owner.login
248+
onto_repo = onto_project.parent.name
249+
onto_project = self.gh.repository(onto_user, onto_repo)
250+
236251
# if no onto branch has been defined, take the default one
237252
# with a fallback on master
238253
if not from_branch:
239254
from_branch = self.repository.active_branch.name
240255
# if no from branch has been defined, chances are we want to push
241256
# the branch we're currently working on
242257
if not onto_branch:
243-
onto_branch = repository.default_branch or 'master'
258+
onto_branch = onto_project.default_branch or 'master'
244259

245-
from_ref = self._extracts_ref(user, from_branch)
246-
if user != repository.owner.login:
247-
from_branch = ':'.join([user, from_branch])
260+
from_target = '{}:{}'.format(from_user, from_branch)
261+
onto_target = '{}/{}:{}'.format(onto_user, onto_project, onto_branch)
248262

249263
# translate from github username to git remote name
250264
if not title and not description and edit:
251-
title, description = edit(self.repository, from_ref)
265+
title, description = edit(self.repository, from_branch, onto_target)
252266
if not title and not description:
253267
raise ArgumentError('Missing message for request creation')
268+
254269
try:
255-
request = repository.create_pull(title,
270+
request = onto_project.create_pull(title,
271+
head=from_target,
256272
base=onto_branch,
257-
head=from_branch,
258273
body=description)
274+
275+
return {
276+
'local': from_branch,
277+
'project': '/'.join([onto_user, onto_repo]),
278+
'remote': onto_branch,
279+
'ref': request.number,
280+
'url': request.html_url
281+
}
282+
259283
except github3.models.GitHubError as err:
260284
if err.code == 422:
261285
if err.message == 'Validation Failed':
@@ -272,9 +296,6 @@ def request_create(self, user, repo, from_branch, onto_branch, title=None, descr
272296
raise ResourceError("Unhandled formatting error: {}".format(err.errors))
273297
raise ResourceError(err.message)
274298

275-
return {'local': from_branch, 'remote': onto_branch, 'ref': request.number,
276-
'url': request.html_url}
277-
278299
def request_list(self, user, repo):
279300
repository = self.gh.repository(user, repo)
280301
yield "{}\t{:<60}\t{}"

git_repo/services/ext/gitlab.py

Lines changed: 59 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -257,37 +257,75 @@ def gist_delete(self, snippet):
257257

258258
return snippet.delete()
259259

260-
def request_create(self, user, repo, local_branch, remote_branch, title, description=None, auto_slug=False):
260+
def request_create(self, onto_user, onto_repo, from_branch, onto_branch, title=None, description=None, auto_slug=False, edit=None):
261261
try:
262-
repository = self.gl.projects.get('/'.join([user, repo]))
263-
if not repository:
264-
raise ResourceNotFoundError('Could not find repository `{}/{}`!'.format(user, repo))
262+
onto_project = self.gl.projects.get('/'.join([onto_user, onto_repo]))
263+
264+
if not onto_project:
265+
raise ResourceNotFoundError('Could not find project `{}/{}`!'.format(onto_user, onto_repo))
266+
267+
from_reposlug = self.guess_repo_slug(self.repository, self)
268+
if from_reposlug:
269+
from_user, from_repo = from_reposlug.split('/')
270+
if (onto_user, onto_repo) == (from_user, from_repo):
271+
from_project = onto_project
272+
else:
273+
from_project = self.gl.projects.get('/'.join([from_user, from_repo]))
274+
else:
275+
from_project = None
276+
277+
if not from_project:
278+
raise ResourceNotFoundError('Could not find project `{}/{}`!'.format(from_user, from_repo))
279+
280+
# when no repo slug has been given to `git-repo X request create`
281+
# then chances are current project is a fork of the target
282+
# project we want to push to
283+
if auto_slug and 'forked_from_project' in onto_project.as_dict():
284+
parent = self.gl.projects.get(onto_project.forked_from_project['id'])
285+
onto_user, onto_repo = parent.namespace.path, parent.path
286+
onto_project = self.gl.projects.get('/'.join([onto_user, onto_repo]))
287+
288+
# if no onto branch has been defined, take the default one
289+
# with a fallback on master
290+
if not from_branch:
291+
from_branch = self.repository.active_branch.name
292+
# if no from branch has been defined, chances are we want to push
293+
# the branch we're currently working on
294+
if not onto_branch:
295+
onto_branch = onto_project.default_branch or 'master'
296+
297+
onto_target = '{}/{}:{}'.format(onto_user, onto_project.name, onto_branch)
298+
299+
# translate from gitlab username to git remote name
265300
if not title and not description and edit:
266-
title, description = edit(repository, from_branch)
301+
title, description = edit(self.repository, from_branch, onto_target)
267302
if not title and not description:
268303
raise ArgumentError('Missing message for request creation')
269-
if not local_branch:
270-
remote_branch = self.repository.active_branch.name or self.repository.active_branch.name
271-
if not remote_branch:
272-
local_branch = repository.master_branch or 'master'
304+
273305
request = self.gl.project_mergerequests.create(
274-
project_id=repository.id,
275-
data= {
276-
'source_branch':local_branch,
277-
'target_branch':remote_branch,
278-
'title':title,
279-
'description':description
280-
}
281-
)
306+
project_id=from_project.id,
307+
data={
308+
'source_branch': from_branch,
309+
'target_branch': onto_branch,
310+
'target_project_id': onto_project.id,
311+
'title': title,
312+
'description': description
313+
}
314+
)
315+
316+
return {
317+
'local': from_branch,
318+
'project': '/'.join([onto_user, onto_repo]),
319+
'remote': onto_branch,
320+
'url': request.web_url,
321+
'ref': request.iid
322+
}
323+
282324
except GitlabGetError as err:
283325
raise ResourceNotFoundError(err) from err
284326
except Exception as err:
285327
raise ResourceError("Unhandled error: {}".format(err)) from err
286328

287-
return {'local': local_branch,
288-
'remote': remote_branch,
289-
'ref': request.iid}
290-
291329
def request_list(self, user, repo):
292330
project = self.gl.projects.get('/'.join([user, repo]))
293331
yield "{:>3}\t{:<60}\t{:2}"

0 commit comments

Comments
 (0)