| 1 |
import logging |
| 2 |
import re |
| 3 |
import subprocess |
| 4 |
|
| 5 |
from rbtools.api.client import RBClient |
| 6 |
from rbtools.api.errors import APIError, ServerInterfaceError |
| 7 |
|
| 8 |
|
| 9 |
SUBMITTED = 'submitted' |
| 10 |
|
| 11 |
|
| 12 |
class HookError(Exception): |
| 13 |
pass |
| 14 |
|
| 15 |
|
| 16 |
def _make_api_client(server_url, username, password): |
| 17 |
"""Returns an RBClient object for the server. |
| 18 |
|
| 19 |
The RBClient will be instantiated with the proper arguments |
| 20 |
for talking to the provided Review Board server url. |
| 21 |
""" |
| 22 |
return RBClient(server_url, username=username, password=password) |
| 23 |
|
| 24 |
def get_api(server_url, username, password): |
| 25 |
"""Returns an RBClient instance and the associated root resource. |
| 26 |
|
| 27 |
Hooks should use this method to gain access to the API, |
| 28 |
instead of instantianting their own client. |
| 29 |
""" |
| 30 |
api_client = _make_api_client(server_url, username, password) |
| 31 |
|
| 32 |
try: |
| 33 |
api_root = api_client.get_root() |
| 34 |
except ServerInterfaceError, e: |
| 35 |
raise HookError('Could not reach the Review Board server at %s' |
| 36 |
% server_url) |
| 37 |
except APIError, e: |
| 38 |
raise HookError('Unexpected API Error: %s' % e) |
| 39 |
|
| 40 |
return api_client, api_root |
| 41 |
|
| 42 |
def execute(command): |
| 43 |
"""Executes the specified command and returns the stdout output.""" |
| 44 |
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) |
| 45 |
return process.communicate()[0].strip() |
| 46 |
|
| 47 |
def get_review_request_id(regex, commit_message): |
| 48 |
"""Returns the review request ID referenced in the commit message. |
| 49 |
|
| 50 |
We assume there is only one review request to be closed per commit. If a |
| 51 |
matching review request cannot be found, we return None. |
| 52 |
""" |
| 53 |
pattern = re.compile(regex, re.IGNORECASE) |
| 54 |
match = pattern.search(commit_message) |
| 55 |
review_request_id = (match and match.group('id')) or None |
| 56 |
return review_request_id |
| 57 |
|
| 58 |
def get_review_request(review_request_id, api_root): |
| 59 |
"""Returns the review request resource for the given ID.""" |
| 60 |
try: |
| 61 |
review_request = api_root.get_review_request( |
| 62 |
review_request_id=review_request_id) |
| 63 |
except APIError, e: |
| 64 |
raise HookError('Error getting review request: %s' % e) |
| 65 |
|
| 66 |
return review_request |
| 67 |
|
| 68 |
def close_review_request(server_url, username, password, review_request_id, |
| 69 |
description): |
| 70 |
"""Closes the specified review request as submitted.""" |
| 71 |
api_client, api_root = get_api(server_url, username, password) |
| 72 |
review_request = get_review_request(review_request_id, api_root) |
| 73 |
|
| 74 |
if review_request.status == SUBMITTED: |
| 75 |
logging.warning('Review request #%s is already %s.', |
| 76 |
review_request_id, SUBMITTED) |
| 77 |
return |
| 78 |
|
| 79 |
if description: |
| 80 |
review_request = review_request.update(status=SUBMITTED, |
| 81 |
description=description) |
| 82 |
else: |
| 83 |
review_request = review_request.update(status=SUBMITTED) |
| 84 |
|
| 85 |
print('Review request #%s is set to %s.' % |
| 86 |
(review_request_id, review_request.status)) |
| 87 |
|
| 88 |
def get_review_request_approval(server_url, username, password, |
| 89 |
review_request_id): |
| 90 |
"""Returns the approval information for the given review request.""" |
| 91 |
api_client, api_root = get_api(server_url, username, password) |
| 92 |
review_request = get_review_request(review_request_id, api_root) |
| 93 |
|
| 94 |
return review_request.approved, review_request.approval_failure |