12d57dc69SVladimir Kotal# 22d57dc69SVladimir Kotal# CDDL HEADER START 32d57dc69SVladimir Kotal# 42d57dc69SVladimir Kotal# The contents of this file are subject to the terms of the 52d57dc69SVladimir Kotal# Common Development and Distribution License (the "License"). 62d57dc69SVladimir Kotal# You may not use this file except in compliance with the License. 72d57dc69SVladimir Kotal# 82d57dc69SVladimir Kotal# See LICENSE.txt included in this distribution for the specific 92d57dc69SVladimir Kotal# language governing permissions and limitations under the License. 102d57dc69SVladimir Kotal# 112d57dc69SVladimir Kotal# When distributing Covered Code, include this CDDL HEADER in each 122d57dc69SVladimir Kotal# file and include the License file at LICENSE.txt. 132d57dc69SVladimir Kotal# If applicable, add the following below this CDDL HEADER, with the 142d57dc69SVladimir Kotal# fields enclosed by brackets "[]" replaced with your own identifying 152d57dc69SVladimir Kotal# information: Portions Copyright [yyyy] [name of copyright owner] 162d57dc69SVladimir Kotal# 172d57dc69SVladimir Kotal# CDDL HEADER END 182d57dc69SVladimir Kotal# 192d57dc69SVladimir Kotal 202d57dc69SVladimir Kotal# 21f321caadSVladimir Kotal# Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. 222d57dc69SVladimir Kotal# Portions Copyright (c) 2020, Krystof Tulinger <k.tulinger@seznam.cz> 232d57dc69SVladimir Kotal# 242d57dc69SVladimir Kotal 252d57dc69SVladimir Kotalfrom shutil import which 262d57dc69SVladimir Kotal 272d57dc69SVladimir Kotalfrom .repository import Repository, RepositoryException 282d57dc69SVladimir Kotalfrom ..utils.command import Command 292d57dc69SVladimir Kotal 302d57dc69SVladimir Kotal 312d57dc69SVladimir Kotalclass GitRepository(Repository): 32ae5b3cb8SVladimir Kotal def __init__(self, name, logger, path, project, command, env, hooks, timeout): 33ae5b3cb8SVladimir Kotal super().__init__(name, logger, path, project, command, env, hooks, timeout) 342d57dc69SVladimir Kotal 352d57dc69SVladimir Kotal self.command = self._repository_command(command, default=lambda: which('git')) 362d57dc69SVladimir Kotal 372d57dc69SVladimir Kotal if not self.command: 382d57dc69SVladimir Kotal raise RepositoryException("Cannot get git command") 392d57dc69SVladimir Kotal 40ae5b3cb8SVladimir Kotal def _configure_git_pull(self): 412d57dc69SVladimir Kotal # The incoming() check relies on empty output so configure 422d57dc69SVladimir Kotal # the repository first to avoid getting extra output. 432d57dc69SVladimir Kotal git_command = [self.command, "config", "--local", "pull.ff", "only"] 44ae5b3cb8SVladimir Kotal cmd = self.get_command(git_command, work_dir=self.path, 452d57dc69SVladimir Kotal env_vars=self.env, logger=self.logger) 462d57dc69SVladimir Kotal cmd.execute() 472d57dc69SVladimir Kotal if cmd.getretcode() != 0 or cmd.getstate() != Command.FINISHED: 482d57dc69SVladimir Kotal cmd.log_error("failed to configure git pull.ff") 492d57dc69SVladimir Kotal 502d57dc69SVladimir Kotal def reposync(self): 51ae5b3cb8SVladimir Kotal self._configure_git_pull() 522d57dc69SVladimir Kotal return self._run_custom_sync_command([self.command, 'pull', '--ff-only']) 532d57dc69SVladimir Kotal 542d57dc69SVladimir Kotal def incoming_check(self): 55ae5b3cb8SVladimir Kotal self._configure_git_pull() 562d57dc69SVladimir Kotal return self._run_custom_incoming_command([self.command, 'pull', '--dry-run']) 57f321caadSVladimir Kotal 58b2d60571SVladimir Kotal def get_branch(self): 59b2d60571SVladimir Kotal status, out = self._run_command([self.command, 'branch', '--show-current']) 60b2d60571SVladimir Kotal if status != 0: 61b2d60571SVladimir Kotal raise RepositoryException("cannot get branch of {}: {}".format(self, out)) 62b2d60571SVladimir Kotal 63b2d60571SVladimir Kotal branch = out.split('\n')[0] 64b2d60571SVladimir Kotal 65b2d60571SVladimir Kotal return branch 66b2d60571SVladimir Kotal 67*f8b2d387SVladimir Kotal def fetch(self): 68*f8b2d387SVladimir Kotal status, out = self._run_command([self.command, 'fetch']) 69*f8b2d387SVladimir Kotal if status != 0: 70*f8b2d387SVladimir Kotal raise RepositoryException("cannot fetch {}: {}".format(self, out)) 71*f8b2d387SVladimir Kotal 72f321caadSVladimir Kotal def strip_outgoing(self): 73*f8b2d387SVladimir Kotal """ 74*f8b2d387SVladimir Kotal Check for outgoing changes and if found, strip them. 75*f8b2d387SVladimir Kotal :return: True if there were any changes stripped, False otherwise. 76*f8b2d387SVladimir Kotal """ 77f321caadSVladimir Kotal self._configure_git_pull() 78*f8b2d387SVladimir Kotal self.fetch() 79b2d60571SVladimir Kotal branch = self.get_branch() 80f321caadSVladimir Kotal status, out = self._run_command([self.command, 'log', 81b2d60571SVladimir Kotal '--pretty=tformat:%H', '--reverse', 'origin/' + branch + '..']) 82f321caadSVladimir Kotal if status == 0: 83673b41abSVladimir Kotal lines = out.split('\n') 84673b41abSVladimir Kotal if len(lines) == 0: 85673b41abSVladimir Kotal return False 86673b41abSVladimir Kotal 87673b41abSVladimir Kotal cset = lines[0] 88673b41abSVladimir Kotal if len(cset) > 0: 89673b41abSVladimir Kotal self.logger.debug("Resetting the repository {} to parent of changeset '{}'". 90f321caadSVladimir Kotal format(self, cset)) 91f321caadSVladimir Kotal status, out = self._run_command([self.command, 'reset', '--hard', 92f321caadSVladimir Kotal cset + '^']) 93f321caadSVladimir Kotal if status != 0: 94f321caadSVladimir Kotal raise RepositoryException("failed to reset {} to parent of changeset {}: {}". 95f321caadSVladimir Kotal format(self, cset, out)) 96f321caadSVladimir Kotal else: 97f321caadSVladimir Kotal return True 98f321caadSVladimir Kotal else: 99f321caadSVladimir Kotal raise RepositoryException("failed to check for outgoing changes in {}: {}". 100f321caadSVladimir Kotal format(self, status)) 101673b41abSVladimir Kotal 102673b41abSVladimir Kotal return False 103