From dbf3e1ffa8ddd841364019c6b8a3d13cba8d4f15 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: May 29 2015 08:52:49 +0000 Subject: [PATCH 1/4] Create the pagure.lib.git.diff_pull_request method This method can be used to retrieve the list of commits differing between two specified git repos of a specified request. This method also update the pull-request info in the database to update the start and stop commit stored there. --- diff --git a/pagure/lib/git.py b/pagure/lib/git.py index ad50596..717a962 100644 --- a/pagure/lib/git.py +++ b/pagure/lib/git.py @@ -836,3 +836,65 @@ def merge_pull_request(session, repo, request, username, request_folder): shutil.rmtree(newpath) return 'Changes merged!' + + +def diff_pull_request(session, request, repo_obj, orig_repo, requestfolder): + """ Returns the diff and the list of commits between the two git repos + mentionned in the given pull-request. + """ + + commitid = None + diff = None + diff_commits = [] + branch = repo_obj.lookup_branch(request.branch_from) + if branch: + commitid = branch.get_object().hex + + if not repo_obj.is_empty and not orig_repo.is_empty: + # Pull-request open + master_commits = [ + commit.oid.hex + for commit in orig_repo.walk( + orig_repo.lookup_branch(request.branch).get_object().hex, + pygit2.GIT_SORT_TIME) + ] + for commit in repo_obj.walk(commitid, pygit2.GIT_SORT_TIME): + if request.status and commit.oid.hex in master_commits: + break + diff_commits.append(commit) + + if request.status and diff_commits: + request.commit_start = diff_commits[-1].oid.hex + request.commit_stop = diff_commits[0].oid.hex + session.add(request) + session.commit() + pagure.lib.git.update_git( + request, repo=request.project, + repofolder=requestfolder) + + if diff_commits: + first_commit = repo_obj[diff_commits[-1].oid.hex] + diff = repo_obj.diff( + repo_obj.revparse_single(first_commit.parents[0].oid.hex), + repo_obj.revparse_single(diff_commits[0].oid.hex) + ) + + elif orig_repo.is_empty and not repo_obj.is_empty: + for commit in repo_obj.walk(commitid, pygit2.GIT_SORT_TIME): + diff_commits.append(commit) + if request.status and diff_commits: + request.commit_start = diff_commits[-1].oid.hex + request.commit_stop = diff_commits[0].oid.hex + session.add(request) + session.commit() + pagure.lib.git.update_git( + request, repo=request.project, + repofolder=requestfolder) + + repo_commit = repo_obj[request.commit_stop] + diff = repo_commit.tree.diff_to_tree(swap=True) + else: + raise pagure.exceptions.PagureException( + 'Fork is empty, there are no commits to request pulling') + + return (diff_commits, diff) diff --git a/pagure/ui/fork.py b/pagure/ui/fork.py index e9bdbc2..6f4ee34 100644 --- a/pagure/ui/fork.py +++ b/pagure/ui/fork.py @@ -16,11 +16,12 @@ import tempfile import pygit2 from sqlalchemy.exc import SQLAlchemyError +import pagure import pagure.doc_utils +import pagure.exceptions import pagure.lib import pagure.lib.git import pagure.forms -import pagure from pagure import (APP, SESSION, LOG, cla_required, is_repo_admin, generate_gitolite_acls) @@ -141,76 +142,20 @@ def request_pull(repo, requestid, username=None): repo_obj.revparse_single(diff_commits[0].oid.hex) ) else: - commitid = None - branch = repo_obj.lookup_branch(request.branch_from) - if branch: - commitid = branch.get_object().hex - - if not repo_obj.is_empty and not orig_repo.is_empty: - # Pull-request open - master_commits = [ - commit.oid.hex - for commit in orig_repo.walk( - orig_repo.lookup_branch(request.branch).get_object().hex, - pygit2.GIT_SORT_TIME) - ] - for commit in repo_obj.walk(commitid, pygit2.GIT_SORT_TIME): - if request.status and commit.oid.hex in master_commits: - break - diff_commits.append(commit) - - if request.status and diff_commits: - first_commit = repo_obj[diff_commits[-1].oid.hex] - request.commit_start = first_commit.oid.hex - request.commit_stop = diff_commits[0].oid.hex - SESSION.add(request) - try: - SESSION.commit() - pagure.lib.git.update_git( - request, repo=request.project, - repofolder=APP.config['REQUESTS_FOLDER']) - except SQLAlchemyError as err: # pragma: no cover - SESSION.rollback() - APP.logger.exception(err) - flask.flash( - 'Could not update this pull-request in the database', - 'error') - - if diff_commits: - first_commit = repo_obj[diff_commits[-1].oid.hex] - diff = repo_obj.diff( - repo_obj.revparse_single(first_commit.parents[0].oid.hex), - repo_obj.revparse_single(diff_commits[0].oid.hex) - ) - - elif orig_repo.is_empty and not repo_obj.is_empty: - for commit in repo_obj.walk(commitid, pygit2.GIT_SORT_TIME): - diff_commits.append(commit) - if request.status and diff_commits: - first_commit = repo_obj[diff_commits[-1].oid.hex] - request.commit_start = first_commit.oid.hex - request.commit_stop = diff_commits[0].oid.hex - SESSION.add(request) - try: - SESSION.commit() - pagure.lib.git.update_git( - request, repo=request.project, - repofolder=APP.config['REQUESTS_FOLDER']) - except SQLAlchemyError as err: # pragma: no cover - SESSION.rollback() - APP.logger.exception(err) - flask.flash( - 'Could not update this pull-request in the database', - 'error') - - repo_commit = repo_obj[request.commit_stop] - diff = repo_commit.tree.diff_to_tree(swap=True) - else: - flask.flash( - 'Fork is empty, there are no commits to request pulling', - 'error') + try: + diff_commits, diff = pagure.lib.git.diff_pull_request( + SESSION, request, repo_obj, orig_repo, + requestfolder=APP.config['REQUESTS_FOLDER']) + except pagure.exceptions.PagureException as err: + flask.flash(err.message, 'error') return flask.redirect(flask.url_for( 'view_repo', username=username, repo=repo.name)) + except SQLAlchemyError as err: # pragma: no cover + SESSION.rollback() + APP.logger.exception(err) + flask.flash( + 'Could not update this pull-request in the database', + 'error') form = pagure.forms.ConfirmationForm() From d9d77c03161c899c1c9db750b4c808f4e5c6343f Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: May 29 2015 08:52:49 +0000 Subject: [PATCH 2/4] Make the diff_pull_request generate a diff only if desired --- diff --git a/pagure/lib/git.py b/pagure/lib/git.py index 717a962..3149e3d 100644 --- a/pagure/lib/git.py +++ b/pagure/lib/git.py @@ -838,7 +838,9 @@ def merge_pull_request(session, repo, request, username, request_folder): return 'Changes merged!' -def diff_pull_request(session, request, repo_obj, orig_repo, requestfolder): +def diff_pull_request( + session, request, repo_obj, orig_repo, requestfolder, + with_diff=True): """ Returns the diff and the list of commits between the two git repos mentionned in the given pull-request. """ @@ -864,7 +866,8 @@ def diff_pull_request(session, request, repo_obj, orig_repo, requestfolder): diff_commits.append(commit) if request.status and diff_commits: - request.commit_start = diff_commits[-1].oid.hex + first_commit = repo_obj[diff_commits[-1].oid.hex] + request.commit_start = first_commit.oid.hex request.commit_stop = diff_commits[0].oid.hex session.add(request) session.commit() @@ -872,10 +875,9 @@ def diff_pull_request(session, request, repo_obj, orig_repo, requestfolder): request, repo=request.project, repofolder=requestfolder) - if diff_commits: - first_commit = repo_obj[diff_commits[-1].oid.hex] + if diff_commits and with_diff: diff = repo_obj.diff( - repo_obj.revparse_single(first_commit.parents[0].oid.hex), + repo_obj.revparse_single(diff_commits[-1].parents[0].oid.hex), repo_obj.revparse_single(diff_commits[0].oid.hex) ) @@ -883,7 +885,8 @@ def diff_pull_request(session, request, repo_obj, orig_repo, requestfolder): for commit in repo_obj.walk(commitid, pygit2.GIT_SORT_TIME): diff_commits.append(commit) if request.status and diff_commits: - request.commit_start = diff_commits[-1].oid.hex + first_commit = repo_obj[diff_commits[-1].oid.hex] + request.commit_start = first_commit.oid.hex request.commit_stop = diff_commits[0].oid.hex session.add(request) session.commit() @@ -892,7 +895,8 @@ def diff_pull_request(session, request, repo_obj, orig_repo, requestfolder): repofolder=requestfolder) repo_commit = repo_obj[request.commit_stop] - diff = repo_commit.tree.diff_to_tree(swap=True) + if with_diff: + diff = repo_commit.tree.diff_to_tree(swap=True) else: raise pagure.exceptions.PagureException( 'Fork is empty, there are no commits to request pulling') From a8e3e53c1e98fcdee42eaf471ef27a6b3942cf9a Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: May 29 2015 08:52:49 +0000 Subject: [PATCH 3/4] Adjust the request_pull_patch endpoint to rely on pagure.lib.git.diff_pull_request --- diff --git a/pagure/ui/fork.py b/pagure/ui/fork.py index 6f4ee34..7739460 100644 --- a/pagure/ui/fork.py +++ b/pagure/ui/fork.py @@ -206,55 +206,28 @@ def request_pull_patch(repo, requestid, username=None): commitid = branch.get_object().hex diff_commits = [] - if not repo_obj.is_empty and not orig_repo.is_empty: - - # Closed pull-request - if request.status is False: - commitid = request.commit_stop - for commit in repo_obj.walk(commitid, pygit2.GIT_SORT_TIME): - diff_commits.append(commit) - if commit.oid.hex == request.commit_start: - break - # Pull-request open - else: - master_commits = [ - commit.oid.hex - for commit in orig_repo.walk( - orig_repo.lookup_branch(request.branch).get_object().hex, - pygit2.GIT_SORT_TIME) - ] - for commit in repo_obj.walk(commitid, pygit2.GIT_SORT_TIME): - if request.status and commit.oid.hex in master_commits: - break - diff_commits.append(commit) - - elif orig_repo.is_empty and not repo_obj.is_empty: + if request.status is False: + commitid = request.commit_stop for commit in repo_obj.walk(commitid, pygit2.GIT_SORT_TIME): diff_commits.append(commit) - if request.status and diff_commits: - first_commit = repo_obj[diff_commits[-1].oid.hex] - request.commit_start = first_commit.oid.hex - request.commit_stop = diff_commits[0].oid.hex - SESSION.add(request) - try: - SESSION.commit() - pagure.lib.git.update_git( - request, repo=request.project, - repofolder=APP.config['REQUESTS_FOLDER']) - except SQLAlchemyError as err: # pragma: no cover - SESSION.rollback() - APP.logger.exception(err) - flask.flash( - 'Could not update this pull-request in the database', - 'error') - - repo_commit = repo_obj[request.commit_stop] + if commit.oid.hex == request.commit_start: + break else: - flask.flash( - 'Fork is empty, there are no commits to request pulling', - 'error') - return flask.redirect(flask.url_for( - 'view_repo', username=username, repo=repo.name)) + try: + diff_commits, diff = pagure.lib.git.diff_pull_request( + SESSION, request, repo_obj, orig_repo, + requestfolder=APP.config['REQUESTS_FOLDER'], + with_diff=False) + except pagure.exceptions.PagureException as err: + flask.flash(err.message, 'error') + return flask.redirect(flask.url_for( + 'view_repo', username=username, repo=repo.name)) + except SQLAlchemyError as err: # pragma: no cover + SESSION.rollback() + APP.logger.exception(err) + flask.flash( + 'Could not update this pull-request in the database', + 'error') diff_commits.reverse() patch = pagure.lib.git.commit_to_patch(repo_obj, diff_commits) From d10db0eb0a45d06383e5b590e51be7b0d0869777 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: May 29 2015 08:52:49 +0000 Subject: [PATCH 4/4] Make sure we update the information in the DB one last time before merging --- diff --git a/pagure/lib/git.py b/pagure/lib/git.py index 3149e3d..c3b55ab 100644 --- a/pagure/lib/git.py +++ b/pagure/lib/git.py @@ -747,6 +747,11 @@ def merge_pull_request(session, repo, request, username, request_folder): newpath = tempfile.mkdtemp(prefix='pagure-pr-merge') new_repo = pygit2.clone_repository(parentpath, newpath) + # Update the start and stop commits in the DB, one last time + pagure.lib.git.diff_pull_request( + session, request, new_repo, fork_obj, + requestfolder=request_folder, with_diff=False) + repo_commit = fork_obj[ fork_obj.lookup_branch(request.branch_from).get_object().hex]