def main(sysargs=None): parser = argparse.ArgumentParser( description="xylem is a package manager abstraction tool.", add_help=False, formatter_class=ConfigHelpFormatter ) add_config_arguments(parser) add_global_arguments(parser) cmds = list_commands() create_subparsers(parser, cmds) args = parser.parse_args(sysargs) handle_global_arguments(args) handle_config_arguments(args) # FIXME: the following logic and error handling try: args.func result = args.func(args) except XylemError as e: if is_debug() or isinstance(e, XylemInternalError): print_exc(exc_to_str(e, tb=True, chain=True)) else: error(exc_to_str(e, tb=False, chain=True)) sys.exit(1) except (KeyboardInterrupt, EOFError): info('') sys.exit(1) sys.stdout.write(ansi('reset')) sys.exit(result or 0)
def main(args=None): args = command_handle_args(args, definition) config = get_config() try: resolve_errors, install_errors = install( args.xylem_key, all_keys=args.all, config=config, reinstall=args.reinstall, simulate=args.dry_run, continue_on_error=args.continue_on_error, fix_prerequisites=args.fix_prerequisites) if resolve_errors: # error("The following errors occurred during resolution:") error("\n".join(indent(exc_to_str(e), 2, exclude_first=True) for _, e in resolve_errors)) if install_errors: # error("The following errors occurred during installation:") error("\n".join(indent(exc_to_str(e), 2, exclude_first=True) for e in install_errors)) if resolve_errors or install_errors: sys.exit(1) except (KeyboardInterrupt, EOFError): info('') sys.exit(1)
def main(args=None): args = command_handle_args(args, definition) try: update(dry_run=args.dry_run) except (KeyboardInterrupt, EOFError): info('') sys.exit(1)
def main(args=None): args = command_handle_args(args, definition) try: # prepare arguments filepath = os.path.abspath(os.path.expanduser(args.rules_file)) # parse rules file with open(filepath, 'rb') as f: data = to_str(f.read()) rules = load_yaml(data) rules = expand_rules(rules) verify_rules_dict(rules) # compact rules compacted = compact_rules(rules, OSSupport().get_default_installer_names()) # output result dump = dump_yaml(compacted) if args.write: with open(filepath, 'wb') as f: f.write(to_bytes(dump)) else: info(dump) except (KeyboardInterrupt, EOFError): sys.exit(1)
def main(args=None): args = command_handle_args(args, definition) try: # prepare arguments filepath = os.path.abspath(os.path.expanduser(args.rules_file)) # parse rules file with open(filepath, 'rb') as f: data = to_str(f.read()) rules = load_yaml(data) rules = expand_rules(rules) verify_rules_dict(rules) # compact rules compacted = compact_rules( rules, OSSupport().get_default_installer_names()) # output result dump = dump_yaml(compacted) if args.write: with open(filepath, 'wb') as f: f.write(to_bytes(dump)) else: info(dump) except (KeyboardInterrupt, EOFError): sys.exit(1)
def main(args=None): args = command_handle_args(args, definition) config = get_config() try: ic = InstallerContext(config=config) default_installer_name = ic.get_default_installer_name() results, errors = resolve(args.xylem_key, all_keys=args.all, config=config, installer_context=ic) if errors: error("\n".join(indent(exc_to_str(e), 2, exclude_first=True) for _, e in errors)) for key, (installer_name, resolutions) in results: if installer_name != default_installer_name or \ args.show_default_installer: installer_string = "{0}: ".format(installer_name) else: installer_string = "" resolution_string = ', '.join(map(to_str, resolutions)) info("{0} --> {1}{2}". format(ansi("cyanf") + key + ansi("reset"), ansi("bluef") + installer_string, ansi("yellowf") + resolution_string)) if errors: sys.exit(1) except (KeyboardInterrupt, EOFError): info('') sys.exit(1)
def main(args=None): args = command_handle_args(args, definition) config = get_config() try: resolve_errors, install_errors = install( args.xylem_key, all_keys=args.all, config=config, reinstall=args.reinstall, simulate=args.dry_run, continue_on_error=args.continue_on_error, fix_prerequisites=args.fix_prerequisites) if resolve_errors: # error("The following errors occurred during resolution:") error("\n".join( indent(exc_to_str(e), 2, exclude_first=True) for _, e in resolve_errors)) if install_errors: # error("The following errors occurred during installation:") error("\n".join( indent(exc_to_str(e), 2, exclude_first=True) for e in install_errors)) if resolve_errors or install_errors: sys.exit(1) except (KeyboardInterrupt, EOFError): info('') sys.exit(1)
def get_source_descriptions(sources_dir): """Return a list of source urls. :returns: lists of source urls keyed by spec, or None if no configs found :rtype: :py:obj:`dict`(:py:obj:`str`: :py:obj:`list`(:py:obj:`str`)) """ if os.path.exists(sources_dir): if is_verbose(): info("Loading source urls from '{0}'".format(sources_dir)) return load_sources_from_path(sources_dir)
def clear_cache(self): """Remove cache file. :raises OSError: if cache file cannot be removed """ path = self.cache_file_path(self.sources_context) if os.path.exists(path): if is_verbose(): info("Removing cache file '%s'.", path) os.remove(path) else: if is_verbose(): info("Cache file '%s' already clear.", path)
def main(args=None): args = command_handle_args(args, definition) config = get_config() try: # TODO: handle multiple keys in one go ic = InstallerContext(config=config) for key in args.xylem_key: result = lookup(key, compact=True, config=config, installer_context=ic) info("Rules for '{}' on '{}':\n{}". format(ansi('cyanf') + key + ansi('reset'), ansi('cyanf') + ic.get_os_string() + ansi('reset'), ansi('yellowf') + dump_yaml(result)[:-1])) except (KeyboardInterrupt, EOFError): # Note: @William why EOFError here? info('') sys.exit(1)
def main(args=None): args = command_handle_args(args, definition) config = get_config() try: # TODO: handle multiple keys in one go ic = InstallerContext(config=config) for key in args.xylem_key: result = lookup(key, compact=True, config=config, installer_context=ic) info("Rules for '{}' on '{}':\n{}".format( ansi('cyanf') + key + ansi('reset'), ansi('cyanf') + ic.get_os_string() + ansi('reset'), ansi('yellowf') + dump_yaml(result)[:-1])) except (KeyboardInterrupt, EOFError): # Note: @William why EOFError here? info('') sys.exit(1)
def load_from_source(self): origins = set() for source in self.sources: if source.origin not in origins: origins.add(source.origin) if self.print_info: info("Processing '{0}'...".format(source.origin)) if self.print_info: info("Loading: {0} : {1}". format(source.spec.name, source.arguments)) try: source.load_from_source() except Exception as e: # TODO: be more specific about which exceptions to catch here if self.raise_on_error: raise else: error("Failed to load source '{0}':\n{1}". format(source.unique_id(), e))
def load_from_source(self): origins = set() for source in self.sources: if source.origin not in origins: origins.add(source.origin) if self.print_info: info("Processing '{0}'...".format(source.origin)) if self.print_info: info("Loading: {0} : {1}".format(source.spec.name, source.arguments)) try: source.load_from_source() except Exception as e: # TODO: be more specific about which exceptions to catch here if self.raise_on_error: raise else: error("Failed to load source '{0}':\n{1}".format( source.unique_id(), e))
def handle_global_config_arguments_post(args, config, tool_name): """Handle global configuration-related command line arguments with config. This deals with global config-related arguments that require the loaded configuration, e.g. ``--print-config``. The is intended to be called after the effective config dict has been created. See :func:`add_global_config_arguments`, :func:`handle_global_config_arguments` :param argparse.Namespace args: parsed command line arguments :param dict config: config dict :param str tool_name: name of the tool to determine config file locations, argument names and environment variables """ if args.print_config: info(dump_yaml(config)) sys.exit(0)
def init_from_sources(self): debug("initializing database with sources dir `{}` and cache dir `{}`". format(self.sources_context.sources_dir, self.sources_context.cache_dir)) self.sources = [] sources_dir = self.sources_context.sources_dir sources_gen = get_source_descriptions(sources_dir) if sources_gen is None: if not self.sources_context.is_default_dirs(): warning("no source files found in source dir '{0}'; " "using default sources".format(sources_dir)) if is_verbose(): info("Loading default source urls") sources_gen = get_default_source_descriptions() for source_file, source_descriptions in sources_gen: for descr in source_descriptions: spec_name, arguments = descr.items()[0] spec = self.sources_context.get_spec(spec_name) self.sources.append( RulesSource(spec, arguments, source_file, self.sources_context)) self.verify_unique_ids()
def update(self): # TODO: save exceptions if they are not raised and then for the # cli command recognize permission errors and suggest to use # 'sudo' # We don't just call `load_from_source` and `save_to_cache` here # since we want errors with saving for each source to happen # directly after loading, not at the end. origins = set() for source in self.sources: if source.origin not in origins: origins.add(source.origin) if self.print_info: info("Processing '{0}'...".format(source.origin)) if self.print_info: info("Loading: {0} : {1}". format(source.spec.name, source.arguments)) try: source.load_from_source() except Exception as e: # TODO: be more specific about which exceptions to catch here if self.raise_on_error: raise else: error("Failed to load source '{0}':\n{1}". format(source.unique_id(), e)) else: try: source.save_to_cache() except Exception as e: # TODO: be more specific about which exceptions to catch if self.raise_on_error: raise else: error("Failed to save source '{0}' to cache:\n{1}". format(source.unique_id(), to_str(e)))
def update(self): # TODO: save exceptions if they are not raised and then for the # cli command recognize permission errors and suggest to use # 'sudo' # We don't just call `load_from_source` and `save_to_cache` here # since we want errors with saving for each source to happen # directly after loading, not at the end. origins = set() for source in self.sources: if source.origin not in origins: origins.add(source.origin) if self.print_info: info("Processing '{0}'...".format(source.origin)) if self.print_info: info("Loading: {0} : {1}".format(source.spec.name, source.arguments)) try: source.load_from_source() except Exception as e: # TODO: be more specific about which exceptions to catch here if self.raise_on_error: raise else: error("Failed to load source '{0}':\n{1}".format( source.unique_id(), e)) else: try: source.save_to_cache() except Exception as e: # TODO: be more specific about which exceptions to catch if self.raise_on_error: raise else: error("Failed to save source '{0}' to cache:\n{1}". format(source.unique_id(), to_str(e)))
def init_from_sources(self): debug("initializing database with sources dir `{}` and cache dir `{}`". format(self.sources_context.sources_dir, self.sources_context.cache_dir)) self.sources = [] sources_dir = self.sources_context.sources_dir sources_gen = get_source_descriptions(sources_dir) if sources_gen is None: if not self.sources_context.is_default_dirs(): warning("no source files found in source dir '{0}'; " "using default sources".format(sources_dir)) if is_verbose(): info("Loading default source urls") sources_gen = get_default_source_descriptions() for source_file, source_descriptions in sources_gen: for descr in source_descriptions: spec_name, arguments = descr.items()[0] spec = self.sources_context.get_spec(spec_name) self.sources.append(RulesSource( spec, arguments, source_file, self.sources_context)) self.verify_unique_ids()
def install_resolutions(installer_name, resolutions, installer_context, interactive=True, reinstall=False, simulate=False, continue_on_error=False): installer = installer_context.lookup_installer(installer_name) if installer is None: raise XylemInternalError("did not find resolved installer '{}'". format(installer_name)) errors = [] try: commands = installer.get_install_commands(resolutions, interactive=interactive, reinstall=reinstall) except InstallerError as e: # TODO: does InstallerError here make sense? errors.append(chain_exception( InstallError, "installer '{}' failed to compose install commands " "for resolutions {} with options `interactive={}` and " "`reinstall={}`". format(installer_name, resolutions, interactive, reinstall), e)) except Exception as e: raise_from( XylemInternalError, "unexpected error in installer '{}' while " "composing install commands for resolutions {} with options " "`interactive={}` and `reinstall={}`". format(installer_name, resolutions, interactive, reinstall), e) if not commands: info_v("# [%s] no packages to install" % installer_name) return errors # 1. when simulating, only print commands to screen if simulate: print("# [%s] installation commands:" % installer_name) for cmd in commands: info(' ' + ' '.join(cmd)) return errors # 2. else, run each install command set and collect errors for cmd in commands: info(fmt("@!executing command: %s@|" % ' '.join(cmd))) exitcode = subprocess.call(cmd) info_v(fmt("@!command return code: %s@|" % exitcode)) if exitcode != 0: errors.append(InstallError( "command `{}` for installer '{}' failed with return code {}". format(' '.join(cmd), installer, exitcode))) if not continue_on_error: return errors # 3. test installation of each resolution item for item in resolutions: try: if not installer.is_installed(item): errors.append(InstallError( "failed to detect successful installation of '{}' " "resolution `{}`".format(installer_name, item))) except InstallerError as e: # TODO: does this here make sense? errors.append(chain_exception( InstallError, "installer '{}' failed to determine if `{}` " "was successfully installed or not". format(installer_name, item), e)) except Exception as e: raise_from( XylemInternalError, "unexpected error in installer '{}' while " "checking successful installation of `{}`". format(installer_name, item), e) # 4. return list of failures if errors: info_v("# [%s] errors during installation" % installer_name) else: info_v("# [%s] successfully installed" % installer_name) return errors
def print_usage(): info("xylem is a package manager abstraction tool.") info("") info("Here are some examples of how to use xylem:") info(" > xylem resolve boost") info(" libboost") info("") info(" > xylem update") info("") info(" > xylem install boost") info("") info("For complete list of options run `xylem -h`")