##// END OF EJS Templates
api: Include merge reference into API data of a PR.
Martin Bornhold -
r1054:122c7b13 default
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,666 +1,678 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2011-2016 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21
22 22 import logging
23 23
24 24 from rhodecode.api import jsonrpc_method, JSONRPCError
25 25 from rhodecode.api.utils import (
26 26 has_superadmin_permission, Optional, OAttr, get_repo_or_error,
27 27 get_pull_request_or_error, get_commit_or_error, get_user_or_error,
28 28 has_repo_permissions, resolve_ref_or_error)
29 29 from rhodecode.lib.auth import (HasRepoPermissionAnyApi)
30 30 from rhodecode.lib.base import vcs_operation_context
31 31 from rhodecode.lib.utils2 import str2bool
32 32 from rhodecode.model.changeset_status import ChangesetStatusModel
33 33 from rhodecode.model.comment import ChangesetCommentsModel
34 34 from rhodecode.model.db import Session, ChangesetStatus
35 35 from rhodecode.model.pull_request import PullRequestModel
36 36 from rhodecode.model.settings import SettingsModel
37 37
38 38 log = logging.getLogger(__name__)
39 39
40 40
41 41 @jsonrpc_method()
42 42 def get_pull_request(request, apiuser, repoid, pullrequestid):
43 43 """
44 44 Get a pull request based on the given ID.
45 45
46 46 :param apiuser: This is filled automatically from the |authtoken|.
47 47 :type apiuser: AuthUser
48 48 :param repoid: Repository name or repository ID from where the pull
49 49 request was opened.
50 50 :type repoid: str or int
51 51 :param pullrequestid: ID of the requested pull request.
52 52 :type pullrequestid: int
53 53
54 54 Example output:
55 55
56 56 .. code-block:: bash
57 57
58 58 "id": <id_given_in_input>,
59 59 "result":
60 60 {
61 61 "pull_request_id": "<pull_request_id>",
62 62 "url": "<url>",
63 63 "title": "<title>",
64 64 "description": "<description>",
65 65 "status" : "<status>",
66 66 "created_on": "<date_time_created>",
67 67 "updated_on": "<date_time_updated>",
68 68 "commit_ids": [
69 69 ...
70 70 "<commit_id>",
71 71 "<commit_id>",
72 72 ...
73 73 ],
74 74 "review_status": "<review_status>",
75 75 "mergeable": {
76 76 "status": "<bool>",
77 77 "message": "<message>",
78 78 },
79 79 "source": {
80 80 "clone_url": "<clone_url>",
81 81 "repository": "<repository_name>",
82 82 "reference":
83 83 {
84 84 "name": "<name>",
85 85 "type": "<type>",
86 86 "commit_id": "<commit_id>",
87 87 }
88 88 },
89 89 "target": {
90 90 "clone_url": "<clone_url>",
91 91 "repository": "<repository_name>",
92 92 "reference":
93 93 {
94 94 "name": "<name>",
95 95 "type": "<type>",
96 96 "commit_id": "<commit_id>",
97 97 }
98 98 },
99 "shadow": {
99 "merge": {
100 100 "clone_url": "<clone_url>",
101 "reference":
102 {
103 "name": "<name>",
104 "type": "<type>",
105 "commit_id": "<commit_id>",
106 }
101 107 },
102 108 "author": <user_obj>,
103 109 "reviewers": [
104 110 ...
105 111 {
106 112 "user": "<user_obj>",
107 113 "review_status": "<review_status>",
108 114 }
109 115 ...
110 116 ]
111 117 },
112 118 "error": null
113 119 """
114 120 get_repo_or_error(repoid)
115 121 pull_request = get_pull_request_or_error(pullrequestid)
116 122 if not PullRequestModel().check_user_read(
117 123 pull_request, apiuser, api=True):
118 124 raise JSONRPCError('repository `%s` does not exist' % (repoid,))
119 125 data = pull_request.get_api_data()
120 126 return data
121 127
122 128
123 129 @jsonrpc_method()
124 130 def get_pull_requests(request, apiuser, repoid, status=Optional('new')):
125 131 """
126 132 Get all pull requests from the repository specified in `repoid`.
127 133
128 134 :param apiuser: This is filled automatically from the |authtoken|.
129 135 :type apiuser: AuthUser
130 136 :param repoid: Repository name or repository ID.
131 137 :type repoid: str or int
132 138 :param status: Only return pull requests with the specified status.
133 139 Valid options are.
134 140 * ``new`` (default)
135 141 * ``open``
136 142 * ``closed``
137 143 :type status: str
138 144
139 145 Example output:
140 146
141 147 .. code-block:: bash
142 148
143 149 "id": <id_given_in_input>,
144 150 "result":
145 151 [
146 152 ...
147 153 {
148 154 "pull_request_id": "<pull_request_id>",
149 155 "url": "<url>",
150 156 "title" : "<title>",
151 157 "description": "<description>",
152 158 "status": "<status>",
153 159 "created_on": "<date_time_created>",
154 160 "updated_on": "<date_time_updated>",
155 161 "commit_ids": [
156 162 ...
157 163 "<commit_id>",
158 164 "<commit_id>",
159 165 ...
160 166 ],
161 167 "review_status": "<review_status>",
162 168 "mergeable": {
163 169 "status": "<bool>",
164 170 "message: "<message>",
165 171 },
166 172 "source": {
167 173 "clone_url": "<clone_url>",
168 174 "reference":
169 175 {
170 176 "name": "<name>",
171 177 "type": "<type>",
172 178 "commit_id": "<commit_id>",
173 179 }
174 180 },
175 181 "target": {
176 182 "clone_url": "<clone_url>",
177 183 "reference":
178 184 {
179 185 "name": "<name>",
180 186 "type": "<type>",
181 187 "commit_id": "<commit_id>",
182 188 }
183 189 },
184 "shadow": {
190 "merge": {
185 191 "clone_url": "<clone_url>",
192 "reference":
193 {
194 "name": "<name>",
195 "type": "<type>",
196 "commit_id": "<commit_id>",
197 }
186 198 },
187 199 "author": <user_obj>,
188 200 "reviewers": [
189 201 ...
190 202 {
191 203 "user": "<user_obj>",
192 204 "review_status": "<review_status>",
193 205 }
194 206 ...
195 207 ]
196 208 }
197 209 ...
198 210 ],
199 211 "error": null
200 212
201 213 """
202 214 repo = get_repo_or_error(repoid)
203 215 if not has_superadmin_permission(apiuser):
204 216 _perms = (
205 217 'repository.admin', 'repository.write', 'repository.read',)
206 218 has_repo_permissions(apiuser, repoid, repo, _perms)
207 219
208 220 status = Optional.extract(status)
209 221 pull_requests = PullRequestModel().get_all(repo, statuses=[status])
210 222 data = [pr.get_api_data() for pr in pull_requests]
211 223 return data
212 224
213 225
214 226 @jsonrpc_method()
215 227 def merge_pull_request(request, apiuser, repoid, pullrequestid,
216 228 userid=Optional(OAttr('apiuser'))):
217 229 """
218 230 Merge the pull request specified by `pullrequestid` into its target
219 231 repository.
220 232
221 233 :param apiuser: This is filled automatically from the |authtoken|.
222 234 :type apiuser: AuthUser
223 235 :param repoid: The Repository name or repository ID of the
224 236 target repository to which the |pr| is to be merged.
225 237 :type repoid: str or int
226 238 :param pullrequestid: ID of the pull request which shall be merged.
227 239 :type pullrequestid: int
228 240 :param userid: Merge the pull request as this user.
229 241 :type userid: Optional(str or int)
230 242
231 243 Example output:
232 244
233 245 .. code-block:: bash
234 246
235 247 "id": <id_given_in_input>,
236 248 "result":
237 249 {
238 250 "executed": "<bool>",
239 251 "failure_reason": "<int>",
240 252 "merge_commit_id": "<merge_commit_id>",
241 253 "possible": "<bool>"
242 254 },
243 255 "error": null
244 256
245 257 """
246 258 repo = get_repo_or_error(repoid)
247 259 if not isinstance(userid, Optional):
248 260 if (has_superadmin_permission(apiuser) or
249 261 HasRepoPermissionAnyApi('repository.admin')(
250 262 user=apiuser, repo_name=repo.repo_name)):
251 263 apiuser = get_user_or_error(userid)
252 264 else:
253 265 raise JSONRPCError('userid is not the same as your user')
254 266
255 267 pull_request = get_pull_request_or_error(pullrequestid)
256 268 if not PullRequestModel().check_user_merge(
257 269 pull_request, apiuser, api=True):
258 270 raise JSONRPCError('repository `%s` does not exist' % (repoid,))
259 271 if pull_request.is_closed():
260 272 raise JSONRPCError(
261 273 'pull request `%s` merge failed, pull request is closed' % (
262 274 pullrequestid,))
263 275
264 276 target_repo = pull_request.target_repo
265 277 extras = vcs_operation_context(
266 278 request.environ, repo_name=target_repo.repo_name,
267 279 username=apiuser.username, action='push',
268 280 scm=target_repo.repo_type)
269 281 data = PullRequestModel().merge(pull_request, apiuser, extras=extras)
270 282 if data.executed:
271 283 PullRequestModel().close_pull_request(
272 284 pull_request.pull_request_id, apiuser)
273 285
274 286 Session().commit()
275 287 return data
276 288
277 289
278 290 @jsonrpc_method()
279 291 def close_pull_request(request, apiuser, repoid, pullrequestid,
280 292 userid=Optional(OAttr('apiuser'))):
281 293 """
282 294 Close the pull request specified by `pullrequestid`.
283 295
284 296 :param apiuser: This is filled automatically from the |authtoken|.
285 297 :type apiuser: AuthUser
286 298 :param repoid: Repository name or repository ID to which the pull
287 299 request belongs.
288 300 :type repoid: str or int
289 301 :param pullrequestid: ID of the pull request to be closed.
290 302 :type pullrequestid: int
291 303 :param userid: Close the pull request as this user.
292 304 :type userid: Optional(str or int)
293 305
294 306 Example output:
295 307
296 308 .. code-block:: bash
297 309
298 310 "id": <id_given_in_input>,
299 311 "result":
300 312 {
301 313 "pull_request_id": "<int>",
302 314 "closed": "<bool>"
303 315 },
304 316 "error": null
305 317
306 318 """
307 319 repo = get_repo_or_error(repoid)
308 320 if not isinstance(userid, Optional):
309 321 if (has_superadmin_permission(apiuser) or
310 322 HasRepoPermissionAnyApi('repository.admin')(
311 323 user=apiuser, repo_name=repo.repo_name)):
312 324 apiuser = get_user_or_error(userid)
313 325 else:
314 326 raise JSONRPCError('userid is not the same as your user')
315 327
316 328 pull_request = get_pull_request_or_error(pullrequestid)
317 329 if not PullRequestModel().check_user_update(
318 330 pull_request, apiuser, api=True):
319 331 raise JSONRPCError(
320 332 'pull request `%s` close failed, no permission to close.' % (
321 333 pullrequestid,))
322 334 if pull_request.is_closed():
323 335 raise JSONRPCError(
324 336 'pull request `%s` is already closed' % (pullrequestid,))
325 337
326 338 PullRequestModel().close_pull_request(
327 339 pull_request.pull_request_id, apiuser)
328 340 Session().commit()
329 341 data = {
330 342 'pull_request_id': pull_request.pull_request_id,
331 343 'closed': True,
332 344 }
333 345 return data
334 346
335 347
336 348 @jsonrpc_method()
337 349 def comment_pull_request(request, apiuser, repoid, pullrequestid,
338 350 message=Optional(None), status=Optional(None),
339 351 userid=Optional(OAttr('apiuser'))):
340 352 """
341 353 Comment on the pull request specified with the `pullrequestid`,
342 354 in the |repo| specified by the `repoid`, and optionally change the
343 355 review status.
344 356
345 357 :param apiuser: This is filled automatically from the |authtoken|.
346 358 :type apiuser: AuthUser
347 359 :param repoid: The repository name or repository ID.
348 360 :type repoid: str or int
349 361 :param pullrequestid: The pull request ID.
350 362 :type pullrequestid: int
351 363 :param message: The text content of the comment.
352 364 :type message: str
353 365 :param status: (**Optional**) Set the approval status of the pull
354 366 request. Valid options are:
355 367 * not_reviewed
356 368 * approved
357 369 * rejected
358 370 * under_review
359 371 :type status: str
360 372 :param userid: Comment on the pull request as this user
361 373 :type userid: Optional(str or int)
362 374
363 375 Example output:
364 376
365 377 .. code-block:: bash
366 378
367 379 id : <id_given_in_input>
368 380 result :
369 381 {
370 382 "pull_request_id": "<Integer>",
371 383 "comment_id": "<Integer>"
372 384 }
373 385 error : null
374 386 """
375 387 repo = get_repo_or_error(repoid)
376 388 if not isinstance(userid, Optional):
377 389 if (has_superadmin_permission(apiuser) or
378 390 HasRepoPermissionAnyApi('repository.admin')(
379 391 user=apiuser, repo_name=repo.repo_name)):
380 392 apiuser = get_user_or_error(userid)
381 393 else:
382 394 raise JSONRPCError('userid is not the same as your user')
383 395
384 396 pull_request = get_pull_request_or_error(pullrequestid)
385 397 if not PullRequestModel().check_user_read(
386 398 pull_request, apiuser, api=True):
387 399 raise JSONRPCError('repository `%s` does not exist' % (repoid,))
388 400 message = Optional.extract(message)
389 401 status = Optional.extract(status)
390 402 if not message and not status:
391 403 raise JSONRPCError('message and status parameter missing')
392 404
393 405 if (status not in (st[0] for st in ChangesetStatus.STATUSES) and
394 406 status is not None):
395 407 raise JSONRPCError('unknown comment status`%s`' % status)
396 408
397 409 allowed_to_change_status = PullRequestModel().check_user_change_status(
398 410 pull_request, apiuser)
399 411 text = message
400 412 if status and allowed_to_change_status:
401 413 st_message = (('Status change %(transition_icon)s %(status)s')
402 414 % {'transition_icon': '>',
403 415 'status': ChangesetStatus.get_status_lbl(status)})
404 416 text = message or st_message
405 417
406 418 rc_config = SettingsModel().get_all_settings()
407 419 renderer = rc_config.get('rhodecode_markup_renderer', 'rst')
408 420 comment = ChangesetCommentsModel().create(
409 421 text=text,
410 422 repo=pull_request.target_repo.repo_id,
411 423 user=apiuser.user_id,
412 424 pull_request=pull_request.pull_request_id,
413 425 f_path=None,
414 426 line_no=None,
415 427 status_change=(ChangesetStatus.get_status_lbl(status)
416 428 if status and allowed_to_change_status else None),
417 429 status_change_type=(status
418 430 if status and allowed_to_change_status else None),
419 431 closing_pr=False,
420 432 renderer=renderer
421 433 )
422 434
423 435 if allowed_to_change_status and status:
424 436 ChangesetStatusModel().set_status(
425 437 pull_request.target_repo.repo_id,
426 438 status,
427 439 apiuser.user_id,
428 440 comment,
429 441 pull_request=pull_request.pull_request_id
430 442 )
431 443 Session().flush()
432 444
433 445 Session().commit()
434 446 data = {
435 447 'pull_request_id': pull_request.pull_request_id,
436 448 'comment_id': comment.comment_id,
437 449 'status': status
438 450 }
439 451 return data
440 452
441 453
442 454 @jsonrpc_method()
443 455 def create_pull_request(
444 456 request, apiuser, source_repo, target_repo, source_ref, target_ref,
445 457 title, description=Optional(''), reviewers=Optional(None)):
446 458 """
447 459 Creates a new pull request.
448 460
449 461 Accepts refs in the following formats:
450 462
451 463 * branch:<branch_name>:<sha>
452 464 * branch:<branch_name>
453 465 * bookmark:<bookmark_name>:<sha> (Mercurial only)
454 466 * bookmark:<bookmark_name> (Mercurial only)
455 467
456 468 :param apiuser: This is filled automatically from the |authtoken|.
457 469 :type apiuser: AuthUser
458 470 :param source_repo: Set the source repository name.
459 471 :type source_repo: str
460 472 :param target_repo: Set the target repository name.
461 473 :type target_repo: str
462 474 :param source_ref: Set the source ref name.
463 475 :type source_ref: str
464 476 :param target_ref: Set the target ref name.
465 477 :type target_ref: str
466 478 :param title: Set the pull request title.
467 479 :type title: str
468 480 :param description: Set the pull request description.
469 481 :type description: Optional(str)
470 482 :param reviewers: Set the new pull request reviewers list.
471 483 :type reviewers: Optional(list)
472 484 Accepts username strings or objects of the format:
473 485 {
474 486 'username': 'nick', 'reasons': ['original author']
475 487 }
476 488 """
477 489
478 490 source = get_repo_or_error(source_repo)
479 491 target = get_repo_or_error(target_repo)
480 492 if not has_superadmin_permission(apiuser):
481 493 _perms = ('repository.admin', 'repository.write', 'repository.read',)
482 494 has_repo_permissions(apiuser, source_repo, source, _perms)
483 495
484 496 full_source_ref = resolve_ref_or_error(source_ref, source)
485 497 full_target_ref = resolve_ref_or_error(target_ref, target)
486 498 source_commit = get_commit_or_error(full_source_ref, source)
487 499 target_commit = get_commit_or_error(full_target_ref, target)
488 500 source_scm = source.scm_instance()
489 501 target_scm = target.scm_instance()
490 502
491 503 commit_ranges = target_scm.compare(
492 504 target_commit.raw_id, source_commit.raw_id, source_scm,
493 505 merge=True, pre_load=[])
494 506
495 507 ancestor = target_scm.get_common_ancestor(
496 508 target_commit.raw_id, source_commit.raw_id, source_scm)
497 509
498 510 if not commit_ranges:
499 511 raise JSONRPCError('no commits found')
500 512
501 513 if not ancestor:
502 514 raise JSONRPCError('no common ancestor found')
503 515
504 516 reviewer_objects = Optional.extract(reviewers) or []
505 517 if not isinstance(reviewer_objects, list):
506 518 raise JSONRPCError('reviewers should be specified as a list')
507 519
508 520 reviewers_reasons = []
509 521 for reviewer_object in reviewer_objects:
510 522 reviewer_reasons = []
511 523 if isinstance(reviewer_object, (basestring, int)):
512 524 reviewer_username = reviewer_object
513 525 else:
514 526 reviewer_username = reviewer_object['username']
515 527 reviewer_reasons = reviewer_object.get('reasons', [])
516 528
517 529 user = get_user_or_error(reviewer_username)
518 530 reviewers_reasons.append((user.user_id, reviewer_reasons))
519 531
520 532 pull_request_model = PullRequestModel()
521 533 pull_request = pull_request_model.create(
522 534 created_by=apiuser.user_id,
523 535 source_repo=source_repo,
524 536 source_ref=full_source_ref,
525 537 target_repo=target_repo,
526 538 target_ref=full_target_ref,
527 539 revisions=reversed(
528 540 [commit.raw_id for commit in reversed(commit_ranges)]),
529 541 reviewers=reviewers_reasons,
530 542 title=title,
531 543 description=Optional.extract(description)
532 544 )
533 545
534 546 Session().commit()
535 547 data = {
536 548 'msg': 'Created new pull request `{}`'.format(title),
537 549 'pull_request_id': pull_request.pull_request_id,
538 550 }
539 551 return data
540 552
541 553
542 554 @jsonrpc_method()
543 555 def update_pull_request(
544 556 request, apiuser, repoid, pullrequestid, title=Optional(''),
545 557 description=Optional(''), reviewers=Optional(None),
546 558 update_commits=Optional(None), close_pull_request=Optional(None)):
547 559 """
548 560 Updates a pull request.
549 561
550 562 :param apiuser: This is filled automatically from the |authtoken|.
551 563 :type apiuser: AuthUser
552 564 :param repoid: The repository name or repository ID.
553 565 :type repoid: str or int
554 566 :param pullrequestid: The pull request ID.
555 567 :type pullrequestid: int
556 568 :param title: Set the pull request title.
557 569 :type title: str
558 570 :param description: Update pull request description.
559 571 :type description: Optional(str)
560 572 :param reviewers: Update pull request reviewers list with new value.
561 573 :type reviewers: Optional(list)
562 574 :param update_commits: Trigger update of commits for this pull request
563 575 :type: update_commits: Optional(bool)
564 576 :param close_pull_request: Close this pull request with rejected state
565 577 :type: close_pull_request: Optional(bool)
566 578
567 579 Example output:
568 580
569 581 .. code-block:: bash
570 582
571 583 id : <id_given_in_input>
572 584 result :
573 585 {
574 586 "msg": "Updated pull request `63`",
575 587 "pull_request": <pull_request_object>,
576 588 "updated_reviewers": {
577 589 "added": [
578 590 "username"
579 591 ],
580 592 "removed": []
581 593 },
582 594 "updated_commits": {
583 595 "added": [
584 596 "<sha1_hash>"
585 597 ],
586 598 "common": [
587 599 "<sha1_hash>",
588 600 "<sha1_hash>",
589 601 ],
590 602 "removed": []
591 603 }
592 604 }
593 605 error : null
594 606 """
595 607
596 608 repo = get_repo_or_error(repoid)
597 609 pull_request = get_pull_request_or_error(pullrequestid)
598 610 if not PullRequestModel().check_user_update(
599 611 pull_request, apiuser, api=True):
600 612 raise JSONRPCError(
601 613 'pull request `%s` update failed, no permission to update.' % (
602 614 pullrequestid,))
603 615 if pull_request.is_closed():
604 616 raise JSONRPCError(
605 617 'pull request `%s` update failed, pull request is closed' % (
606 618 pullrequestid,))
607 619
608 620 reviewer_objects = Optional.extract(reviewers) or []
609 621 if not isinstance(reviewer_objects, list):
610 622 raise JSONRPCError('reviewers should be specified as a list')
611 623
612 624 reviewers_reasons = []
613 625 reviewer_ids = set()
614 626 for reviewer_object in reviewer_objects:
615 627 reviewer_reasons = []
616 628 if isinstance(reviewer_object, (int, basestring)):
617 629 reviewer_username = reviewer_object
618 630 else:
619 631 reviewer_username = reviewer_object['username']
620 632 reviewer_reasons = reviewer_object.get('reasons', [])
621 633
622 634 user = get_user_or_error(reviewer_username)
623 635 reviewer_ids.add(user.user_id)
624 636 reviewers_reasons.append((user.user_id, reviewer_reasons))
625 637
626 638 title = Optional.extract(title)
627 639 description = Optional.extract(description)
628 640 if title or description:
629 641 PullRequestModel().edit(
630 642 pull_request, title or pull_request.title,
631 643 description or pull_request.description)
632 644 Session().commit()
633 645
634 646 commit_changes = {"added": [], "common": [], "removed": []}
635 647 if str2bool(Optional.extract(update_commits)):
636 648 if PullRequestModel().has_valid_update_type(pull_request):
637 649 _version, _commit_changes = PullRequestModel().update_commits(
638 650 pull_request)
639 651 commit_changes = _commit_changes or commit_changes
640 652 Session().commit()
641 653
642 654 reviewers_changes = {"added": [], "removed": []}
643 655 if reviewer_ids:
644 656 added_reviewers, removed_reviewers = \
645 657 PullRequestModel().update_reviewers(pull_request, reviewers_reasons)
646 658
647 659 reviewers_changes['added'] = sorted(
648 660 [get_user_or_error(n).username for n in added_reviewers])
649 661 reviewers_changes['removed'] = sorted(
650 662 [get_user_or_error(n).username for n in removed_reviewers])
651 663 Session().commit()
652 664
653 665 if str2bool(Optional.extract(close_pull_request)):
654 666 PullRequestModel().close_pull_request_with_comment(
655 667 pull_request, apiuser, repo)
656 668 Session().commit()
657 669
658 670 data = {
659 671 'msg': 'Updated pull request `{}`'.format(
660 672 pull_request.pull_request_id),
661 673 'pull_request': pull_request.get_api_data(),
662 674 'updated_commits': commit_changes,
663 675 'updated_reviewers': reviewers_changes
664 676 }
665 677 return data
666 678
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now