[win-bootstrap] Bootstrap Git config global-level instead of system

Modifying the system-level Git config may require admin privileges,
depending on where Git was installed.

This CL makes the bootstrap.py script target a user's Git config
at the global level, instead of system level.

Checks the global Git config for postprocess version and explicit
enabling of global config changing. Logs a warning if out of date
and not enabled so the user knows how to agree to global config
changes.

Bug: b/379888465, b/360206460
Change-Id: I9be395b64d5429f85514397918f4a6140dfe2a1a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/6034204
Reviewed-by: Allen Li <ayatane@chromium.org>
Reviewed-by: Josip Sokcevic <sokcevic@chromium.org>
Commit-Queue: Anne Redulla <aredulla@google.com>
changes/04/6034204/6
Anne Redulla 3 months ago committed by LUCI CQ
parent 208e306fbf
commit c35fbb2ecb

@ -8,12 +8,15 @@ from replacing it outright without breaking running code. To
ommodate this, and Python cleanup, we handle Python in two stages:
1. Use CIPD to install both Git and Python at once.
2. Use "win_tools.py" as a post-processor to install generated files and
2. Use "bootstrap.py" as a post-processor to install generated files and
fix-ups.
## Software bootstrapped
* Python 3 (https://www.python.org/)
* Git for Windows (https://git-for-windows.github.io/)
* This will soon be unbundled from depot_tools. To prepare for this change,
please install Git directly. See the instructions in the
[Windows build docs](https://chromium.googlesource.com/chromium/src/+/main/docs/windows_build_instructions.md#Install-git).
## Mechanism
@ -29,7 +32,7 @@ cases is not true, it will download and unpack the respective binary.
Installation of Git and Python is done by the [win_tools.bat](./win_tools.bat)
script, which uses CIPD (via the [cipd](/cipd.bat) bootstrap) to acquire and
install each package into the root of the `depot_tools` repository. Afterwards,
the [win_tools.py](./win_tools.py) Python script is invoked to install stubs,
the [bootstrap.py](./bootstrap.py) Python script is invoked to install stubs,
wrappers, and support scripts into `depot_tools` for end-users.
### Manifest

@ -34,6 +34,19 @@ WIN_GIT_STUBS = {
'ssh-keygen.bat': 'usr\\bin\\ssh-keygen.exe',
}
# The global git config which should be applied by |git_postprocess|.
# The following set of parameters is versioned by "GIT_POSTPROCESS_VERSION".
# If they change, update "GIT_POSTPROCESS_VERSION" accordingly.
GIT_GLOBAL_CONFIG = {
'core.autocrlf': 'false',
'core.filemode': 'false',
'core.preloadindex': 'true',
'core.fscache': 'true',
'protocol.version': '2',
}
# Version of GIT_GLOBAL_CONFIG above.
GIT_POSTPROCESS_VERSION = '2'
# Accumulated template parameters for generated stubs.
class Template(
@ -185,14 +198,15 @@ def _toolchain_in_use(toolchain_path):
def _check_call(argv, stdin_input=None, **kwargs):
"""Wrapper for subprocess.check_call that adds logging."""
"""Wrapper for subprocess.Popen that adds logging."""
logging.info('running %r', argv)
if stdin_input is not None:
kwargs['stdin'] = subprocess.PIPE
proc = subprocess.Popen(argv, **kwargs)
proc.communicate(input=stdin_input)
stdout, stderr = proc.communicate(input=stdin_input)
if proc.returncode:
raise subprocess.CalledProcessError(proc.returncode, argv, None)
return stdout, stderr
def _safe_rmtree(path):
@ -241,10 +255,6 @@ def clean_up_old_installations(skip_dir):
logging.info('Toolchain at %r is in-use; skipping', full_entry)
# Version of "git_postprocess" system configuration (see |git_postprocess|).
GIT_POSTPROCESS_VERSION = '2'
def _within_depot_tools(path):
"""Returns whether the given path is within depot_tools."""
try:
@ -307,7 +317,85 @@ def git_get_mingw_dir(git_directory):
return None
def git_postprocess(template, bootstrap_git_dir, add_docs):
def get_git_global_config_value(git_path, key):
"""Helper to get the value from the global git config.
Returns:
- if present in the global git config, the associated value for the key;
- empty string if the key is not in the global git config.
Raises:
subprocess.CalledProcessError if there was an error reading the config
which resulted in an exit code other than 1.
"""
try:
stdout, _ = _check_call([git_path, 'config', '--global', key],
stdout=subprocess.PIPE,
encoding='utf-8')
return stdout.strip()
except subprocess.CalledProcessError as e:
# Exit code is 1 if the key is invalid (i.e. not in the config).
if e.returncode == 1:
logging.info('{} was not in the global git config.'.format(key))
return ''
raise e
def _win_git_bootstrap_config():
"""Bootstraps the global git config, if enabled by the user.
To allow depot_tools to update your global git config, run:
git config --global depot-tools.allowGlobalGitConfig true
To prevent depot_tools updating your global git config and silence the
warning, run:
git config --global depot-tools.allowGlobalGitConfig false
"""
git_bat_path = os.path.join(ROOT_DIR, 'git.bat')
postprocess_key = 'depot-tools.gitPostprocessVersion'
postprocess_version = get_git_global_config_value(git_path=git_bat_path,
key=postprocess_key)
if postprocess_version == GIT_POSTPROCESS_VERSION:
# Already configured. Nothing to do.
return
# Check whether the user has authorized depot_tools to update their global
# git config.
allow_global_key = 'depot-tools.allowGlobalGitConfig'
allow_global = get_git_global_config_value(git_path=git_bat_path,
key=allow_global_key).lower()
if allow_global in ('false', '0', 'no', 'off'):
# The user has explicitly disabled this.
return
if allow_global not in ('true', '1', 'yes', 'on'):
logging.warning(
'depot_tools would like to update your global Git config\n'
'to have the optimal settings for Chromium development.\n'
'Allow this by running:\n'
f' git config --global {allow_global_key} true\n'
'Then, get depot_tools to update your config by running:\n'
' gclient sync\n'
'To deny and silence this warning, run:\n'
f' git config --global {allow_global_key} false\n')
return
# Global git config changes have been authorized - do the update.
for k, v in GIT_GLOBAL_CONFIG.items():
_check_call([git_bat_path, 'config', '--global', k, v])
# Update the postprocess version to denote this version of the config has
# been applied.
_check_call([
git_bat_path, 'config', '--global', postprocess_key,
GIT_POSTPROCESS_VERSION
])
def git_postprocess(template, add_docs):
if add_docs:
# Update depot_tools files for "git help <command>".
mingw_dir = git_get_mingw_dir(template.GIT_BIN_ABSDIR)
@ -327,25 +415,8 @@ def git_postprocess(template, bootstrap_git_dir, add_docs):
stub_template.maybe_install('git.template.bat',
os.path.join(ROOT_DIR, stub_name))
# Set-up our system configuration environment. The following set of
# parameters is versioned by "GIT_POSTPROCESS_VERSION". If they change,
# update "GIT_POSTPROCESS_VERSION" accordingly.
def configure_git_system():
git_bat_path = os.path.join(ROOT_DIR, 'git.bat')
_check_call(
[git_bat_path, 'config', '--system', 'core.autocrlf', 'false'])
_check_call(
[git_bat_path, 'config', '--system', 'core.filemode', 'false'])
_check_call(
[git_bat_path, 'config', '--system', 'core.preloadindex', 'true'])
_check_call(
[git_bat_path, 'config', '--system', 'core.fscache', 'true'])
_check_call(
[git_bat_path, 'config', '--system', 'protocol.version', '2'])
os.makedirs(bootstrap_git_dir, exist_ok=True)
call_if_outdated(os.path.join(bootstrap_git_dir, '.git_postprocess'),
GIT_POSTPROCESS_VERSION, configure_git_system)
# Bootstrap the git global config.
_win_git_bootstrap_config()
def main(argv):
@ -374,7 +445,6 @@ def main(argv):
clean_up_old_installations(bootstrap_dir)
if IS_WIN:
bootstrap_git_dir = os.path.join(bootstrap_dir, 'git')
# Avoid messing with system git docs.
add_docs = False
git_dir = None
@ -384,10 +454,10 @@ def main(argv):
# Either using system git was not enabled
# or git was not found in PATH.
# Fall back to depot_tools bundled git.
git_dir = bootstrap_git_dir
git_dir = os.path.join(bootstrap_dir, 'git')
add_docs = True
template = template._replace(GIT_BIN_ABSDIR=git_dir)
git_postprocess(template, bootstrap_git_dir, add_docs)
git_postprocess(template, add_docs)
templates = [
('git-bash.template.sh', 'git-bash', ROOT_DIR),
('python3.bat', 'python3.bat', ROOT_DIR),

Loading…
Cancel
Save