Example #1
0
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)
Example #2
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)
Example #3
0
def main(args=None):
    args = command_handle_args(args, definition)
    try:
        update(dry_run=args.dry_run)
    except (KeyboardInterrupt, EOFError):
        info('')
        sys.exit(1)
Example #4
0
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)
Example #5
0
def main(args=None):
    args = command_handle_args(args, definition)
    try:
        update(dry_run=args.dry_run)
    except (KeyboardInterrupt, EOFError):
        info('')
        sys.exit(1)
Example #6
0
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)
Example #7
0
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)
Example #8
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)
Example #9
0
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)
Example #10
0
    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)
Example #11
0
    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)
Example #12
0
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)
Example #13
0
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)
Example #14
0
 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))
Example #15
0
 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))
Example #16
0
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)
Example #17
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()
Example #18
0
    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)))
Example #19
0
    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)))
Example #20
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()
Example #21
0
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
Example #22
0
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`")