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(1)) 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 |