blob: 12fb1da3d8f5bbc84fc8fb65dd515abf6dc85d14 [file] [log] [blame]
# Copyright (C) 2018 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
import os
import subprocess
LOG = logging.getLogger(__name__)
GIT_SUFFIX = ".git"
class GitCommandException(Exception):
"""Exception thrown by failed git commands."""
def git_dir():
try:
return (
subprocess.run(
["git", "rev-parse", "--git-dir"], capture_output=True, check=True
)
.stdout.decode()
.strip()
)
except subprocess.CalledProcessError:
raise GitCommandException("Unable to find .git directory.")
def commit_id(repo_dir, ref="HEAD"):
try:
cmd = ["git", "rev-parse", "--short", ref]
return (
subprocess.run(cmd, cwd=repo_dir, capture_output=True, check=True)
.stdout.decode()
.strip()
)
except subprocess.CalledProcessError:
raise GitCommandException("Unable to parse current commit ID.")
def add(repo_dir, files=None):
if not files:
files = ["."]
try:
cmd = ["git", "add"]
cmd.extend(files)
subprocess.run(cmd, cwd=repo_dir, capture_output=True, check=True)
except subprocess.CalledProcessError:
raise GitCommandException("Unable to add files to index.")
def commit(repo_dir, message):
try:
cmd = ["git", "commit", "-m", message]
subprocess.run(cmd, cwd=repo_dir, capture_output=True, check=True)
except subprocess.CalledProcessError:
raise GitCommandException("Unable to commit.")
def push(repo_dir, remote, refspec):
try:
cmd = ["git", "push", remote, refspec]
subprocess.run(cmd, cwd=repo_dir, capture_output=True, check=True)
except subprocess.CalledProcessError:
raise GitCommandException("Unable to push.")
def clone(url, target_dir=""):
try:
cmd = ["git", "clone", url, target_dir]
subprocess.run(cmd, capture_output=True, check=True)
if target_dir:
return target_dir
repo_name = url.split("/")[-1]
if repo_name.endswith(GIT_SUFFIX):
repo_name = repo_name[: -len(GIT_SUFFIX)]
return repo_name
except subprocess.CalledProcessError:
raise GitCommandException(f"Unable to clone repo {url}.")
def init(base_dir, repo_name, bare=False):
try:
cmd = ["git", "init"]
if bare:
cmd.append("--bare")
cmd.append(os.path.join(base_dir, repo_name))
subprocess.run(cmd, cwd=base_dir, capture_output=True, check=True)
except subprocess.CalledProcessError:
raise GitCommandException(f"Unable to initialize git repo {repo_name}.")
def pack_refs(repo_dir, all=False):
command = "git pack-refs"
if all:
command += " --all"
try:
subprocess.run(command, cwd=repo_dir, shell=True, check=True)
except subprocess.CalledProcessError as e:
if e.stdout:
LOG.info(e.stdout)
if e.stderr:
LOG.error(e.stderr)
raise GitCommandException(f"Failed to pack refs in {repo_dir}")
def gc(repo_dir, git_config=None, args=None):
cmd = "git "
if git_config:
cmd = cmd + "-c " + " -c ".join(git_config)
cmd += " gc"
if args:
cmd = cmd + " " + " ".join(args)
try:
# Git gc requires a shell to output logs, i.e. `shell` has to be `True`
subprocess.run(cmd, cwd=repo_dir, shell=True, check=True)
except subprocess.CalledProcessError as e:
if e.stdout:
LOG.info(e.stdout)
if e.stderr:
LOG.error(e.stderr)
raise GitCommandException(f"Failed to run gc in {repo_dir}")