From 54c4f38d20bf556a7937707da310f82b3a8232df Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Aug 24 2016 09:13:23 +0000 Subject: [PATCH 1/7] Add the possibility for PagureRepo to run post-receive hook when asked --- diff --git a/pagure/lib/repo.py b/pagure/lib/repo.py index fbdbe95..6496b4e 100644 --- a/pagure/lib/repo.py +++ b/pagure/lib/repo.py @@ -1,13 +1,15 @@ # -*- coding: utf-8 -*- """ - (c) 2015 - Copyright Red Hat Inc + (c) 2015-2016 - Copyright Red Hat Inc Authors: Pierre-Yves Chibon """ +import os +import subprocess import pygit2 @@ -76,3 +78,27 @@ class PagureRepo(pygit2.Repository): 'Un-expected merge result: %s' % ( pygit2.GIT_MERGE_ANALYSIS_NORMAL)) raise AssertionError('Unknown merge analysis result') + + def run_hook(self, old, new, ref, username): + ''' Runs the post-update hook on the repo. ''' + line = '%s %s %s\n' % (old, new, ref) + cmd = ['./hooks/post-receive'] + env = os.environ.copy() + env['GIT_DIR'] = self.path + env['GL_USER'] = username + + procs = subprocess.Popen( + cmd, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + cwd=self.path, + env=env, + ) + (out, err) = procs.communicate(line) + retcode = procs.wait() + if retcode: + print 'ERROR: %s =-- %s' % (cmd, retcode) + print out + print err + out = out.rstrip('\n\r') From 5a8c6a1431bde96099c3627f2ea347ed5db23fda Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Aug 24 2016 09:13:23 +0000 Subject: [PATCH 2/7] Upon merging a pull-request, call the post-receive hook --- diff --git a/pagure/lib/git.py b/pagure/lib/git.py index 524b1c3..ceba03a 100644 --- a/pagure/lib/git.py +++ b/pagure/lib/git.py @@ -1044,20 +1044,21 @@ def merge_pull_request( mergecode & pygit2.GIT_MERGE_ANALYSIS_FASTFORWARD)): if domerge: + head = new_repo.lookup_reference('HEAD').get_object() if not request.project.settings.get('always_merge', False): if merge is not None: # This is depending on the pygit2 version branch_ref.target = merge.fastforward_oid elif merge is None and mergecode is not None: branch_ref.set_target(repo_commit.oid.hex) + commit = repo_commit.oid.hex else: tree = new_repo.index.write_tree() - head = new_repo.lookup_reference('HEAD').get_object() user_obj = pagure.lib.__get_user(session, username) author = pygit2.Signature( user_obj.fullname.encode('utf-8'), user_obj.default_email.encode('utf-8')) - new_repo.create_commit( + commit = new_repo.create_commit( 'refs/heads/%s' % request.branch, author, author, @@ -1066,6 +1067,9 @@ def merge_pull_request( [head.hex, repo_commit.oid.hex]) PagureRepo.push(ori_remote, refname) + fork_obj.run_hook( + head.hex, commit, 'refs/heads/%s' % request.branch, + username) else: request.merge_status = 'FFORWARD' session.commit() @@ -1091,14 +1095,18 @@ def merge_pull_request( author = pygit2.Signature( user_obj.fullname.encode('utf-8'), user_obj.default_email.encode('utf-8')) - new_repo.create_commit( + commit = new_repo.create_commit( 'refs/heads/%s' % request.branch, author, author, 'Merge #%s `%s`' % (request.id, request.title), tree, [head.hex, repo_commit.oid.hex]) + PagureRepo.push(ori_remote, refname) + fork_obj.run_hook( + head.hex, commit, 'refs/heads/%s' % request.branch, + username) else: request.merge_status = 'MERGE' From 34d7f2c222dbc9c88aeee5e74830a05ece1cb059 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Aug 24 2016 09:13:23 +0000 Subject: [PATCH 3/7] Adjust the pagure_hook to only run on the main branch This will avoid re-closing a ticket when rebasing a branch --- diff --git a/pagure/hooks/files/pagure_hook.py b/pagure/hooks/files/pagure_hook.py index 16963ec..58579e9 100755 --- a/pagure/hooks/files/pagure_hook.py +++ b/pagure/hooks/files/pagure_hook.py @@ -8,6 +8,8 @@ relates to an issue. import os import sys +import pygit2 + from sqlalchemy.exc import SQLAlchemyError if 'PAGURE_CONFIG' not in os.environ \ @@ -129,34 +131,27 @@ def fixes_relation(commitid, relation, app_url=None): pagure.SESSION.rollback() pagure.APP.logger.exception(err) - branches = [ - item.replace('* ', '') - for item in pagure.lib.git.read_git_lines( - ['branch', '--contains', commitid], abspath) - ] - - if 'master' in branches: - try: - if relation.isa == 'issue': - pagure.lib.edit_issue( - pagure.SESSION, - relation, - ticketfolder=pagure.APP.config['TICKETS_FOLDER'], - user=pagure.lib.git.get_author_email(commitid, abspath), - status='Fixed') - elif relation.isa == 'pull-request': - pagure.lib.close_pull_request( - pagure.SESSION, - relation, - requestfolder=pagure.APP.config['REQUESTS_FOLDER'], - user=pagure.lib.git.get_author_email(commitid, abspath), - merged=True) - pagure.SESSION.commit() - except pagure.exceptions.PagureException as err: - print err - except SQLAlchemyError as err: # pragma: no cover - pagure.SESSION.rollback() - pagure.APP.logger.exception(err) + try: + if relation.isa == 'issue': + pagure.lib.edit_issue( + pagure.SESSION, + relation, + ticketfolder=pagure.APP.config['TICKETS_FOLDER'], + user=pagure.lib.git.get_author_email(commitid, abspath), + status='Fixed') + elif relation.isa == 'pull-request': + pagure.lib.close_pull_request( + pagure.SESSION, + relation, + requestfolder=pagure.APP.config['REQUESTS_FOLDER'], + user=pagure.lib.git.get_author_email(commitid, abspath), + merged=True) + pagure.SESSION.commit() + except pagure.exceptions.PagureException as err: + print err + except SQLAlchemyError as err: # pragma: no cover + pagure.SESSION.rollback() + pagure.APP.logger.exception(err) def run_as_post_receive_hook(): @@ -174,6 +169,17 @@ def run_as_post_receive_hook(): print ' -- Ref name' print refname + # Retrieve the default branch + repo_obj = pygit2.Repository(abspath) + default_branch = None + if not repo_obj.is_empty and not repo_obj.head_is_unborn: + default_branch = repo_obj.head.shorthand + + # Skip all branch but the default one + refname = refname.replace('refs/heads/', '') + if refname != default_branch: + continue + if set(newrev) == set(['0']): print "Deleting a reference/branch, so we won't run the "\ "pagure hook" From 976a0e08a0900af9d9cc46163c6957e1404d6552 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Aug 24 2016 09:13:23 +0000 Subject: [PATCH 4/7] Adjust the comment so that it uses the user's username Otherwise it was using the specified key which could either be the username or an email address. --- diff --git a/pagure/lib/__init__.py b/pagure/lib/__init__.py index 03efeca..54f67c1 100644 --- a/pagure/lib/__init__.py +++ b/pagure/lib/__init__.py @@ -1291,7 +1291,8 @@ def edit_issue(session, issue, ticketfolder, user, add_issue_comment( session, issue, - comment='@%s changed the status to ``%s``' % (user, status), + comment='@%s changed the status to ``%s``' % ( + user_obj.username, status), user=user, ticketfolder=ticketfolder, notify=False, From 477d8f7ff92b4c70fd2ff6ab545871cf1eb8189b Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Aug 24 2016 09:13:24 +0000 Subject: [PATCH 5/7] Build the URL to the user's page by hand instead of relying on flask This is most useful for when adding a comment to a PR/ticket via a hook action. --- diff --git a/pagure/pfmarkdown.py b/pagure/pfmarkdown.py index 9068b6a..f4762b8 100644 --- a/pagure/pfmarkdown.py +++ b/pagure/pfmarkdown.py @@ -49,7 +49,10 @@ class MentionPattern(markdown.inlinepatterns.Pattern): return text element = markdown.util.etree.Element("a") - url = flask.url_for('view_user', username=name) + base_url = pagure.APP.config['APP_URL'] + if base_url.endswith('/'): + base_url = base_url[:-1] + url = '%s/user/%s' % (base_url, user.username) element.set('href', url) element.text = text return element From e6bff32139f600ae7c45633b38703bb43477790f Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Aug 24 2016 09:13:24 +0000 Subject: [PATCH 6/7] Do not try to run the post-receive hook is none are installed --- diff --git a/pagure/lib/repo.py b/pagure/lib/repo.py index 6496b4e..1b77330 100644 --- a/pagure/lib/repo.py +++ b/pagure/lib/repo.py @@ -87,6 +87,10 @@ class PagureRepo(pygit2.Repository): env['GIT_DIR'] = self.path env['GL_USER'] = username + hookfile = os.path.join(self.path, 'hooks', 'post-receive') + if not os.path.exists(hookfile): + return + procs = subprocess.Popen( cmd, stdin=subprocess.PIPE, From cfaec6a4b97013e52c0ccf1679d0346072d05610 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Aug 24 2016 09:13:24 +0000 Subject: [PATCH 7/7] Adjust the unit-tests for the change in the markdown processor --- diff --git a/tests/test_pagure_flask_ui_issues.py b/tests/test_pagure_flask_ui_issues.py index 6907faa..8ab1e3f 100644 --- a/tests/test_pagure_flask_ui_issues.py +++ b/tests/test_pagure_flask_ui_issues.py @@ -534,8 +534,9 @@ class PagureFlaskIssuestests(tests.Modeltests): '' in output.data) self.assertIn( - '

@pingou ' - 'changed the status to Fixed

', + '

' + '@pingou changed the status to Fixed' + '

', output.data) # Add new comment