summaryrefslogtreecommitdiff
path: root/third_party/catapult/devil/devil/devil_env.py
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/catapult/devil/devil/devil_env.py')
-rw-r--r--third_party/catapult/devil/devil/devil_env.py194
1 files changed, 194 insertions, 0 deletions
diff --git a/third_party/catapult/devil/devil/devil_env.py b/third_party/catapult/devil/devil/devil_env.py
new file mode 100644
index 0000000000..aa4fe1ee6d
--- /dev/null
+++ b/third_party/catapult/devil/devil/devil_env.py
@@ -0,0 +1,194 @@
+# Copyright 2015 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 contextlib
+import json
+import logging
+import os
+import platform
+import sys
+import tempfile
+import threading
+
+CATAPULT_ROOT_PATH = os.path.abspath(os.path.join(
+ os.path.dirname(__file__), '..', '..'))
+DEPENDENCY_MANAGER_PATH = os.path.join(
+ CATAPULT_ROOT_PATH, 'dependency_manager')
+PYMOCK_PATH = os.path.join(
+ CATAPULT_ROOT_PATH, 'third_party', 'mock')
+
+
+@contextlib.contextmanager
+def SysPath(path):
+ sys.path.append(path)
+ yield
+ if sys.path[-1] != path:
+ sys.path.remove(path)
+ else:
+ sys.path.pop()
+
+with SysPath(DEPENDENCY_MANAGER_PATH):
+ import dependency_manager # pylint: disable=import-error
+
+_ANDROID_BUILD_TOOLS = {'aapt', 'dexdump', 'split-select'}
+
+_DEVIL_DEFAULT_CONFIG = os.path.abspath(os.path.join(
+ os.path.dirname(__file__), 'devil_dependencies.json'))
+
+_LEGACY_ENVIRONMENT_VARIABLES = {
+ 'ADB_PATH': {
+ 'dependency_name': 'adb',
+ 'platform': 'linux2_x86_64',
+ },
+ 'ANDROID_SDK_ROOT': {
+ 'dependency_name': 'android_sdk',
+ 'platform': 'linux2_x86_64',
+ },
+}
+
+
+def EmptyConfig():
+ return {
+ 'config_type': 'BaseConfig',
+ 'dependencies': {}
+ }
+
+
+def LocalConfigItem(dependency_name, dependency_platform, dependency_path):
+ if isinstance(dependency_path, basestring):
+ dependency_path = [dependency_path]
+ return {
+ dependency_name: {
+ 'file_info': {
+ dependency_platform: {
+ 'local_paths': dependency_path
+ },
+ },
+ },
+ }
+
+
+def _GetEnvironmentVariableConfig():
+ env_config = EmptyConfig()
+ path_config = (
+ (os.environ.get(k), v)
+ for k, v in _LEGACY_ENVIRONMENT_VARIABLES.iteritems())
+ path_config = ((p, c) for p, c in path_config if p)
+ for p, c in path_config:
+ env_config['dependencies'].update(
+ LocalConfigItem(c['dependency_name'], c['platform'], p))
+ return env_config
+
+
+class _Environment(object):
+
+ def __init__(self):
+ self._dm_init_lock = threading.Lock()
+ self._dm = None
+ self._logging_init_lock = threading.Lock()
+ self._logging_initialized = False
+
+ def Initialize(self, configs=None, config_files=None):
+ """Initialize devil's environment from configuration files.
+
+ This uses all configurations provided via |configs| and |config_files|
+ to determine the locations of devil's dependencies. Configurations should
+ all take the form described by py_utils.dependency_manager.BaseConfig.
+ If no configurations are provided, a default one will be used if available.
+
+ Args:
+ configs: An optional list of dict configurations.
+ config_files: An optional list of files to load
+ """
+
+ # Make sure we only initialize self._dm once.
+ with self._dm_init_lock:
+ if self._dm is None:
+ if configs is None:
+ configs = []
+
+ env_config = _GetEnvironmentVariableConfig()
+ if env_config:
+ configs.insert(0, env_config)
+ self._InitializeRecursive(
+ configs=configs,
+ config_files=config_files)
+ assert self._dm is not None, 'Failed to create dependency manager.'
+
+ def _InitializeRecursive(self, configs=None, config_files=None):
+ # This recurses through configs to create temporary files for each and
+ # take advantage of context managers to appropriately close those files.
+ # TODO(jbudorick): Remove this recursion if/when dependency_manager
+ # supports loading configurations directly from a dict.
+ if configs:
+ with tempfile.NamedTemporaryFile(delete=False) as next_config_file:
+ try:
+ next_config_file.write(json.dumps(configs[0]))
+ next_config_file.close()
+ self._InitializeRecursive(
+ configs=configs[1:],
+ config_files=[next_config_file.name] + (config_files or []))
+ finally:
+ if os.path.exists(next_config_file.name):
+ os.remove(next_config_file.name)
+ else:
+ config_files = config_files or []
+ if 'DEVIL_ENV_CONFIG' in os.environ:
+ config_files.append(os.environ.get('DEVIL_ENV_CONFIG'))
+ config_files.append(_DEVIL_DEFAULT_CONFIG)
+
+ self._dm = dependency_manager.DependencyManager(
+ [dependency_manager.BaseConfig(c) for c in config_files])
+
+ def InitializeLogging(self, log_level, formatter=None, handler=None):
+ if self._logging_initialized:
+ return
+
+ with self._logging_init_lock:
+ if self._logging_initialized:
+ return
+
+ formatter = formatter or logging.Formatter(
+ '%(threadName)-4s %(message)s')
+ handler = handler or logging.StreamHandler(sys.stdout)
+ handler.setFormatter(formatter)
+
+ devil_logger = logging.getLogger('devil')
+ devil_logger.setLevel(log_level)
+ devil_logger.propagate = False
+ devil_logger.addHandler(handler)
+
+ import py_utils.cloud_storage
+ lock_logger = py_utils.cloud_storage.logger
+ lock_logger.setLevel(log_level)
+ lock_logger.propagate = False
+ lock_logger.addHandler(handler)
+
+ self._logging_initialized = True
+
+ def FetchPath(self, dependency, arch=None, device=None):
+ if self._dm is None:
+ self.Initialize()
+ if dependency in _ANDROID_BUILD_TOOLS:
+ self.FetchPath('android_build_tools_libc++', arch=arch, device=device)
+ return self._dm.FetchPath(dependency, GetPlatform(arch, device))
+
+ def LocalPath(self, dependency, arch=None, device=None):
+ if self._dm is None:
+ self.Initialize()
+ return self._dm.LocalPath(dependency, GetPlatform(arch, device))
+
+ def PrefetchPaths(self, dependencies=None, arch=None, device=None):
+ return self._dm.PrefetchPaths(
+ GetPlatform(arch, device), dependencies=dependencies)
+
+
+def GetPlatform(arch=None, device=None):
+ if arch or device:
+ return 'android_%s' % (arch or device.product_cpu_abi)
+ return '%s_%s' % (sys.platform, platform.machine())
+
+
+config = _Environment()
+