1# 2# CDDL HEADER START 3# 4# The contents of this file are subject to the terms of the 5# Common Development and Distribution License (the "License"). 6# You may not use this file except in compliance with the License. 7# 8# See LICENSE.txt included in this distribution for the specific 9# language governing permissions and limitations under the License. 10# 11# When distributing Covered Code, include this CDDL HEADER in each 12# file and include the License file at LICENSE.txt. 13# If applicable, add the following below this CDDL HEADER, with the 14# fields enclosed by brackets "[]" replaced with your own identifying 15# information: Portions Copyright [yyyy] [name of copyright owner] 16# 17# CDDL HEADER END 18# 19 20# 21# Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. 22# Portions Copyright (c) 2020, Krystof Tulinger <k.tulinger@seznam.cz> 23# 24 25from shutil import which 26 27from .repository import Repository, RepositoryException 28from ..utils.command import Command 29 30 31class GitRepository(Repository): 32 def __init__(self, name, logger, path, project, command, env, hooks, timeout): 33 super().__init__(name, logger, path, project, command, env, hooks, timeout) 34 35 self.command = self._repository_command(command, default=lambda: which('git')) 36 37 if not self.command: 38 raise RepositoryException("Cannot get git command") 39 40 def _configure_git_pull(self): 41 # The incoming() check relies on empty output so configure 42 # the repository first to avoid getting extra output. 43 git_command = [self.command, "config", "--local", "pull.ff", "only"] 44 cmd = self.get_command(git_command, work_dir=self.path, 45 env_vars=self.env, logger=self.logger) 46 cmd.execute() 47 if cmd.getretcode() != 0 or cmd.getstate() != Command.FINISHED: 48 cmd.log_error("failed to configure git pull.ff") 49 50 def reposync(self): 51 self._configure_git_pull() 52 return self._run_custom_sync_command([self.command, 'pull', '--ff-only']) 53 54 def incoming_check(self): 55 self._configure_git_pull() 56 return self._run_custom_incoming_command([self.command, 'pull', '--dry-run']) 57 58 def get_branch(self): 59 status, out = self._run_command([self.command, 'branch', '--show-current']) 60 if status != 0: 61 raise RepositoryException("cannot get branch of {}: {}".format(self, out)) 62 63 branch = out.split('\n')[0] 64 65 return branch 66 67 def fetch(self): 68 status, out = self._run_command([self.command, 'fetch']) 69 if status != 0: 70 raise RepositoryException("cannot fetch {}: {}".format(self, out)) 71 72 def strip_outgoing(self): 73 """ 74 Check for outgoing changes and if found, strip them. 75 :return: True if there were any changes stripped, False otherwise. 76 """ 77 self._configure_git_pull() 78 self.fetch() 79 branch = self.get_branch() 80 status, out = self._run_command([self.command, 'log', 81 '--pretty=tformat:%H', '--reverse', 'origin/' + branch + '..']) 82 if status == 0: 83 lines = out.split('\n') 84 if len(lines) == 0: 85 return False 86 87 cset = lines[0] 88 if len(cset) > 0: 89 self.logger.debug("Resetting the repository {} to parent of changeset '{}'". 90 format(self, cset)) 91 status, out = self._run_command([self.command, 'reset', '--hard', 92 cset + '^']) 93 if status != 0: 94 raise RepositoryException("failed to reset {} to parent of changeset {}: {}". 95 format(self, cset, out)) 96 else: 97 return True 98 else: 99 raise RepositoryException("failed to check for outgoing changes in {}: {}". 100 format(self, status)) 101 102 return False 103