109 lines
3.5 KiB
Python
109 lines
3.5 KiB
Python
|
# -*- coding: utf-8 -*-
|
||
|
|
||
|
"""
|
||
|
(c) 2015-2016 - Copyright Red Hat Inc
|
||
|
|
||
|
Authors:
|
||
|
Pierre-Yves Chibon <pingou@pingoured.fr>
|
||
|
|
||
|
"""
|
||
|
|
||
|
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')
|