From cd76ea4b935cfa33f78c26023b2e456aa1e9d537 Mon Sep 17 00:00:00 2001 From: Raphael Castaneda Date: Tue, 15 Mar 2016 18:29:14 -0700 Subject: [PATCH 01/15] add stash interface --- inlineplz/interfaces/__init__.py | 4 +- inlineplz/interfaces/stash.py | 72 ++++++++++++++++++++++++++++++++ setup.py | 1 + 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 inlineplz/interfaces/stash.py diff --git a/inlineplz/interfaces/__init__.py b/inlineplz/interfaces/__init__.py index f968f590..87cff375 100644 --- a/inlineplz/interfaces/__init__.py +++ b/inlineplz/interfaces/__init__.py @@ -3,7 +3,9 @@ from __future__ import absolute_import from inlineplz.interfaces.github import GitHubInterface +from inlineplz.interfaces.stash import StashInterface INTERFACES = { - 'github': GitHubInterface + 'github': GitHubInterface, + 'stash': StashInterface } diff --git a/inlineplz/interfaces/stash.py b/inlineplz/interfaces/stash.py new file mode 100644 index 00000000..3b35fe41 --- /dev/null +++ b/inlineplz/interfaces/stash.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import + +import stashy + +from inlineplz.interfaces.base import InterfaceBase +from inlineplz.util import git + + +class StashInterface(InterfaceBase): + def __init__(self, project, repo, pr, username, password, url=None): + # TODO: support non-PR runs + try: + pr = int(pr) + except ValueError: + return + if not url: + return + else: + self.stash = stashy.connect(url, username=username, password=password, verify=False) + self.pull_request = self.stash.projects[project].repos[repo].pull_requests[pr] + self.commits = [c for c in self.pull_request.commits()] + self.last_sha = self.commits[0]['id'] + self.first_sha = self.commits[-1]['id'] + self.parent_sha = self.commits[-1]['parents'][0]['id'] + self.diff = git.diff(self.parent_sha, self.last_sha) + + def post_messages(self, messages, max_comments): + # TODO: support non-PR runs + if not self.stash: + return + messages_to_post = 0 + messages_posted = 0 + for msg in messages: + if not msg.comments: + continue + msg_position = msg.line_number + if msg_position: + messages_to_post += 1 + if not self.is_duplicate(msg, msg_position): + self.pull_request.comment( + self.format_message(msg), + srcPath=msg.path, + fileLine=msg_position, + lineType='ADDED', + fileType='TO' + ) + messages_posted += 1 + if max_comments >= 0 and messages_posted > max_comments: + break + return messages_to_post + + def is_duplicate(self, message, position): + for comment in self.pull_request.comments(message.path): + if ('anchor' in comment and + 'line' in comment['anchor'] and + comment['anchor']['line'] == position and + comment['text'].strip() == self.format_message(message).strip()): + return True + return False + + @staticmethod + def format_message(message): + if not message.comments: + return '' + if len(message.comments) > 1: + return ( + '```\n' + + '\n'.join(sorted(list(message.comments))) + + '\n```' + ) + return '`{0}`'.format(list(message.comments)[0].strip()) diff --git a/setup.py b/setup.py index 8642ca0a..ccc5ffce 100644 --- a/setup.py +++ b/setup.py @@ -14,6 +14,7 @@ requirements = [ 'unidiff', 'github3.py', + 'stashy', 'xmltodict', 'pyyaml' ] From 25a06b1d1142e58b69b1614a1efc83e78a94a93f Mon Sep 17 00:00:00 2001 From: Raphael Castaneda Date: Tue, 15 Mar 2016 18:29:40 -0700 Subject: [PATCH 02/15] add support for user/password authentication --- inlineplz/main.py | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/inlineplz/main.py b/inlineplz/main.py index 1ccec681..67ad3af2 100644 --- a/inlineplz/main.py +++ b/inlineplz/main.py @@ -21,6 +21,8 @@ def main(): parser.add_argument('--repo', type=str) parser.add_argument('--repo-slug', type=str) parser.add_argument('--token', type=str) + parser.add_argument('--user', type=str) + parser.add_argument('--password', type=str) parser.add_argument('--interface', type=str, choices=interfaces.INTERFACES) parser.add_argument('--url', type=str) parser.add_argument('--dryrun', action='store_true') @@ -103,13 +105,23 @@ def inline(args): print(str(msg)) return 0 try: - my_interface = interfaces.INTERFACES[args.interface]( - owner, - repo, - args.pull_request, - args.token, - args.url - ) + if args.token: + my_interface = interfaces.INTERFACES[args.interface]( + owner, + repo, + args.pull_request, + args.token, + args.url + ) + else: + my_interface = interfaces.INTERFACES[args.interface]( + owner, + repo, + args.pull_request, + args.user, + args.password, + args.url + ) if my_interface.post_messages(messages, args.max_comments) and not args.zero_exit: return 1 except KeyError: From 0a2d7e23beba53e7fb26a505d631bf57e79d7d46 Mon Sep 17 00:00:00 2001 From: Raphael Castaneda Date: Wed, 16 Mar 2016 12:09:13 -0700 Subject: [PATCH 03/15] filter messages from outside of changed regions --- inlineplz/interfaces/stash.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/inlineplz/interfaces/stash.py b/inlineplz/interfaces/stash.py index 3b35fe41..30aa200b 100644 --- a/inlineplz/interfaces/stash.py +++ b/inlineplz/interfaces/stash.py @@ -2,6 +2,7 @@ from __future__ import absolute_import import stashy +import unidiff from inlineplz.interfaces.base import InterfaceBase from inlineplz.util import git @@ -34,7 +35,7 @@ def post_messages(self, messages, max_comments): for msg in messages: if not msg.comments: continue - msg_position = msg.line_number + msg_position = self.position(msg) if msg_position: messages_to_post += 1 if not self.is_duplicate(msg, msg_position): @@ -70,3 +71,20 @@ def format_message(message): '\n```' ) return '`{0}`'.format(list(message.comments)[0].strip()) + + def position(self, message): + """ + Determine where the comment should go + + Skips messages outside of the scope of changes we're looking at + """ + patch = unidiff.PatchSet(self.diff.split('\n')) + for patched_file in patch: + target = patched_file.target_file.lstrip('b/') + if target == message.path: + for hunk_no, hunk in enumerate(patched_file): + for position, hunk_line in enumerate(hunk): + if '+' not in hunk_line.line_type: + continue + if hunk_line.target_line_no == message.line_number: + return hunk_line.target_line_no From 242612879027bb6990d2b2e36e98606ab9c5ac9e Mon Sep 17 00:00:00 2001 From: Raphael Castaneda Date: Wed, 16 Mar 2016 14:21:34 -0700 Subject: [PATCH 04/15] combine token and user auth into a dictionary --- inlineplz/interfaces/github.py | 3 ++- inlineplz/interfaces/stash.py | 5 ++++- inlineplz/main.py | 24 +++++++----------------- 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/inlineplz/interfaces/github.py b/inlineplz/interfaces/github.py index 5b18e74c..68aedbf1 100644 --- a/inlineplz/interfaces/github.py +++ b/inlineplz/interfaces/github.py @@ -9,8 +9,9 @@ class GitHubInterface(InterfaceBase): - def __init__(self, owner, repo, pr, token, url=None): + def __init__(self, owner, repo, pr, auth, url=None): self.github = None + token = auth.get('token') # TODO: support non-PR runs try: pr = int(pr) diff --git a/inlineplz/interfaces/stash.py b/inlineplz/interfaces/stash.py index 30aa200b..4ee4cace 100644 --- a/inlineplz/interfaces/stash.py +++ b/inlineplz/interfaces/stash.py @@ -9,7 +9,10 @@ class StashInterface(InterfaceBase): - def __init__(self, project, repo, pr, username, password, url=None): + def __init__(self, project, repo, pr, auth, url=None): + self.stash = None + username = auth.get('username') + password = auth.get('password') # TODO: support non-PR runs try: pr = int(pr) diff --git a/inlineplz/main.py b/inlineplz/main.py index dda5fcbb..bc4a878e 100644 --- a/inlineplz/main.py +++ b/inlineplz/main.py @@ -105,23 +105,13 @@ def inline(args): print(str(msg)) return 0 try: - if args.token: - my_interface = interfaces.INTERFACES[args.interface]( - owner, - repo, - args.pull_request, - args.token, - args.url - ) - else: - my_interface = interfaces.INTERFACES[args.interface]( - owner, - repo, - args.pull_request, - args.user, - args.password, - args.url - ) + my_interface = interfaces.INTERFACES[args.interface]( + owner, + repo, + args.pull_request, + dict(token=args.token, username=args.user, password=args.password), + args.url + ) if my_interface.post_messages(messages, args.max_comments) and not args.zero_exit: return 1 except KeyError: From c2bd991e04c1313e52c50c78695aa4a7953e7984 Mon Sep 17 00:00:00 2001 From: Raphael Castaneda Date: Wed, 16 Mar 2016 14:22:19 -0700 Subject: [PATCH 05/15] add missing username and password params to docstring --- inlineplz/main.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/inlineplz/main.py b/inlineplz/main.py index bc4a878e..f87fc8de 100644 --- a/inlineplz/main.py +++ b/inlineplz/main.py @@ -79,6 +79,8 @@ def inline(args): repo: Repository name pr: Pull request ID token: Authentication for repository + username: (If not using token) username for repository + password: (If not using token) password for repository url: Root URL of repository (not your project) Default: https://github.com dryrun: Prints instead of posting comments. zero_exit: If true: always return a 0 exit code. From 34375472bf4874511eff572825066c4767564d77 Mon Sep 17 00:00:00 2001 From: Raphael Castaneda Date: Wed, 16 Mar 2016 14:24:28 -0700 Subject: [PATCH 06/15] update incorrect `user` param in docstring for `inline` --- inlineplz/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inlineplz/main.py b/inlineplz/main.py index f87fc8de..66be366d 100644 --- a/inlineplz/main.py +++ b/inlineplz/main.py @@ -79,7 +79,7 @@ def inline(args): repo: Repository name pr: Pull request ID token: Authentication for repository - username: (If not using token) username for repository + user: (If not using token) username for repository password: (If not using token) password for repository url: Root URL of repository (not your project) Default: https://github.com dryrun: Prints instead of posting comments. From 900835f7403cc017a110dcb53f546ec12e6d8503 Mon Sep 17 00:00:00 2001 From: Raphael Castaneda Date: Wed, 16 Mar 2016 15:14:00 -0700 Subject: [PATCH 07/15] add temporary dependency workaround for stashy --- setup.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 557bfb98..207d5af7 100644 --- a/setup.py +++ b/setup.py @@ -14,7 +14,7 @@ requirements = [ 'unidiff', 'github3.py', - 'stashy', + 'stashy>=0.3.0', 'xmltodict', 'pyyaml', 'scandir' @@ -35,6 +35,9 @@ packages=find_packages('.', exclude=('tests*', 'testing*')), include_package_data=True, install_requires=requirements, + dependency_links=[ # TODO: Remove dependency_links once stashy is updated on PyPI + 'git+ssh://git@github.com/RisingOak/stashy.git#egg=stashy-0.3.0' + ], license="ISCL", zip_safe=False, keywords='inlineplz', From fe86b2aa796fd6c231aeea0a67ef944076eed6e1 Mon Sep 17 00:00:00 2001 From: Raphael Castaneda Date: Wed, 16 Mar 2016 15:18:56 -0700 Subject: [PATCH 08/15] use https instead of ssh for stashy install --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 207d5af7..fe5964f6 100644 --- a/setup.py +++ b/setup.py @@ -36,7 +36,7 @@ include_package_data=True, install_requires=requirements, dependency_links=[ # TODO: Remove dependency_links once stashy is updated on PyPI - 'git+ssh://git@github.com/RisingOak/stashy.git#egg=stashy-0.3.0' + 'git+https://github.com/RisingOak/stashy.git#egg=stashy-0.3.0' ], license="ISCL", zip_safe=False, From 3383ae72f368fb15fe1414c9ce6fde5772c32c24 Mon Sep 17 00:00:00 2001 From: Raphael Castaneda Date: Wed, 16 Mar 2016 15:31:50 -0700 Subject: [PATCH 09/15] stashy version 0.3.0 -> 0.3 --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index fe5964f6..41cced7d 100644 --- a/setup.py +++ b/setup.py @@ -14,7 +14,7 @@ requirements = [ 'unidiff', 'github3.py', - 'stashy>=0.3.0', + 'stashy>=0.3', 'xmltodict', 'pyyaml', 'scandir' @@ -36,7 +36,7 @@ include_package_data=True, install_requires=requirements, dependency_links=[ # TODO: Remove dependency_links once stashy is updated on PyPI - 'git+https://github.com/RisingOak/stashy.git#egg=stashy-0.3.0' + 'git+https://github.com/RisingOak/stashy.git#egg=stashy-0.3' ], license="ISCL", zip_safe=False, From 041d2d0782b4f7d14b645394f19226214fbb781d Mon Sep 17 00:00:00 2001 From: Raphael Castaneda Date: Wed, 16 Mar 2016 15:52:00 -0700 Subject: [PATCH 10/15] tell travis to use dependency links --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a3925ee3..8671ce35 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,7 +20,7 @@ env: install: - pip install -U pip - pip install -r requirements_dev.txt -- python setup.py develop +- python setup.py develop --process-dependency-links language: python python: - '3.5' From 235eee4adf32a6c82a75ae5f8d511ed689572906 Mon Sep 17 00:00:00 2001 From: Raphael Castaneda Date: Wed, 16 Mar 2016 15:57:57 -0700 Subject: [PATCH 11/15] Revert "tell travis to use dependency links" This reverts commit 041d2d0782b4f7d14b645394f19226214fbb781d. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8671ce35..a3925ee3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,7 +20,7 @@ env: install: - pip install -U pip - pip install -r requirements_dev.txt -- python setup.py develop --process-dependency-links +- python setup.py develop language: python python: - '3.5' From ad9f6c7a7647e6a402c78e2990015378fe31b981 Mon Sep 17 00:00:00 2001 From: Raphael Castaneda Date: Wed, 23 Mar 2016 10:24:38 -0700 Subject: [PATCH 12/15] offset stash comments up by one line --- inlineplz/interfaces/stash.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inlineplz/interfaces/stash.py b/inlineplz/interfaces/stash.py index 4ee4cace..b861133a 100644 --- a/inlineplz/interfaces/stash.py +++ b/inlineplz/interfaces/stash.py @@ -90,4 +90,4 @@ def position(self, message): if '+' not in hunk_line.line_type: continue if hunk_line.target_line_no == message.line_number: - return hunk_line.target_line_no + return hunk_line.target_line_no - 1 From f371d363b5b839e8d9266ca8efacf3ef51d7b418 Mon Sep 17 00:00:00 2001 From: Raphael Castaneda Date: Thu, 24 Mar 2016 15:19:40 -0700 Subject: [PATCH 13/15] Revert "offset stash comments up by one line" This reverts commit ad9f6c7a7647e6a402c78e2990015378fe31b981. It turns out the offset I saw was due to failing to merge before running inline-plz during my testing --- inlineplz/interfaces/stash.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inlineplz/interfaces/stash.py b/inlineplz/interfaces/stash.py index b861133a..4ee4cace 100644 --- a/inlineplz/interfaces/stash.py +++ b/inlineplz/interfaces/stash.py @@ -90,4 +90,4 @@ def position(self, message): if '+' not in hunk_line.line_type: continue if hunk_line.target_line_no == message.line_number: - return hunk_line.target_line_no - 1 + return hunk_line.target_line_no From 312f33f3ef4a991fa58e24fc5af96c977b97ed61 Mon Sep 17 00:00:00 2001 From: Raphael Castaneda Date: Mon, 18 Apr 2016 10:39:31 -0700 Subject: [PATCH 14/15] comment out stashy requirement --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 915e05c0..bdee4602 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ requirements = [ 'unidiff', 'github3.py', - 'stashy>=0.3', + #'stashy>=0.3', #TODO: Use this instead of dependency_links for stashy 'xmltodict', 'pyyaml', 'scandir' From 3c8a4186ca501ffc12dee44270b3a36d4e9bde8c Mon Sep 17 00:00:00 2001 From: Raphael Castaneda Date: Mon, 18 Apr 2016 11:00:01 -0700 Subject: [PATCH 15/15] only include stash interface when the environment supports it --- inlineplz/interfaces/__init__.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/inlineplz/interfaces/__init__.py b/inlineplz/interfaces/__init__.py index b4fba05c..476a6e69 100644 --- a/inlineplz/interfaces/__init__.py +++ b/inlineplz/interfaces/__init__.py @@ -4,9 +4,17 @@ from __future__ import unicode_literals from inlineplz.interfaces.github import GitHubInterface -from inlineplz.interfaces.stash import StashInterface + +STASH_SUPPORTED = False +try: + from inlineplz.interfaces.stash import StashInterface + STASH_SUPPORTED = True +except ImportError: + pass INTERFACES = { 'github': GitHubInterface, - 'stash': StashInterface } + +if STASH_SUPPORTED: + INTERFACES['stash'] = StashInterface