Move gclient path access to separate module.
gclient_utils.py is a kitchen sink and is for that reason expensive to import. Move the comparatively cheap and simple path routines to a new gclient_paths module and use that in gn.py, clang_format.py, dart_format.py. (To be able to move FindGclientRoot() to gclient_paths.py, make it use io.open() instead of FileRead(). FileRead() tries to paper over invalid utf-8, but that was added for presubmits, not for .gclient files, so this is hopefully fine.) Cuts gn.py overhead in half (on my Windows laptop from 0.6s to 0.25s, still high; on my Mac laptop from 0.1s to 0.05s), and probably helps the other two too. Completely remove PathDifference() since it's unused. Bug: 939959 Change-Id: I6a70f6e4c16062b622fb2df8778e8a598d4cc956 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/1512058 Commit-Queue: Nico Weber <thakis@chromium.org> Reviewed-by: Andrii Shyshkalov <tandrii@chromium.org>changes/58/1512058/9
parent
3485a263f4
commit
09e0b38f0f
@ -0,0 +1,135 @@
|
||||
# Copyright 2019 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.
|
||||
|
||||
# This file is imported by various thin wrappers (around gn, clang-format, ...),
|
||||
# so it's meant to import very quickly. To keep it that way don't add more
|
||||
# code, and even more importantly don't add more toplevel import statements.
|
||||
import os
|
||||
|
||||
|
||||
def FindGclientRoot(from_dir, filename='.gclient'):
|
||||
"""Tries to find the gclient root."""
|
||||
real_from_dir = os.path.realpath(from_dir)
|
||||
path = real_from_dir
|
||||
while not os.path.exists(os.path.join(path, filename)):
|
||||
split_path = os.path.split(path)
|
||||
if not split_path[1]:
|
||||
return None
|
||||
path = split_path[0]
|
||||
|
||||
# If we did not find the file in the current directory, make sure we are in a
|
||||
# sub directory that is controlled by this configuration.
|
||||
if path != real_from_dir:
|
||||
entries_filename = os.path.join(path, filename + '_entries')
|
||||
if not os.path.exists(entries_filename):
|
||||
import sys
|
||||
# If .gclient_entries does not exist, a previous call to gclient sync
|
||||
# might have failed. In that case, we cannot verify that the .gclient
|
||||
# is the one we want to use. In order to not to cause too much trouble,
|
||||
# just issue a warning and return the path anyway.
|
||||
print >> sys.stderr, ("%s missing, %s file in parent directory %s might "
|
||||
"not be the file you want to use." %
|
||||
(entries_filename, filename, path))
|
||||
return path
|
||||
scope = {}
|
||||
try:
|
||||
import io
|
||||
with io.open(entries_filename, encoding='utf-8') as f:
|
||||
exec(f.read(), scope)
|
||||
except SyntaxError, e:
|
||||
SyntaxErrorToError(filename, e)
|
||||
all_directories = scope['entries'].keys()
|
||||
path_to_check = real_from_dir[len(path)+1:]
|
||||
while path_to_check:
|
||||
if path_to_check in all_directories:
|
||||
return path
|
||||
path_to_check = os.path.dirname(path_to_check)
|
||||
return None
|
||||
|
||||
import logging
|
||||
logging.info('Found gclient root at ' + path)
|
||||
return path
|
||||
|
||||
|
||||
def GetPrimarySolutionPath():
|
||||
"""Returns the full path to the primary solution. (gclient_root + src)"""
|
||||
|
||||
gclient_root = FindGclientRoot(os.getcwd())
|
||||
if not gclient_root:
|
||||
# Some projects might not use .gclient. Try to see whether we're in a git
|
||||
# checkout.
|
||||
top_dir = [os.getcwd()]
|
||||
def filter_fn(line):
|
||||
repo_root_path = os.path.normpath(line.rstrip('\n'))
|
||||
if os.path.exists(repo_root_path):
|
||||
top_dir[0] = repo_root_path
|
||||
try:
|
||||
CheckCallAndFilter(["git", "rev-parse", "--show-toplevel"],
|
||||
print_stdout=False, filter_fn=filter_fn)
|
||||
except Exception:
|
||||
pass
|
||||
top_dir = top_dir[0]
|
||||
if os.path.exists(os.path.join(top_dir, 'buildtools')):
|
||||
return top_dir
|
||||
return None
|
||||
|
||||
# Some projects' top directory is not named 'src'.
|
||||
source_dir_name = GetGClientPrimarySolutionName(gclient_root) or 'src'
|
||||
return os.path.join(gclient_root, source_dir_name)
|
||||
|
||||
|
||||
def GetBuildtoolsPath():
|
||||
"""Returns the full path to the buildtools directory.
|
||||
This is based on the root of the checkout containing the current directory."""
|
||||
|
||||
# Overriding the build tools path by environment is highly unsupported and may
|
||||
# break without warning. Do not rely on this for anything important.
|
||||
override = os.environ.get('CHROMIUM_BUILDTOOLS_PATH')
|
||||
if override is not None:
|
||||
return override
|
||||
|
||||
primary_solution = GetPrimarySolutionPath()
|
||||
if not primary_solution:
|
||||
return None
|
||||
buildtools_path = os.path.join(primary_solution, 'buildtools')
|
||||
if not os.path.exists(buildtools_path):
|
||||
# Buildtools may be in the gclient root.
|
||||
gclient_root = FindGclientRoot(os.getcwd())
|
||||
buildtools_path = os.path.join(gclient_root, 'buildtools')
|
||||
return buildtools_path
|
||||
|
||||
|
||||
def GetBuildtoolsPlatformBinaryPath():
|
||||
"""Returns the full path to the binary directory for the current platform."""
|
||||
buildtools_path = GetBuildtoolsPath()
|
||||
if not buildtools_path:
|
||||
return None
|
||||
|
||||
if sys.platform.startswith(('cygwin', 'win')):
|
||||
subdir = 'win'
|
||||
elif sys.platform == 'darwin':
|
||||
subdir = 'mac'
|
||||
elif sys.platform.startswith('linux'):
|
||||
subdir = 'linux64'
|
||||
else:
|
||||
raise Error('Unknown platform: ' + sys.platform)
|
||||
return os.path.join(buildtools_path, subdir)
|
||||
|
||||
|
||||
def GetExeSuffix():
|
||||
"""Returns '' or '.exe' depending on how executables work on this platform."""
|
||||
if sys.platform.startswith(('cygwin', 'win')):
|
||||
return '.exe'
|
||||
return ''
|
||||
|
||||
|
||||
def GetGClientPrimarySolutionName(gclient_root_dir_path):
|
||||
"""Returns the name of the primary solution in the .gclient file specified."""
|
||||
gclient_config_file = os.path.join(gclient_root_dir_path, '.gclient')
|
||||
env = {}
|
||||
execfile(gclient_config_file, env)
|
||||
solutions = env.get('solutions', [])
|
||||
if solutions:
|
||||
return solutions[0].get('name')
|
||||
return None
|
Loading…
Reference in New Issue