def UpdateCliTrees(cli=None, commands=None, directory=None, verbose=False, warn_on_exceptions=False): """(re)generates the CLI trees in directory if non-existent or out ot date. This function uses the progress tracker because some of the updates can take ~minutes. Args: cli: The default CLI. If not None then the default CLI is also updated. commands: Update only the commands in this list. directory: The directory containing the CLI tree JSON files. If None then the default installation directories are used. verbose: Display a status line for up to date CLI trees if True. warn_on_exceptions: Emits warning messages in lieu of exceptions. Used during installation. Raises: NoCliTreeGeneratorForCommand: A command in commands is not supported (doesn't have a generator). """ # Initialize the list of directories to search for CLI tree files. The default # CLI tree is only searched for and generated in directories[0]. Other # existing trees are updated in the directory in which they were found. New # trees are generated in directories[-1]. directories = [] if directory: directories.append(directory) else: try: directories.append(cli_tree.CliTreeDir()) except cli_tree.SdkRootNotFoundError as e: if not warn_on_exceptions: raise log.warn(str(e)) directories.append(cli_tree.CliTreeConfigDir()) if not commands: commands = set([cli_tree.DEFAULT_CLI_NAME] + GENERATORS.keys()) failed = [] for command in sorted(commands): if command != cli_tree.DEFAULT_CLI_NAME: generator = GetCliTreeGenerator(command) try: generator.LoadOrGenerate(directories=directories, verbose=verbose, warn_on_exceptions=warn_on_exceptions) except subprocess.CalledProcessError: failed.append(command) elif cli: cli_tree.Load(cli=cli, path=cli_tree.CliTreePath(directory=directories[0]), verbose=verbose) if failed: message = 'No CLI tree {} for [{}].'.format( text_utils.Pluralize(len(failed), 'generator'), ', '.join(sorted(failed))) if not warn_on_exceptions: raise NoCliTreeGeneratorForCommand(message) log.warn(message)
def FindTreeFile(self, directories): """Returns (path,f) open for read for the first CLI tree in directories.""" for directory in directories or [cli_tree.CliTreeConfigDir()]: path = os.path.join(directory or '.', self.command) + '.json' try: return path, io.open(path, 'rt') except IOError: pass return path, None # pytype: disable=name-error
def _GetDirectories(directory=None, warn_on_exceptions=False): """Returns the list of directories to search for CLI trees. Args: directory: The directory containing the CLI tree JSON files. If None then the default installation and config directories are used. warn_on_exceptions: Emits warning messages in lieu of exceptions. """ # Initialize the list of directories to search for CLI tree files. The default # CLI tree is only searched for and generated in directories[0]. Other # existing trees are updated in the directory in which they were found. New # trees are generated in directories[-1]. directories = [] if directory: directories.append(directory) else: try: directories.append(cli_tree.CliTreeDir()) except cli_tree.SdkRootNotFoundError as e: if not warn_on_exceptions: raise log.warning(six.text_type(e)) directories.append(cli_tree.CliTreeConfigDir()) return directories
def ListAll(directory=None): """Returns the CliTreeInfo list of all available CLI trees. Args: directory: The config directory containing the CLI tree modules. Raises: CliTreeVersionError: loaded tree version mismatch ImportModuleError: import errors Returns: The CLI tree. """ # List all CLIs by searching directories in order. .py, .pyc, and .json # files are treated as CLI modules/data, where the file base name is the name # of the CLI root command. directories = [ directory, # Explicit caller override dir cli_tree.CliTreeConfigDir(), # Config dir shared across installations cli_tree.CliTreeDir(), # Installation dir controlled by the updater ] trees = [] for directory in directories: if not directory or not os.path.exists(directory): continue for (dirpath, _, filenames) in os.walk(directory): for filename in sorted(filenames): # For stability across runs. base, extension = os.path.splitext(filename) if base == '__init__' or '.' in base: # Ignore Python droppings and names containing more than one dot. continue path = os.path.join(dirpath, filename) error = '' tree = None if extension in ('.py', '.pyc'): try: module = module_util.ImportPath(path) except module_util.ImportModuleError as e: error = six.text_type(e) try: tree = module.TREE except AttributeError: tree = None elif extension == '.json': try: tree = json.loads(files.ReadFileContents(path)) except Exception as e: # pylint: disable=broad-except, record all errors error = six.text_type(e) if tree: version = tree.get(cli_tree.LOOKUP_VERSION, 'UNKNOWN') cli_version = tree.get(cli_tree.LOOKUP_CLI_VERSION, 'UNKNOWN') del tree else: version = 'UNKNOWN' cli_version = 'UNKNOWN' trees.append( CliTreeInfo(command=base, path=_ParameterizePath(path), version=version, cli_version=cli_version, command_installed=bool( files.FindExecutableOnPath(base)), error=error)) # Don't search subdirectories. break return trees