blob: d8b1f4ccb7a523ee84000a1b39a6a9a5f5cf8a16 [file] [log] [blame]
# Lint as: python3
# Copyright 2020 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 utility functions.'''
import os
import subprocess
import sys
from typing import List, Optional
def get_head_hash(git_src: str) -> str:
'''Gets the repository's head hash.'''
return run_command(['git', 'rev-parse', 'HEAD'], cwd=git_src)
def get_last_commit_date(git_src: str) -> str:
'''Gets the repository's time of last commit.'''
return run_command(['git', 'log', '-1', '--format=%ct'], cwd=git_src)
def get_total_lines_of_code(git_src: str, subdirectory: str) -> int:
'''Gets the number of lines contained in the git directory.'''
filepaths = _run_ls_files_command(subdirectory, git_src)
total_loc = 0
for filepath in filepaths:
with open(filepath, 'rb') as f:
total_loc += sum(1 for line in f)
return total_loc
def get_total_files(git_src: str, subdirectory: str) -> int:
'''Gets the number of files contained in the git directory.'''
filepaths = _run_ls_files_command(subdirectory, git_src)
return len(filepaths)
def _run_ls_files_command(subdirectory: Optional[str],
git_src: str) -> List[str]:
command = _build_ls_files_command(subdirectory)
filepath_str = run_command(command, cwd=git_src)
result = []
for relative_filepath in filepath_str.split('\n'):
if relative_filepath:
absolute_filepath = os.path.join(git_src, relative_filepath)
result.append(absolute_filepath)
return result
def _build_ls_files_command(subdirectory: Optional[str]) -> List[str]:
if subdirectory:
return ['git', 'ls-files', '--', subdirectory]
else:
return ['git', 'ls-files']
def get_log(git_src: str, subdirectory: str, trailing_days: int) -> str:
'''Gets the git log for a given directory.'''
return run_command([
'git',
'log',
'--follow',
f'--since=\"{trailing_days} days ago\"',
'--',
subdirectory,
],
cwd=git_src)
def run_command(command: List[str], cwd: str) -> str:
'''Runs a command and returns the output.
Raises an exception and prints the command output if the command fails.'''
try:
run_result = subprocess.run(command,
capture_output=True,
text=True,
check=True,
cwd=cwd)
except subprocess.CalledProcessError as e:
print(f'{command} failed with code {e.returncode}.', file=sys.stderr)
print(f'\nSTDERR:\n{e.stderr}', file=sys.stderr)
print(f'\nSTDOUT:\n{e.stdout}', file=sys.stderr)
raise
return run_result.stdout.strip()