Files
chromium_depot_tools/hooks/pre-commit.py
Yiwei Zhang 03a1a8936e pre-commit: do not ignore submodule when running diff-index
Without this line, if the git config specifies to ignore submodule
change (what happned in the associated bug), this script is useless
because the command will never return gitlink change

R=sokcevic

Bug: 1496925
Change-Id: I6536b95502e708e44d6fd3e4909fd30eac8c7c98
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/4995364
Auto-Submit: Yiwei Zhang <yiwzhang@google.com>
Reviewed-by: Josip Sokcevic <sokcevic@chromium.org>
Commit-Queue: Josip Sokcevic <sokcevic@chromium.org>
2023-11-01 16:46:03 +00:00

98 lines
2.9 KiB
Python

#!/usr/bin/env python3
# Copyright (c) 2023 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.
"""A git pre-commit hook to drop staged gitlink changes.
To bypass this hook, set SKIP_GITLINK_PRECOMMIT=1.
"""
import os
import sys
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, ROOT_DIR)
import git_common
from gclient_eval import SYNC
SKIP_VAR = 'SKIP_GITLINK_PRECOMMIT'
TESTING_ANSWER = 'TESTING_ANSWER'
def main():
if os.getenv(SKIP_VAR) == '1':
print(f'{SKIP_VAR} is set. Committing gitlinks, if any.')
exit(0)
has_deps_diff = False
staged_gitlinks = []
diff = git_common.run('diff-index', '--cached', '--ignore-submodules=dirty',
'HEAD')
for line in diff.splitlines():
path = line.split()[-1]
if path == 'DEPS':
has_deps_diff = True
continue
if line.startswith(':160000 160000'):
staged_gitlinks.append(path)
if not staged_gitlinks or has_deps_diff:
exit(0)
# There are staged gitlinks and DEPS wasn't changed. Get git_dependencies
# migration state in DEPS.
state = None
try:
with open('DEPS', 'r') as f:
for l in f.readlines():
if l.startswith('git_dependencies'):
state = l.split()[-1].strip(' "\'')
break
except OSError:
# Don't abort the commit if DEPS wasn't found.
exit(0)
if state != SYNC:
# DEPS only has to be in sync with gitlinks when state is SYNC.
exit(0)
prompt = (
f'Found no change to DEPS, but found staged gitlink(s) in diff:\n{diff}\n'
'Press Enter/Return if you intended to include them or "n" to unstage '
'(exclude from commit) the gitlink(s): ')
print(prompt)
if os.getenv(TESTING_ANSWER) is not None:
answer = os.getenv(TESTING_ANSWER)
else:
try:
sys.stdin = open("/dev/tty", "r")
except (FileNotFoundError, OSError):
try:
sys.stdin = open('CON')
except:
print(
'Unable to acquire input handle, proceeding without modifications'
)
exit(0)
answer = input()
disable_msg = f'To disable this hook, set {SKIP_VAR}=1'
if answer.lower() == 'n':
print(
f'\nUnstaging {len(staged_gitlinks)} staged gitlink(s) found in diff'
)
git_common.run('restore', '--staged', '--', *staged_gitlinks)
if len(staged_gitlinks) == len(diff.splitlines()):
print(
'\nFound no changes after unstaging gitlinks, aborting commit.')
print(disable_msg)
exit(1)
print(disable_msg)
if __name__ == "__main__":
main()