Skip to content

Commit 31e563d

Browse files
authored
Bitbucket Cloud: Add PR diff/patch/diffstat (atlassian-api#888)
* Added object for DiffStat and moved to its own file since it can be generated at different places in the API. Signed-off-by: Frank Lichtenheld <frank@lichtenheld.com>
1 parent 4d90a20 commit 31e563d

File tree

2 files changed

+123
-1
lines changed

2 files changed

+123
-1
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
from ..base import BitbucketCloudBase
2+
3+
4+
class DiffStat(BitbucketCloudBase):
5+
"""
6+
Bitbucket Cloud repository diffstat entry.
7+
8+
This represents the changes for one specific file in a diff.
9+
10+
See https://developer.atlassian.com/cloud/bitbucket/rest/api-group-commits/#api-repositories-workspace-repo-slug-diffstat-spec-get
11+
"""
12+
13+
MODIFIED = "modified"
14+
ADDED = "added"
15+
REMOVED = "removed"
16+
MERGE_CONFLICT = "merge conflict"
17+
SUBREPO_CONFLICT = "subrepo conflict"
18+
19+
def __init__(self, data, *args, **kwargs):
20+
"""See BitbucketCloudBase."""
21+
super(DiffStat, self).__init__(None, None, *args, data=data, expected_type="diffstat", **kwargs)
22+
23+
@property
24+
def lines_removed(self):
25+
"""Lines removed."""
26+
return self.get_data("lines_removed")
27+
28+
@property
29+
def lines_added(self):
30+
"""Lines added."""
31+
return self.get_data("lines_added")
32+
33+
@property
34+
def old(self):
35+
"""A CommitFile object, representing a file at a commit in a repository."""
36+
return CommitFile(self.get_data("old"), **self._new_session_args)
37+
38+
@property
39+
def new(self):
40+
"""A CommitFile object, representing a file at a commit in a repository."""
41+
return CommitFile(self.get_data("new"), **self._new_session_args)
42+
43+
@property
44+
def has_conflict(self):
45+
"""True if the change causes a conflict."""
46+
return str(self.get_data("status")) in (self.MERGE_CONFLICT, self.SUBREPO_CONFLICT)
47+
48+
49+
class CommitFile(BitbucketCloudBase):
50+
"""
51+
Bitbucket Cloud repository diffstat file.
52+
53+
File reference from a diffstat entry.
54+
55+
See https://developer.atlassian.com/cloud/bitbucket/rest/api-group-commits/#api-repositories-workspace-repo-slug-diffstat-spec-get
56+
"""
57+
58+
def __init__(self, data, *args, **kwargs):
59+
"""See BitbucketCloudBase."""
60+
if data is None: # handles add/remove
61+
data = {"path": None, "escaped_path": None, "links": {}, "type": "commit_file"}
62+
super(CommitFile, self).__init__(None, None, *args, data=data, expected_type="commit_file", **kwargs)
63+
64+
@property
65+
def path(self):
66+
"""The path in the repository."""
67+
return self.get_data("path")
68+
69+
@property
70+
def escaped_path(self):
71+
"""
72+
The escaped version of the path as it appears in a diff.
73+
74+
If the path does not require escaping this will be the same as path.
75+
"""
76+
return self.get_data("escaped_path")

atlassian/bitbucket/cloud/repositories/pullRequests.py

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# coding=utf-8
22

33
from ..base import BitbucketCloudBase
4+
from .diffstat import DiffStat
45
from ..common.users import User
56

67

@@ -177,6 +178,16 @@ def destination_branch(self):
177178
"""destination branch"""
178179
return self.get_data("destination")["branch"]["name"]
179180

181+
@property
182+
def source_commit(self):
183+
"""Source commit."""
184+
return self.get_data("source")["commit"]["hash"]
185+
186+
@property
187+
def destination_commit(self):
188+
"""Destination commit."""
189+
return self.get_data("destination")["commit"]["hash"]
190+
180191
@property
181192
def comment_count(self):
182193
"""number of comments"""
@@ -197,6 +208,41 @@ def author(self):
197208
"""User object of the author"""
198209
return User(None, self.get_data("author"))
199210

211+
@property
212+
def has_conflict(self):
213+
"""Returns True if any of the changes in the PR cause conflicts."""
214+
for diffstat in self.diffstat():
215+
if diffstat.has_conflict:
216+
return True
217+
return False
218+
219+
def diffstat(self):
220+
"""
221+
Returns a generator object of diffstats
222+
223+
API docs: https://developer.atlassian.com/bitbucket/api/2/reference/resource/repositories/%7Bworkspace%7D/%7Brepo_slug%7D/pullrequests/%7Bpull_request_id%7D/diffstat
224+
"""
225+
for diffstat in self._get_paged("diffstat"):
226+
yield DiffStat(diffstat, **self._new_session_args)
227+
228+
return
229+
230+
def diff(self, encoding="utf-8"):
231+
"""
232+
Returns PR diff
233+
234+
API docs: https://developer.atlassian.com/bitbucket/api/2/reference/resource/repositories/%7Bworkspace%7D/%7Brepo_slug%7D/pullrequests/%7Bpull_request_id%7D/diff
235+
"""
236+
return str(self.get("diff", not_json_response=True), encoding=encoding)
237+
238+
def patch(self, encoding="utf-8"):
239+
"""
240+
Returns PR patch
241+
242+
API docs: https://developer.atlassian.com/bitbucket/api/2/reference/resource/repositories/%7Bworkspace%7D/%7Brepo_slug%7D/pullrequests/%7Bpull_request_id%7D/patch
243+
"""
244+
return str(self.get("patch", not_json_response=True), encoding=encoding)
245+
200246
def statuses(self):
201247
"""
202248
Returns generator object of the statuses endpoint
@@ -573,7 +619,7 @@ def update(self, raw_message):
573619

574620
def delete(self):
575621
"""
576-
Delete the pullrequest tasl.
622+
Delete the pullrequest task.
577623
578624
This is feature currently undocumented.
579625
"""

0 commit comments

Comments
 (0)