blob: fa09880cdec27e773ced8e52086b9452ca7b5f00 [file] [log] [blame]
# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Git support functions."""
from errors import FatalError
import fnmatch
import os.path
import subprocess
def Git(subcommand, *args):
"""Runs "git <subcommand> <args...>" and returns the output, including
standard error. Raises |OSError| if it fails to run git at all and
|subprocess.CalledProcessError| if the command returns failure (nonzero)."""
return subprocess.check_output(
('git', subcommand) + args, stderr=subprocess.STDOUT)
def SanityCheckGit():
"""Does a sanity check that git is available and the current working directory
is in a git repository (exits with an error message on failure)."""
try:
Git("status")
except OSError:
FatalError("failed to run git -- is it in your PATH?")
except subprocess.CalledProcessError:
FatalError("\"git status\" failed -- is %s in a git repository?" %
os.getcwd())
def IsGitTreeDirty():
"""Checks if the tree looks dirty (returning true if it is)."""
try:
Git("diff-index", "--quiet", "HEAD")
except subprocess.CalledProcessError:
return True
return False
def GitLsFiles(path, recursive=True, exclude_file_patterns=None,
exclude_path_patterns=None):
"""Returns a list of files under the given path (the filenames will include
the full path). If |recursive| is true (the default), then this list will
include all files (recursively); if not, it will only include the files "at"
the exact path. |exclude_file_patterns| may be a list of shell-style wildcards
of filenames to exclude. Similarly, |exclude_path_patterns| may be a list of
shell-style wildcards of paths to exclude (note: to make it easier to match
subtrees, a trailing '/' is added to the path for matching purposes)."""
# Files are "null-terminated". This results in an extra empty string at the
# end. "Luckily", in the empty case, we also get an empty string.
result = Git("ls-files", "-z", path).split("\0")[:-1]
if not recursive:
result = [f for f in result if os.path.dirname(f) == path]
if exclude_file_patterns:
for p in exclude_file_patterns:
result = [f for f in result
if not fnmatch.fnmatch(os.path.basename(f), p)]
if exclude_path_patterns:
for p in exclude_path_patterns:
result = [f for f in result
if not fnmatch.fnmatch(os.path.dirname(f) + "/", p)]
return result