Commit 847afeb5 authored by Vamshi Krishna's avatar Vamshi Krishna

Commit.py: Add mentioned_issues, closes_issues propeties

Closes coala/GSoC/GSoC-2018#287 , #130
parent 8eb39867
Pipeline #23299202 passed with stages
in 34 seconds
......@@ -8,6 +8,7 @@ from IGitt import ElementDoesntExistError
from IGitt.GitHub import GitHubMixin, GitHubToken
from IGitt.GitHub.GitHubComment import GitHubComment
from IGitt.GitHub.GitHubRepository import GitHubRepository
from IGitt.GitHub.GitHubIssue import GitHubIssue
from IGitt.Interfaces import get, post
from IGitt.Interfaces.Comment import CommentType
from IGitt.Interfaces.Commit import Commit
......@@ -368,3 +369,20 @@ class GitHubCommit(GitHubMixin, Commit):
return '\n'.join([diff for diff in difflines
if not diff.startswith('diff --git') and
not diff.startswith('index')])
@property
def closes_issues(self) -> Set[GitHubIssue]:
"""
Returns a set of GitHubIssue objects which would be closed upon merging
this commit.
"""
return {GitHubIssue(self._token, repo_name, number)
for number, repo_name in self._get_closes_issues()}
@property
def mentioned_issues(self) -> Set[GitHubIssue]:
"""
Returns a set of GitHubIssue objects which are related to the commit.
"""
return {GitHubIssue(self._token, repo_name, number)
for number, repo_name in self._get_mentioned_issues()}
......@@ -227,9 +227,8 @@ class GitHubMergeRequest(GitHubIssue, MergeRequest):
Returns a set of GitHubIssue objects which would be closed upon merging
this pull request.
"""
issues = self._get_closes_issues()
return {GitHubIssue(self._token, repo_name, number)
for number, repo_name in issues}
return {issue for commit in self.commits
for issue in commit.closes_issues}
@property
def mentioned_issues(self) -> Set[GitHubIssue]:
......@@ -237,7 +236,11 @@ class GitHubMergeRequest(GitHubIssue, MergeRequest):
Returns a set of GitHubIssue objects which are related to the pull
request.
"""
issues = self._get_mentioned_issues()
commit_bodies = [commit.message for commit in self.commits]
comment_bodies = [comment.body for comment in self.comments]
commit = next(iter(self.commits))
issues = commit.get_keywords_issues(r'',
commit_bodies + comment_bodies)
return {GitHubIssue(self._token, repo_name, number)
for number, repo_name in issues}
......
......@@ -12,6 +12,7 @@ from IGitt.GitLab import GitLabMixin
from IGitt.GitLab import GitLabOAuthToken, GitLabPrivateToken
from IGitt.GitLab.GitLabComment import GitLabComment
from IGitt.GitLab.GitLabRepository import GitLabRepository
from IGitt.GitLab.GitLabIssue import GitLabIssue
from IGitt.Interfaces import get, post
from IGitt.Interfaces.Comment import CommentType
from IGitt.Interfaces.Commit import Commit
......@@ -340,3 +341,23 @@ class GitLabCommit(GitLabMixin, Commit):
return '\n'.join(patch['diff']
for patch in get(self._token, self.url + '/diff')
)
@property
def closes_issues(self) -> Set[GitLabIssue]:
"""
Returns a set of GitLabIssue objects which would be closed upon merging
this pull request.
"""
issues = self._get_closes_issues()
return {GitLabIssue(self._token, repo_name, number)
for number, repo_name in issues}
@property
def mentioned_issues(self) -> Set[GitLabIssue]:
"""
Returns a set of GitLabIssue objects which are related to the merge
request.
"""
issues = self._get_mentioned_issues()
return {GitLabIssue(self._token, repo_name, number)
for number, repo_name in issues}
......@@ -206,17 +206,18 @@ class GitLabMergeRequest(GitLabIssue, MergeRequest):
Returns a set of GitLabIssue objects which would be closed upon merging
this pull request.
"""
issues = self._get_closes_issues()
return {GitLabIssue(self._token, repo_name, number)
for number, repo_name in issues}
return {issue for commit in self.commits
for issue in commit.closes_issues}
@property
def mentioned_issues(self) -> Set[GitLabIssue]:
"""
Returns a set of GitLabIssue objects which are related to the merge
request.
"""
issues = self._get_mentioned_issues()
body = [commit.message for commit in self.commits] + [
comment.body for comment in self.comments]
commit = next(iter(self.commits))
issues = commit.get_keywords_issues(r'', body)
return {GitLabIssue(self._token, repo_name, number)
for number, repo_name in issues}
......
......@@ -3,11 +3,26 @@ This module contains the actual commit object.
"""
from typing import Optional
from typing import Set
from typing import List
from itertools import chain
import re
from IGitt.Interfaces import IGittObject
from IGitt.Interfaces import Comment
from IGitt.Interfaces.CommitStatus import CommitStatus, Status
from IGitt.Interfaces.Repository import Repository
from IGitt.Interfaces.Issue import Issue
SUPPORTED_HOST_KEYWORD_REGEX = {
'github': (r'[Cc]lose[sd]?'
r'|[Rr]esolve[sd]?'
r'|[Ff]ix(?:e[sd])?'),
'gitlab': (r'[Cc]los(?:e[sd]?|ing)'
r'|[Rr]esolv(?:e[sd]?|ing)'
r'|[Ff]ix(?:e[sd]|ing)?')
}
CONCATENATION_KEYWORDS = [r',', r'\sand\s']
class Commit(IGittObject):
......@@ -187,3 +202,92 @@ class Commit(IGittObject):
Retrieves the unified diff for the commit excluding the diff index.
"""
raise NotImplementedError
def get_keywords_issues(self, keyword: str, body_list: List) -> Set[int]:
"""
Returns a set of tuples(issue number, name of the repository the issue
is contained in), which are mentioned with given ``keyword``.
"""
results = set()
hoster = self.repository.hoster
repo_name = self.repository.full_name
identifier_regex = r'[\w\.-]+'
namespace_regex = r'(?:{0})/(?:{0})(?:/(?:{0}))?'.format(
identifier_regex)
concat_regex = '|'.join(kw for kw in CONCATENATION_KEYWORDS)
issue_no_regex = r'[1-9][0-9]*'
issue_url_regex = r'https?://{}\S+/issues/{}'.format(
hoster, issue_no_regex)
c_joint_regex = re.compile(
r'((?:{0})' # match keywords expressed via ``keyword``
r'(?:(?:{3})?\s*' # match conjunctions
# eg: ',', 'and' etc.
r'(?:(?:\S*)#{2}|' # match short references
# eg: #123, coala/example#23
r'(?:{1})))+)' # match full length issue URLs
# eg: https://github.com/coala/coala/issues/23
r''.format(keyword,
issue_url_regex, issue_no_regex, concat_regex))
c_issue_capture_regex = re.compile(
r'(?:(?:\s+|^)({2})?#({0}))|(?:https?://{1}\S+?/({2})/issues/({0}))'
''.format(
issue_no_regex, hoster, namespace_regex))
for body in body_list:
matches = c_joint_regex.findall(body.replace('\r', ''))
refs = list(chain(*[c_issue_capture_regex.findall(match)
for match in matches]))
for ref in refs:
if ref[0] != '':
repo_name = ref[0]
if ref[1] != '':
results.add((ref[1], repo_name))
if ref[2] != '' and ref[3] != '':
results.add((ref[3], ref[2]))
return results
def _get_closes_issues(self) -> Set[int]:
"""
Returns a set of tuples(issue number, name of the repository the issue
is contained in), which would be closed upon merging this commit.
"""
hoster = self.repository.hoster
# If the hoster does not support auto closing issues with matching
# keywords, just return an empty set. At the moment, we only have
# support for GitLab and GitHub. And both of them support autoclosing
# issues with matching keywords.
if hoster not in SUPPORTED_HOST_KEYWORD_REGEX: # dont cover
return set()
return self.get_keywords_issues(
SUPPORTED_HOST_KEYWORD_REGEX[self.repository.hoster],
[self.message]
)
def _get_mentioned_issues(self):
"""
Returns a set of tuples(issue number, name of the repository the issue
is contained in), which are related to this commit.
"""
return self.get_keywords_issues(r'', [self.message])
@property
def closes_issues(self) -> Set[Issue]:
"""
Returns a set of Issue objects which would be closed upon merging this
commit.
"""
raise NotImplementedError
@property
def mentioned_issues(self) -> Set[Issue]:
"""
Returns a set of Issue objects which are related to the commit.
"""
raise NotImplementedError
......@@ -3,10 +3,8 @@ Contains a class that represents a request to merge something into some git
branch.
"""
from datetime import datetime
from itertools import chain
from typing import List
from typing import Set
import re
from IGitt.Interfaces import MergeRequestStates
from IGitt.Interfaces.Commit import Commit
......@@ -15,17 +13,6 @@ from IGitt.Interfaces.Issue import Issue
from IGitt.Interfaces.User import User
SUPPORTED_HOST_KEYWORD_REGEX = {
'github': (r'[Cc]lose[sd]?'
r'|[Rr]esolve[sd]?'
r'|[Ff]ix(?:e[sd])?'),
'gitlab': (r'[Cc]los(?:e[sd]?|ing)'
r'|[Rr]esolv(?:e[sd]?|ing)'
r'|[Ff]ix(?:e[sd]|ing)?')
}
CONCATENATION_KEYWORDS = [r',', r'\sand\s']
class MergeRequest(Issue):
"""
A request to merge something into the main codebase. Can be a patch in a
......@@ -174,86 +161,6 @@ class MergeRequest(Issue):
"""
raise NotImplementedError
# Ignore PyLintBear
def _get_keywords_issues(self, keyword: str, body_list: List) -> Set[int]:
"""
Returns a set of tuples(issue number, name of the repository the issue
is contained in), which are mentioned with given ``keyword``.
"""
results = set()
hoster = self.repository.hoster
repo_name = self.repository.full_name
identifier_regex = r'[\w\.-]+'
namespace_regex = r'(?:{0})/(?:{0})(?:/(?:{0}))?'.format(
identifier_regex)
concat_regex = '|'.join(kw for kw in CONCATENATION_KEYWORDS)
issue_no_regex = r'[1-9][0-9]*'
issue_url_regex = r'https?://{}\S+/issues/{}'.format(
hoster, issue_no_regex)
c_joint_regex = re.compile(
r'((?:{0})' # match keywords expressed via ``keyword``
r'(?:(?:{3})?\s*' # match conjunctions
# eg: ',', 'and' etc.
r'(?:(?:\S*)#{2}|' # match short references
# eg: #123, coala/example#23
r'(?:{1})))+)' # match full length issue URLs
# eg: https://github.com/coala/coala/issues/23
r''.format(keyword,
issue_url_regex, issue_no_regex, concat_regex))
c_issue_capture_regex = re.compile(
r'(?:(?:\s+|^)({2})?#({0}))|(?:https?://{1}\S+?/({2})/issues/({0}))'
''.format(
issue_no_regex, hoster, namespace_regex))
for body in body_list:
matches = c_joint_regex.findall(body.replace('\r', ''))
refs = list(chain(*[c_issue_capture_regex.findall(match)
for match in matches]))
for ref in refs:
if ref[0] != '':
repo_name = ref[0]
if ref[1] != '':
results.add((ref[1], repo_name))
if ref[2] != '' and ref[3] != '':
results.add((ref[3], ref[2]))
return results
def _get_closes_issues(self) -> Set[int]:
"""
Returns a set of tuples(issue number, name of the repository the issue
is contained in), which would be closed upon merging this pull request.
"""
hoster = self.repository.hoster
# If the hoster does not support auto closing issues with matching
# keywords, just return an empty set. At the moment, we only have
# support for GitLab and GitHub. And both of them support autoclosing
# issues with matching keywords.
if hoster not in SUPPORTED_HOST_KEYWORD_REGEX: # dont cover
return set()
relevant_texts = [commit.message for commit in self.commits]
relevant_texts.extend([self.description, self.title])
return self._get_keywords_issues(
SUPPORTED_HOST_KEYWORD_REGEX[self.repository.hoster],
relevant_texts
)
def _get_mentioned_issues(self):
"""
Returns a set of tuples(issue number, name of the repository the issue
is contained in), which are related to this pull request.
"""
commit_bodies = [commit.message for commit in self.commits]
comment_bodies = [comment.body for comment in self.comments]
return self._get_keywords_issues(r'', commit_bodies + comment_bodies)
@property
def closes_issues(self) -> Set[Issue]:
"""
......
interactions:
- request:
body: '{}'
headers:
Accept: ['*/*']
Accept-Encoding: ['gzip, deflate']
Connection: [keep-alive]
Content-Length: ['2']
Content-Type: [application/json]
User-Agent: [IGitt]
method: GET
uri: https://api.github.com/repos/gitmate-test-user/test/commits/fb37d69e72b46a52f8694cf45adb007315de3b6e?per_page=100
response:
body:
string: !!binary |
H4sIAAAAAAAAA61XXY+bOBT9K4h5bDIYwmekqqkqdSut1JftvuxONTJwSawCjmyTdDbKf++9BDIk
q5kJSR+QDPY598M+15edrVfcnttFOovyMIHIS/2QB14Rh4mfFX7A85SxaOYGOczSEOyJncmqEsae
72zemJVUNKp5BcjylW8AauvPpuLK+ovXS4HroeKixMn6x1qJOgOkWyzp2z0y4XzODWE95kZTlkw9
/5sbzwN3zvx/7H1vzsDQzh/CfGnSIbdUsC6fFkthVk16GXEFWvMlmf4CZSkf6of64xa0rMA6hGh1
Kx4UzuHzWfy07lzmTywcgaZxYPE6tz6VUuP7IEDHgDZ37j3Bvq2E7hlxxEstLQUlRp1bRiJL1JIU
PWc0se6SmJD0eWXMWs8d5zkyGlaInpKNaaNBtdYcoXUD2kmie0yMUYCR7brd9WdZXAQRy7wiBzcP
eFzEvuvFoZezOGRJ4LucJWmMwEbRXvVW+VrcDyxjkqV+yT6uc8isdi42h9t7m73DRmln5PGF2jxm
sqnxFLOJvQElCpFxI2RNOTu8Q27PC9wsmNgKuKYpu6m1WNY4M7FpwE2jMMt1U5YTe82fSskRRK/7
myK7IqqVqcrH01y+fWIOdq5Inj4zNeaYjA3OIQBumMakPxecUi4F7chAczgvMP1u5DEvTnBf+YYb
rs5dbT/qWXesST6ZrA0aoKrhNE6P/7B57yPlUnU0xG2/JRCi086pU69vzenaQmIl2iLHudenOvyf
GecIRA8PY1EvryNB4M6RZgWYOgxnT0kQ2ox2qQXtsFpo8yhyotGYeQX5WLc6GDq1rdGfnUNlqOVr
Up0psSbhjnbvBIxkUi15Lf5rq8BoMgTT+Wzr49jwWhCCYUOnfCz6gNo5eLduePZEaVGQgdhgnq9j
PIMjoXla0zX5N54Gyrow8MjzivTXFsjzS7rX5hbSaYHHGTGtMJM49H0/ulqYHf4GYQ48el2Vg4Wj
JNnjrtfjGcMtYjxS3aTEI8vvk+Ez5VDA12jwyDRWgEfgePUdob9HegNPTmR7ke7WXLVX4/zfvtUr
IkhCL2MsDIsoi0LGYMaxwfPTLPKA5ZmbFnnBPKS/vvU63uGXG3tdby+0tH2DcqmZ/ff2kqGE7Gwj
Dcde1sV6k+eiLevtWw4ldG8MS1chShgmMJiFjPszzw0CHnDwUi/yeJJFiRen2EW7SVpEBc8pgQTt
/nwU9uqyog9UIdGFBjnJcNssvuwA/t+s8D+JPEDX0lKmo7s4Al3cwzknjiq+HW0OMVda6/qsN664
V/8xeopBGB8UFO9H9P9rbrIV7s1iYU3ZhFnvXGuxeKjfHRLTGbD33/e/ANR7i2EbDwAA
headers:
Access-Control-Allow-Origin: ['*']
Access-Control-Expose-Headers: ['ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit,
X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes,
X-Poll-Interval']
Cache-Control: ['private, max-age=60, s-maxage=60']
Content-Encoding: [gzip]
Content-Security-Policy: [default-src 'none']
Content-Type: [application/json; charset=utf-8]
Date: ['Sat, 12 May 2018 14:53:07 GMT']
ETag: [W/"a3acd640be74e71a3233e83ba5b560e0"]
Last-Modified: ['Sun, 24 Sep 2017 18:51:04 GMT']
Referrer-Policy: ['origin-when-cross-origin, strict-origin-when-cross-origin']
Server: [GitHub.com]
Status: [200 OK]
Strict-Transport-Security: [max-age=31536000; includeSubdomains; preload]
Vary: ['Accept, Authorization, Cookie, X-GitHub-OTP']
X-Accepted-OAuth-Scopes: ['']
X-Content-Type-Options: [nosniff]
X-Frame-Options: [deny]
X-GitHub-Media-Type: [github.v3; format=json]
X-GitHub-Request-Id: ['1CD0:55F4:1F7E3FB:46C500F:5AF6FFD2']
X-OAuth-Scopes: ['admin:gpg_key, admin:org, admin:org_hook, admin:public_key,
admin:repo_hook, gist, notifications, repo, user']
X-RateLimit-Limit: ['5000']
X-RateLimit-Remaining: ['4998']
X-RateLimit-Reset: ['1526140139']
X-Runtime-rack: ['0.122179']
X-XSS-Protection: [1; mode=block]
status: {code: 200, message: OK}
- request:
body: '{}'
headers:
Accept: ['*/*']
Accept-Encoding: ['gzip, deflate']
Connection: [keep-alive]
Content-Length: ['2']
Content-Type: [application/json]
User-Agent: [IGitt]
method: GET
uri: https://api.github.com/repos/gitmate-test-user/test/commits/4efefe405197072e709fa3d2a3459f29ba949b64?per_page=100
response:
body:
string: !!binary |
H4sIAAAAAAAAA+1XS2/iMBD+K1GuheZNCFJVjnva0+5lt1U1fiRYCnZkO6Au4r/vTIBtQeojrfZW
wcF28s3T38xkF7oVhIswlzX+8rhIqjIuU1nGVQ2ZSCHLi6pOKwZVXrFZHk5CbtZr5cPFLoTer4yl
lYa1RCncQK1aiS/JNaj26QQftLBs6PAa8fiCAE+INE7KaYz/6kcaL7JqkSW/wv1JiZf/R/paOgcN
6f8m29agOd5K3O6O0WA8ZRXPUpkKlrFKzjMpCs4Er4s0q7KE53GdZXyGwN6SmyvvO7eIIujUdaP8
qmfkZmRlZ1yEB2v0duql89PeSRvRio4jUuuid6vDwHxO3yF3LhqZbqn9Aze9xqzHk3AjraoVB6+M
ppgd9lKEixpaJyehleDoUdhrpxqNTyYhLcD3FqOs+7adhB08tgYQRNv9pzz7gFcrv24fzmP5LG8v
ZOyg5wPBcxeqxlyTsc5FBMCEOQz6E0Fb0yjKyBNDFYY+rcqsnJUVvrkBD/bSzOHQxccrTVeXG+1R
+HC7++iEv93cUGVo7FEMyQ7fIgeJc2jtqWS8npKn92qDlN0i9tLac+6diY/+gdCqw1rpZrwABO0i
41cSQ4Xm78lp5fwoUwbADunv/IMSJMJhlK0UY8w5QtCYrUY7dkOpGWT1zHGrOiLnKLPOgCjI2Aa0
+jOwfJQgBNLdG2rfGJcGAALlhm7vGOQBsYs6qzbAHykMVnKpNhjT8dIuoCjMP3bUK35ixinCyssH
EGvi01DwLtvVF9eOBMVgfXHtMAmcV6Mvrh2qPlatM5q+i2sd2KG9LX6fxrUZzqizhMfzPIF5zhOB
c2sxL7ICoIxB5AWT+ZznnxvXTn14hLLXO9rrQ8a71ezvhwZCAdmF3njAeTTBhi6EGkr3sBOylcdd
jOWKhvTnASyApfUc8izNgEHNkhgYm81nRSkqkVV1AmVZxEVJhEbocdrHIeDUu8mAHiWS2mHce1k9
zvYr0A3pR8NYa9hFqX97DiPQu6ew6JmZFrajlSHmQ7qOk9IbjezVL4STiH8u3FpZ34yY3TvwfIVZ
WS6DaTyJg6skWC7v9NXw1XOn7+6C7ybQctsqLQPwgdQiMHUwfMPt7/d/ATwotPcdDgAA
headers:
Access-Control-Allow-Origin: ['*']
Access-Control-Expose-Headers: ['ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit,
X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes,
X-Poll-Interval']
Cache-Control: ['private, max-age=60, s-maxage=60']
Content-Encoding: [gzip]
Content-Security-Policy: [default-src 'none']
Content-Type: [application/json; charset=utf-8]
Date: ['Wed, 30 May 2018 12:36:39 GMT']
ETag: [W/"7cddc280b4207e5c37c8059a7c8cb354"]
Last-Modified: ['Sun, 09 Jul 2017 20:39:31 GMT']
Referrer-Policy: ['origin-when-cross-origin, strict-origin-when-cross-origin']
Server: [GitHub.com]
Status: [200 OK]
Strict-Transport-Security: [max-age=31536000; includeSubdomains; preload]
Vary: ['Accept, Authorization, Cookie, X-GitHub-OTP']
X-Accepted-OAuth-Scopes: ['']
X-Content-Type-Options: [nosniff]
X-Frame-Options: [deny]
X-GitHub-Media-Type: [github.v3; format=json]
X-GitHub-Request-Id: ['07BA:0219:7BF5C0D:F06FA09:5B0E9AD6']
X-OAuth-Scopes: ['admin:gpg_key, admin:org, admin:org_hook, admin:public_key,
admin:repo_hook, gist, notifications, repo, user']
X-RateLimit-Limit: ['5000']
X-RateLimit-Remaining: ['4998']
X-RateLimit-Reset: ['1527686274']
X-Runtime-rack: ['0.118023']
X-XSS-Protection: [1; mode=block]
status: {code: 200, message: OK}
version: 1
interactions:
- request:
body: '{}'
headers:
Accept: ['*/*']
Accept-Encoding: ['gzip, deflate']
Connection: [keep-alive]
Content-Length: ['2']
Content-Type: [application/json]
If-None-Match: [W/"a3acd640be74e71a3233e83ba5b560e0"]
User-Agent: [IGitt]
method: GET
uri: https://api.github.com/repos/gitmate-test-user/test/commits/fb37d69e72b46a52f8694cf45adb007315de3b6e?per_page=100
response:
body: {string: ''}
headers:
Access-Control-Allow-Origin: ['*']
Access-Control-Expose-Headers: ['ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit,
X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes,
X-Poll-Interval']
Cache-Control: ['private, max-age=60, s-maxage=60']
Content-Security-Policy: [default-src 'none']
Content-Type: [application/octet-stream]
Date: ['Sat, 12 May 2018 14:53:09 GMT']
ETag: ['"a3acd640be74e71a3233e83ba5b560e0"']
Last-Modified: ['Sun, 24 Sep 2017 18:51:04 GMT']
Referrer-Policy: ['origin-when-cross-origin, strict-origin-when-cross-origin']
Server: [GitHub.com]
Status: [304 Not Modified]
Strict-Transport-Security: [max-age=31536000; includeSubdomains; preload]
Vary: ['Accept, Authorization, Cookie, X-GitHub-OTP']
X-Content-Type-Options: [nosniff]
X-Frame-Options: [deny]
X-GitHub-Request-Id: ['1CD1:55F4:1F7E4C6:46C51D7:5AF6FFD4']
X-RateLimit-Limit: ['5000']
X-RateLimit-Remaining: ['4998']
X-RateLimit-Reset: ['1526140139']
X-Runtime-rack: ['0.051452']
X-XSS-Protection: [1; mode=block]
status: {code: 304, message: Not Modified}
- request:
body: '{}'
headers:
Accept: ['*/*']
Accept-Encoding: ['gzip, deflate']
Connection: [keep-alive]
Content-Length: ['2']
Content-Type: [application/json]
If-None-Match: [W/"7cddc280b4207e5c37c8059a7c8cb354"]
User-Agent: [IGitt]
method: GET
uri: https://api.github.com/repos/gitmate-test-user/test/commits/4efefe405197072e709fa3d2a3459f29ba949b64?per_page=100
response:
body: {string: ''}
headers:
Access-Control-Allow-Origin: ['*']
Access-Control-Expose-Headers: ['ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit,
X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes,
X-Poll-Interval']
Cache-Control: ['private, max-age=60, s-maxage=60']
Content-Security-Policy: [default-src 'none']
Content-Type: [application/octet-stream]
Date: ['Wed, 30 May 2018 12:36:42 GMT']
ETag: ['"7cddc280b4207e5c37c8059a7c8cb354"']
Last-Modified: ['Sun, 09 Jul 2017 20:39:31 GMT']
Referrer-Policy: ['origin-when-cross-origin, strict-origin-when-cross-origin']
Server: [GitHub.com]
Status: [304 Not Modified]
Strict-Transport-Security: [max-age=31536000; includeSubdomains; preload]
Vary: ['Accept, Authorization, Cookie, X-GitHub-OTP']
X-Content-Type-Options: [nosniff]
X-Frame-Options: [deny]
X-GitHub-Request-Id: ['07BC:0219:7BF5E11:F06FE62:5B0E9AD9']
X-RateLimit-Limit: ['5000']
X-RateLimit-Remaining: ['4998']
X-RateLimit-Reset: ['1527686274']
X-Runtime-rack: ['0.059815']
X-XSS-Protection: [1; mode=block]
status: {code: 304, message: Not Modified}
version: 1
......@@ -56,30 +56,31 @@ interactions:
X-XSS-Protection: [1; mode=block]
status: {code: 200, message: OK}
- request:
body: null
body: '{}'
headers:
Accept: ['*/*']
Accept-Encoding: ['gzip, deflate']
Connection: [keep-alive]
Content-Length: ['2']
Content-Type: [application/json]
User-Agent: [IGitt]
method: GET
uri: https://api.github.com/repos/gitmate-test-user/test/issues/113?per_page=100
uri: https://api.github.com/repos/gitmate-test-user/test/pulls/99/commits?per_page=100
response:
body:
string: !!binary |
H4sIAAAAAAAAA62WXW/aMBSG/0rk3gJO6Acl0jRt1ar1YqvU0ZutU2SSQ2LVsTPboaMR/33HJukK
1WCNeoFkkvM+Pj5fTkNqLUhMCmsrE1PKKj7KuS3q+ShVJdVQKUPxQcksDC0YO6wNaOpWlBtTg6FR
dEwGxFtyq/Qq6U1EjGBzEKY/4plTdMNqqGQlrJGNBypB2jeidzQEw/LtsBsWQgtbip04PEvMP1JS
1UK0CeEZicdnYRSenZ5NB0TW5Rw0iTFbA2K5FYBZ/wxCKNzL5ZTEDREq5xKfy/tKc5lCGE7wrSNF
k3E4Pp+GA8KWzDK9myH/0By3teN4qZIWw+LLqKad/v3y3Qkic91iHJs4D/ZVocMZuu3U/vBs2y4U
HvMBGbtebxf7i23okxA93Ky5zPtBUNhQZQvA0OFxXD3m3BwqxpcueVGDLWlswjOHMRh5Ddlr3Wpl
6NSDRH8a3+ueV89NqnlluZKvjtiWGGFK50zyR9YLhmKDDD9aXns8L0Lx//TmyyhvVA3FNliydOXC
oiEFvsQ49yPuyBFoV5XrwVvXexh1biFhWen6b8GEgXU3DEn846fPsnXmqgKJ5kKl94C9402xKY3h
uQQ0kDgB/v43G3HJBQ5sJZ/ePw2vGDs61YDsLGEW+eMwmgzD6XB8MovO49MoHoffcb+6yg7apEKZ
FtN6UdtC6QSdUyn3JYAbXF7dfJsls6svn5KL66+zm6uPt7PrG9zCza5Ewy+8U9CRZv9I2HsxOVJ3