# -*- coding: utf-8 -*- """ (c) 2015-2016 - Copyright Red Hat Inc Authors: Pierre-Yves Chibon """ import os import subprocess import pygit2 import pagure import pagure.exceptions def get_pygit2_version(): ''' Return pygit2 version as a tuple of integers. This is needed for correct version comparison. ''' return tuple([int(i) for i in pygit2.__version__.split('.')]) class PagureRepo(pygit2.Repository): """ An utility class allowing to go around pygit2's inability to be stable. """ @staticmethod def push(remote, refname): """ Push the given reference to the specified remote. """ pygit2_version = get_pygit2_version() if pygit2_version >= (0, 22): remote.push([refname]) else: remote.push(refname) def pull(self, remote_name='origin', branch='master', force=False): ''' pull changes for the specified remote (defaults to origin). Code from MichaelBoselowitz at: https://github.com/MichaelBoselowitz/pygit2-examples/blob/ 68e889e50a592d30ab4105a2e7b9f28fac7324c8/examples.py#L58 licensed under the MIT license. ''' for remote in self.remotes: if remote.name == remote_name: 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: return # We can just fastforward elif merge_result & pygit2.GIT_MERGE_ANALYSIS_FASTFORWARD: self.checkout_tree(self.get(remote_master_id)) master_ref = self.lookup_reference( 'refs/heads/%s' % branch) 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.GitConflictsException( 'Pulling remote changes leads to a conflict') else: pagure.LOG.debug( '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 hookfile = os.path.join(self.path, 'hooks', 'post-receive') if not os.path.exists(hookfile): return 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')