Files
mongo/buildscripts/patch_builds/change_data.py
Lydia Stepanek 2a76e589a5 SERVER-46453 Selected_tests_gen should pick up changed files in mongo-enterprise-modules files
(cherry picked from commit 92f4273fb6d3d3079b07dc3c76acf1afd17f4225)
2020-03-05 16:58:44 +00:00

86 lines
2.6 KiB
Python

"""Tools for detecting changes in a commit."""
import os
from itertools import chain
from typing import Any, Iterable, Set
import structlog
from structlog.stdlib import LoggerFactory
from git import DiffIndex, Repo
structlog.configure(logger_factory=LoggerFactory())
LOGGER = structlog.get_logger(__name__)
def _paths_for_iter(diff, iter_type):
"""
Get the set for all the files in the given diff for the specified type.
:param diff: git diff to query.
:param iter_type: Iter type ['M', 'A', 'R', 'D'].
:return: set of changed files.
"""
a_path_changes = {change.a_path for change in diff.iter_change_type(iter_type)}
b_path_changes = {change.b_path for change in diff.iter_change_type(iter_type)}
return a_path_changes.union(b_path_changes)
def _modified_files_for_diff(diff: DiffIndex, log: Any) -> Set:
"""
Get the set of files modified in the given git diff.
:param diff: Git diff information.
:param log: Logger for logging.
:return: Set of files that were modified in diff.
"""
modified_files = _paths_for_iter(diff, 'M')
log.debug("modified files", files=modified_files)
added_files = _paths_for_iter(diff, 'A')
log.debug("added files", files=added_files)
renamed_files = _paths_for_iter(diff, 'R')
log.debug("renamed files", files=renamed_files)
deleted_files = _paths_for_iter(diff, 'D')
log.debug("deleted files", files=deleted_files)
return modified_files.union(added_files).union(renamed_files).union(deleted_files)
def find_changed_files(repo: Repo) -> Set[str]:
"""
Find files that were new or added to the repository between commits.
:param repo: Git repository.
:return: Set of changed files.
"""
diff = repo.index.diff(None)
work_tree_files = _modified_files_for_diff(diff, LOGGER.bind(diff="working tree diff"))
commit = repo.index
diff = commit.diff(repo.head.commit)
index_files = _modified_files_for_diff(diff, LOGGER.bind(diff="index diff"))
untracked_files = set(repo.untracked_files)
LOGGER.info("untracked files", files=untracked_files, diff="untracked diff")
paths = work_tree_files.union(index_files).union(untracked_files)
return [
os.path.relpath(f"{repo.working_dir}/{os.path.normpath(path)}", os.getcwd())
for path in paths
]
def find_changed_files_in_repos(repos: Iterable[Repo]) -> Set[str]:
"""
Find the changed files.
Use git to find which files have changed in this patch.
:param repos: List of repos containing changed files.
:returns: Set of changed files.
"""
return set(chain.from_iterable([find_changed_files(repo) for repo in repos]))