73
74
return description.splitlines()[0]
77
class ValidationFailed(errors.BzrError):
79
_fmt = "GitHub validation failed: %(error)s"
81
def __init__(self, error):
82
errors.BzrError.__init__(self)
76
86
class NotGitHubUrl(errors.BzrError):
78
88
_fmt = "Not a GitHub URL: %(url)s"
139
152
def _patch(self, data):
140
153
response = self._gh._api_request(
141
154
'PATCH', self._pr['url'], body=json.dumps(data).encode('utf-8'))
155
if response.status == 422:
156
raise ValidationFailed(json.loads(response.text))
142
157
if response.status != 200:
143
158
raise InvalidHttpResponse(self._pr['url'], response.text)
144
159
self._pr = json.loads(response.text)
152
167
def is_merged(self):
153
return self._pr['state'] == 'merged'
168
return bool(self._pr.get('merged_at'))
171
return self._pr['state'] == 'closed' and not bool(self._pr.get('merged_at'))
175
self._patch({'state': 'open'})
176
except ValidationFailed as e:
177
raise ReopenFailed(e.error['errors'][0]['message'])
156
180
self._patch({'state': 'closed'})
234
258
return json.loads(response.text)
235
259
raise InvalidHttpResponse(path, response.text)
261
def _create_pull(self, path, title, head, base, body=None):
262
path = 'repos/' + path + '/pulls'
271
response = self._api_request(
272
'POST', path, body=json.dumps(data).encode('utf-8'))
273
if response.status != 201:
274
raise InvalidHttpResponse(path, response.text)
275
return json.loads(response.text)
277
def _get_user_by_email(self, email):
278
path = 'search/users?q=%s+in:email' % email
279
response = self._api_request('GET', path)
280
if response.status != 200:
281
raise InvalidHttpResponse(path, response.text)
282
ret = json.loads(response.text)
283
if ret['total_count'] == 0:
284
raise KeyError('no user with email %s' % email)
285
elif ret['total_count'] > 1:
286
raise ValueError('more than one result for email %s' % email)
287
return ret['items'][0]
237
289
def _get_user(self, username=None):
239
291
path = 'users/:%s' % username
447
499
# TODO(jelmer): Probe for right repo name
448
500
if self.target_repo_name.endswith('.git'):
449
501
self.target_repo_name = self.target_repo_name[:-4]
450
target_repo = self.gh._get_repo("%s/%s" % (self.target_owner, self.target_repo_name))
451
502
# TODO(jelmer): Allow setting title explicitly?
452
503
title = determine_title(description)
453
# TOOD(jelmer): Set maintainers_can_modify?
504
# TODO(jelmer): Set maintainers_can_modify?
455
pull_request = target_repo.create_pull(
506
pull_request = self.gh._create_pull(
507
"%s/%s" % (self.target_owner, self.target_repo_name),
456
508
title=title, body=description,
457
509
head="%s:%s" % (self.source_owner, self.source_branch_name),
458
510
base=self.target_branch_name)
459
except github.GithubException as e:
461
raise MergeProposalExists(self.source_branch.user_url)
511
except ValidationFailed:
512
raise MergeProposalExists(self.source_branch.user_url)
464
514
for reviewer in reviewers:
465
pull_request.assignees.append(
466
self.gh._get_user(reviewer)['login'])
516
user = self.gh._get_user_by_email(reviewer)
518
user = self.gh._get_user(reviewer)
519
pull_request.assignees.append(user['login'])
468
521
for label in labels:
469
522
pull_request.issue.labels.append(label)