From 21522bb78d630e0575c36e83d96995c8ae625364 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Aug 27 2015 12:16:14 +0000 Subject: [PATCH 1/5] Make repo.pull() raise a specific exception when there is a conflict When pulling from upstream leads to the situation where there is a conflict in the repo, repo.pull() will now raise a specific exception for this. --- diff --git a/pagure/exceptions.py b/pagure/exceptions.py index 611f25e..8927952 100644 --- a/pagure/exceptions.py +++ b/pagure/exceptions.py @@ -50,3 +50,10 @@ class PagureEvException(PagureException): ''' Exceptions used in the pagure-stream-server. ''' pass + + +class GitConflictsException(PagureException): + ''' Exception used when trying to pull on a repo and that leads to + conflicts. + ''' + pass diff --git a/pagure/lib/repo.py b/pagure/lib/repo.py index f887e97..5f83871 100644 --- a/pagure/lib/repo.py +++ b/pagure/lib/repo.py @@ -55,7 +55,7 @@ class PagureRepo(pygit2.Repository): master_ref.set_target(remote_master_id) self.head.set_target(remote_master_id) elif merge_result & pygit2.GIT_MERGE_ANALYSIS_NORMAL: - raise pagure.exceptions.PagureException( + raise pagure.exceptions.GitConflictsException( 'Pulling remote changes leads to a conflict') else: pagure.LOG.debug( From c16b65041b0ac37bf3e9bf7ec88b0a3ece559416 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Aug 27 2015 12:16:14 +0000 Subject: [PATCH 2/5] Increase debugging and re-clone if there is a conflict when pulling If when we pull from a remote git repo we end up in a situation where there is a conflict (for example the user forced-push a new commit), then we should just drop our current clone and re-clone the repo. --- diff --git a/pagure/__init__.py b/pagure/__init__.py index befecc5..3bdbd03 100644 --- a/pagure/__init__.py +++ b/pagure/__init__.py @@ -19,6 +19,7 @@ __api_version__ = '0.5' import datetime import logging import os +import shutil import subprocess import urlparse from logging.handlers import SMTPHandler @@ -415,7 +416,7 @@ def get_repo_path(repo): return repopath -def get_remote_repo_path(remote_git, branch_from): +def get_remote_repo_path(remote_git, branch_from, loop=False): """ Return the path of the remote git repository corresponding to the provided information. """ @@ -436,7 +437,27 @@ def get_remote_repo_path(remote_git, branch_from): repo = pagure.lib.repo.PagureRepo(repopath) try: repo.pull(branch=branch_from) + except pagure.exceptions.GitConflictsException as err: + # In this case, we drop the repo and re-try + try: + shutil.rmtree(repopath) + except Exception as err: + LOG.debug(err) + LOG.exception(err) + flask.abort(500, err.message) + + if loop: + # Let's be sure we don't run into an infinite loop + LOG.debug(err) + LOG.exception(err) + flask.abort(500, err.message) + else: + return get_remote_repo_path( + remote_git, branch_from, loop=True) + except pagure.exceptions.PagureException as err: + LOG.debug(err) + LOG.exception(err) flask.abort(500, err.message) return repopath From c4c8bc2f3df0c69ae1a6031c6c1615d56a0eb291 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Aug 27 2015 12:16:14 +0000 Subject: [PATCH 3/5] Allow repo.pull() to force the pull if desired --- diff --git a/pagure/lib/repo.py b/pagure/lib/repo.py index 5f83871..c8a0661 100644 --- a/pagure/lib/repo.py +++ b/pagure/lib/repo.py @@ -29,7 +29,7 @@ class PagureRepo(pygit2.Repository): else: remote.push(refname) - def pull(self, remote_name='origin', branch='master'): + def pull(self, remote_name='origin', branch='master', force=False): ''' pull changes for the specified remote (defaults to origin). Code from MichaelBoselowitz at: @@ -43,6 +43,12 @@ class PagureRepo(pygit2.Repository): remote.fetch() remote_master_id = self.lookup_reference( 'refs/remotes/origin/%s' % branch).target + + if force: + repo_branch = self.lookup_reference( + 'refs/heads/%s' % branch) + repo_branch.set_target(remote_master_id) + merge_result, _ = self.merge_analysis(remote_master_id) # Up to date, do nothing if merge_result & pygit2.GIT_MERGE_ANALYSIS_UP_TO_DATE: From b7983c5275155fce53f23d04b29ef0290e9598e2 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Aug 27 2015 12:16:14 +0000 Subject: [PATCH 4/5] To handle forced commits, we can just force the pull We'll always do it as we want to have the latest content in the repo --- diff --git a/pagure/__init__.py b/pagure/__init__.py index 3bdbd03..af32587 100644 --- a/pagure/__init__.py +++ b/pagure/__init__.py @@ -436,25 +436,7 @@ def get_remote_repo_path(remote_git, branch_from, loop=False): else: repo = pagure.lib.repo.PagureRepo(repopath) try: - repo.pull(branch=branch_from) - except pagure.exceptions.GitConflictsException as err: - # In this case, we drop the repo and re-try - try: - shutil.rmtree(repopath) - except Exception as err: - LOG.debug(err) - LOG.exception(err) - flask.abort(500, err.message) - - if loop: - # Let's be sure we don't run into an infinite loop - LOG.debug(err) - LOG.exception(err) - flask.abort(500, err.message) - else: - return get_remote_repo_path( - remote_git, branch_from, loop=True) - + repo.pull(branch=branch_from, force=True) except pagure.exceptions.PagureException as err: LOG.debug(err) LOG.exception(err) From 06df02c931ac3c3606aff527addf46097767f720 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Aug 27 2015 12:16:14 +0000 Subject: [PATCH 5/5] Remove un-necessary import --- diff --git a/pagure/__init__.py b/pagure/__init__.py index af32587..83775a1 100644 --- a/pagure/__init__.py +++ b/pagure/__init__.py @@ -19,7 +19,6 @@ __api_version__ = '0.5' import datetime import logging import os -import shutil import subprocess import urlparse from logging.handlers import SMTPHandler