Commit 84b5f9a2 authored by Edward Lemur's avatar Edward Lemur Committed by Commit Bot

depot_tools: Add tests for gclient_paths

Change-Id: I544aa85b040544508df8ed16310def982356fbcc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/1949417
Commit-Queue: Edward Lesmes <ehmaldonado@chromium.org>
Reviewed-by: 's avatarAnthony Polito <apolito@google.com>
parent 9253a685
......@@ -11,7 +11,9 @@
from __future__ import print_function
import gclient_utils
import logging
import os
import subprocess2
import sys
......@@ -25,66 +27,66 @@ def FindGclientRoot(from_dir, filename='.gclient'):
return None
path = split_path[0]
logging.info('Found gclient root at ' + path)
if path == real_from_dir:
return path
# 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):
# 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(
"%s missing, %s file in parent directory %s might not be the file "
"you want to use." % (entries_filename, filename, path),
file=sys.stderr)
entries_filename = os.path.join(path, filename + '_entries')
if not os.path.exists(entries_filename):
# 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(
"%s missing, %s file in parent directory %s might not be the file "
"you want to use." % (entries_filename, filename, path),
file=sys.stderr)
return path
entries_content = gclient_utils.FileRead(entries_filename)
scope = {}
try:
exec(entries_content, scope)
except (SyntaxError, Exception) as e:
gclient_utils.SyntaxErrorToError(filename, e)
all_directories = scope['entries'].keys()
path_to_check = os.path.relpath(real_from_dir, path)
while path_to_check:
if path_to_check in all_directories:
return path
scope = {}
try:
import io
with io.open(entries_filename, encoding='utf-8') as f:
exec(f.read(), scope)
except SyntaxError as 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
path_to_check = os.path.dirname(path_to_check)
import logging
logging.info('Found gclient root at ' + path)
return path
return None
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:
gclient_utils.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)
if gclient_root:
# 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)
# Some projects might not use .gclient. Try to see whether we're in a git
# checkout that contains a 'buildtools' subdir.
top_dir = os.getcwd()
try:
top_dir = subprocess2.check_output(
['git', 'rev-parse', '--show-toplevel'])
if sys.version_info.major == 3:
top_dir = top_dir.decode('utf-8', 'replace')
top_dir = os.path.normpath(top_dir.strip())
except subprocess2.CalledProcessError:
pass
if os.path.exists(os.path.join(top_dir, 'buildtools')):
return top_dir
return None
def GetBuildtoolsPath():
......@@ -100,12 +102,18 @@ def GetBuildtoolsPath():
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
if os.path.exists(buildtools_path):
return buildtools_path
# buildtools may be in the gclient root.
gclient_root = FindGclientRoot(os.getcwd())
buildtools_path = os.path.join(gclient_root, 'buildtools')
if os.path.exists(buildtools_path):
return buildtools_path
return None
def GetBuildtoolsPlatformBinaryPath():
......@@ -121,7 +129,7 @@ def GetBuildtoolsPlatformBinaryPath():
elif sys.platform.startswith('linux'):
subdir = 'linux64'
else:
raise Error('Unknown platform: ' + sys.platform)
raise gclient_utils.Error('Unknown platform: ' + sys.platform)
return os.path.join(buildtools_path, subdir)
......@@ -135,9 +143,9 @@ def GetExeSuffix():
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')
gclient_config_contents = gclient_utils.FileRead(gclient_config_file)
env = {}
exec(compile(open(gclient_config_file).read(), gclient_config_file, 'exec'),
env)
exec(gclient_config_contents, env)
solutions = env.get('solutions', [])
if solutions:
return solutions[0].get('name')
......
#!/usr/bin/env vpython3
# coding=utf-8
# Copyright (c) 2012 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.
import os
import sys
import unittest
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import gclient_paths
import gclient_utils
import subprocess2
if sys.version_info.major == 2:
from StringIO import StringIO
import mock
else:
from io import StringIO
from unittest import mock
EXCEPTION = subprocess2.CalledProcessError(
128, ['cmd'], 'cwd', 'stdout', 'stderr')
class TestBase(unittest.TestCase):
def setUp(self):
super(TestBase, self).setUp()
self.file_tree = {}
self.root = 'C:\\' if sys.platform == 'win32' else '/'
self.cwd = self.root
mock.patch('gclient_utils.FileRead', self.read).start()
mock.patch('os.environ', {}).start()
mock.patch('os.getcwd', self.getcwd).start()
mock.patch('os.path.exists', self.exists).start()
mock.patch('os.path.realpath', side_effect=lambda path: path).start()
mock.patch('subprocess2.check_output').start()
mock.patch('sys.platform', '').start()
mock.patch('sys.stderr', StringIO()).start()
self.addCleanup(mock.patch.stopall)
def getcwd(self):
return self.cwd
def exists(self, path):
return path in self.file_tree
def read(self, path):
return self.file_tree[path]
def make_file_tree(self, file_tree):
self.file_tree = {
self.root + path: content
for path, content in file_tree.items()
}
class FindGclientRootTest(TestBase):
def testFindGclientRoot(self):
self.make_file_tree({'.gclient': ''})
self.assertEqual(self.root, gclient_paths.FindGclientRoot(self.root))
def testGclientRootInParentDir(self):
self.make_file_tree({
'.gclient': '',
'.gclient_entries': 'entries = {"foo": "..."}',
})
self.assertEqual(
self.root,
gclient_paths.FindGclientRoot(os.path.join(self.root, 'foo', 'bar')))
def testGclientRootInParentDir_NotInGclientEntries(self):
self.make_file_tree({
'.gclient': '',
'.gclient_entries': 'entries = {"foo": "..."}',
})
self.assertIsNone(
gclient_paths.FindGclientRoot(os.path.join(self.root, 'bar', 'baz')))
def testGclientRootInParentDir_NoGclientEntriesFile(self):
self.make_file_tree({'.gclient': ''})
self.assertEqual(
self.root,
gclient_paths.FindGclientRoot(os.path.join(self.root, 'x', 'y', 'z')))
self.assertEqual(
'%s missing, .gclient file in parent directory %s might not be the '
'file you want to use.\n' % (
os.path.join(self.root, '.gclient_entries'), self.root),
sys.stderr.getvalue())
def testGclientRootInParentDir_ErrorWhenParsingEntries(self):
self.make_file_tree({'.gclient': '', '.gclient_entries': ':P'})
with self.assertRaises(Exception):
gclient_paths.FindGclientRoot(os.path.join(self.root, 'foo', 'bar'))
def testRootNotFound(self):
self.assertIsNone(
gclient_paths.FindGclientRoot(os.path.join(self.root, 'x', 'y', 'z')))
class GetGClientPrimarySolutionNameTest(TestBase):
def testGetGClientPrimarySolutionName(self):
self.make_file_tree({'.gclient': 'solutions = [{"name": "foo"}]'})
self.assertEqual(
'foo', gclient_paths.GetGClientPrimarySolutionName(self.root))
def testNoSolutionsInGclientFile(self):
self.make_file_tree({'.gclient': ''})
self.assertIsNone(gclient_paths.GetGClientPrimarySolutionName(self.root))
class GetPrimarySolutionPathTest(TestBase):
def testGetPrimarySolutionPath(self):
self.make_file_tree({'.gclient': 'solutions = [{"name": "foo"}]'})
self.assertEqual(
os.path.join(self.root, 'foo'), gclient_paths.GetPrimarySolutionPath())
def testSolutionNameDefaultsToSrc(self):
self.make_file_tree({'.gclient': ''})
self.assertEqual(
os.path.join(self.root, 'src'), gclient_paths.GetPrimarySolutionPath())
def testGclientRootNotFound_GitRootHasBuildtools(self):
self.make_file_tree({os.path.join('foo', 'buildtools'): ''})
self.cwd = os.path.join(self.root, 'foo', 'bar')
subprocess2.check_output.return_value = (
os.path.join(self.root, 'foo').replace(os.sep, '/').encode('utf-8')
+ b'\n')
self.assertEqual(
os.path.join(self.root, 'foo'), gclient_paths.GetPrimarySolutionPath())
def testGclientRootNotFound_NoBuildtools(self):
self.cwd = os.path.join(self.root, 'foo', 'bar')
subprocess2.check_output.return_value = b'/foo\n'
self.assertIsNone(gclient_paths.GetPrimarySolutionPath())
def testGclientRootNotFound_NotInAGitRepo_CurrentDirHasBuildtools(self):
self.make_file_tree({os.path.join('foo', 'bar', 'buildtools'): ''})
self.cwd = os.path.join(self.root, 'foo', 'bar')
subprocess2.check_output.side_effect = EXCEPTION
self.assertEqual(self.cwd, gclient_paths.GetPrimarySolutionPath())
def testGclientRootNotFound_NotInAGitRepo_NoBuildtools(self):
self.cwd = os.path.join(self.root, 'foo')
subprocess2.check_output.side_effect = EXCEPTION
self.assertIsNone(gclient_paths.GetPrimarySolutionPath())
class GetBuildtoolsPathTest(TestBase):
def testEnvVarOverride(self):
os.environ = {'CHROMIUM_BUILDTOOLS_PATH': 'foo'}
self.assertEqual('foo', gclient_paths.GetBuildtoolsPath())
def testNoSolutionsFound(self):
self.cwd = os.path.join(self.root, 'foo', 'bar')
subprocess2.check_output.side_effect = EXCEPTION
self.assertIsNone(gclient_paths.GetBuildtoolsPath())
def testBuildtoolsInSolution(self):
self.make_file_tree({
'.gclient': '',
os.path.join('src', 'buildtools'): '',
})
self.cwd = os.path.join(self.root, 'src', 'foo')
self.assertEqual(
os.path.join(self.root, 'src', 'buildtools'),
gclient_paths.GetBuildtoolsPath())
def testBuildtoolsInGclientRoot(self):
self.make_file_tree({'.gclient': '', 'buildtools': ''})
self.cwd = os.path.join(self.root, 'src', 'foo')
self.assertEqual(
os.path.join(self.root, 'buildtools'),
gclient_paths.GetBuildtoolsPath())
def testNoBuildtools(self):
self.make_file_tree({'.gclient': ''})
self.cwd = os.path.join(self.root, 'foo', 'bar')
self.assertIsNone(gclient_paths.GetBuildtoolsPath())
class GetBuildtoolsPlatformBinaryPath(TestBase):
def testNoBuildtoolsPath(self):
self.make_file_tree({'.gclient': ''})
self.cwd = os.path.join(self.root, 'foo', 'bar')
self.assertIsNone(gclient_paths.GetBuildtoolsPlatformBinaryPath())
def testWin(self):
self.make_file_tree({'.gclient': '', 'buildtools': ''})
sys.platform = 'win'
self.assertEqual(
os.path.join(self.root, 'buildtools', 'win'),
gclient_paths.GetBuildtoolsPlatformBinaryPath())
def testCygwin(self):
self.make_file_tree({'.gclient': '', 'buildtools': ''})
sys.platform = 'cygwin'
self.assertEqual(
os.path.join(self.root, 'buildtools', 'win'),
gclient_paths.GetBuildtoolsPlatformBinaryPath())
def testMac(self):
self.make_file_tree({'.gclient': '', 'buildtools': ''})
sys.platform = 'darwin'
self.assertEqual(
os.path.join(self.root, 'buildtools', 'mac'),
gclient_paths.GetBuildtoolsPlatformBinaryPath())
def testLinux(self):
self.make_file_tree({'.gclient': '', 'buildtools': ''})
sys.platform = 'linux'
self.assertEqual(
os.path.join(self.root, 'buildtools', 'linux64'),
gclient_paths.GetBuildtoolsPlatformBinaryPath())
def testError(self):
self.make_file_tree({'.gclient': '', 'buildtools': ''})
sys.platform = 'foo'
with self.assertRaises(gclient_utils.Error, msg='Unknown platform: foo'):
gclient_paths.GetBuildtoolsPlatformBinaryPath()
class GetExeSuffixTest(TestBase):
def testGetExeSuffix(self):
sys.platform = 'win'
self.assertEqual('.exe', gclient_paths.GetExeSuffix())
sys.platform = 'cygwin'
self.assertEqual('.exe', gclient_paths.GetExeSuffix())
sys.platform = 'foo'
self.assertEqual('', gclient_paths.GetExeSuffix())
if __name__ == '__main__':
unittest.main()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment