示例#1
0
文件: helper.py 项目: SulinOS/inary
def check_conflicts(order, packagedb):
    """check if upgrading to the latest versions will cause havoc
    done in a simple minded way without regard for dependencies of
    conflicts, etc."""

    (C, D, pkg_conflicts) = inary.analyzer.conflict.calculate_conflicts(order, packagedb)

    if D:
        raise Exception(
            _("Selected packages \"[{}]\" are in conflict with each other.").format(
                util.strlist(
                    list(D))))

    if pkg_conflicts:
        conflicts = ""
        for pkg in list(pkg_conflicts.keys()):
            conflicts += _(" - [\"{0}\" conflicts with: \"{1}\"]\n").format(
                pkg, util.strlist(pkg_conflicts[pkg]))

        ctx.ui.info(
            _("The following packages have conflicts:\n{}").format(conflicts))

        if not ctx.ui.confirm(_('Remove the following conflicting packages?')):
            raise Exception(
                _("Conflicting packages should be removed to continue."))

    return list(C)
示例#2
0
文件: emerge.py 项目: paledega/inary
def emerge(A):
    """
    Builds and installs the given packages from source
    @param A: list of package names -> list_of_strings
    """
    inary.db.historydb.HistoryDB().create_history("emerge")

    # A was a list, remove duplicates and expand components
    A = [str(x) for x in A]
    A_0 = A = inary.operations.helper.expand_src_components(set(A))
    ctx.ui.debug('A = {}'.format(str(A)))

    if len(A) == 0:
        ctx.ui.info(_('No packages to emerge.'))
        return

    # A |= upgrade_base(A)

    # FIXME: Errr... order_build changes type conditionally and this
    # is not good. - baris
    if not ctx.config.get_option('ignore_dependency'):
        G_f, order_inst, order_build = plan_emerge(A)
    else:
        G_f = None
        order_inst = []
        order_build = A

    if order_inst:
        ctx.ui.info(_("""The following list of packages will be installed
from repository in the respective order to satisfy dependencies:
""") + util.strlist(order_inst))
    ctx.ui.info(_("""The following list of packages will be built and
installed in the respective order to satisfy dependencies:
""") + util.strlist(order_build))

    if ctx.get_option('dry_run'):
        return

    if len(order_inst) + len(order_build) > len(A_0):
        if not ctx.ui.confirm(_('There are extra packages due to dependencies. Would you like to continue?')):
            return False

    ctx.ui.notify(ui.packagestogo, order=order_inst)

    for x in order_inst:
        atomicoperations.install_single_name(x)

    # ctx.ui.notify(ui.packagestogo, order = order_build)

    for x in order_build:
        package_names = operations.build.build(x).new_packages
        inary.operations.install.install_pkg_files(package_names, reinstall=True)  # handle inter-package deps here
        # reset counts between builds
        ctx.ui.errors = ctx.ui.warnings = 0

    # FIXME: take a look at the fixme above :(, we have to be sure
    # that order_build is a known type...
    U = set(order_build)
    U.update(order_inst)
示例#3
0
def takeback(operation):
    """
    Takes back the system to a previous state. Uses inary history to find out which packages were
    installed at the time _after_ the given operation that the system is requested to be taken back.
    @param operation: number of the operation that the system will be taken back -> integer
    """
    historydb = inary.db.historydb.HistoryDB()
    historydb.create_history("takeback")
    beinstalled, beremoved, configs = plan_takeback(operation)
    if not beinstalled and not beremoved:
        ctx.ui.info(
            _("There is no packages to taking back (installing or removing)."))
        return

    if beinstalled:
        ctx.ui.info(
            _("Following packages will be installed:\n") +
            util.strlist(beinstalled))

    if beremoved:
        ctx.ui.info(
            _("Following packages will be removed:\n") +
            util.strlist(beremoved))

    if (beremoved or beinstalled) and not ctx.ui.confirm(
            _('Would you like to continue?')):
        return

    errors = []
    paths = []
    for pkg in beinstalled:
        lndig = math.floor(math.log(len(beinstalled), 10)) + 1
        ctx.ui.info(_("Downloading") +
                    str(" [ {:>" +
                        str(lndig) +
                        "} / {} ] => [{}]").format(beinstalled.index(pkg) +
                                                   1, len(beinstalled), pkg), color="yellow")
        pkg += ctx.const.package_suffix
        if fetch_remote_file(pkg, errors):
            paths.append(os.path.join(ctx.config.cached_packages_dir(), pkg))

    if errors:
        ctx.ui.info(_("\nFollowing packages could not be found in repositories and are not cached:\n") +
                    util.strlist(errors))
        if not ctx.ui.confirm(_('Would you like to continue?')):
            return

    if beremoved:
        operations.remove.remove(beremoved, True, True)

    if paths:
        operations.install.install_pkg_files(paths, True)

    for pkg, operation in configs:
        historydb.load_config(operation, pkg)
示例#4
0
文件: info.py 项目: sulincix/inary
 def print_specdata(spec, sourcedb=None):
     src = spec.source
     if ctx.get_option('short'):
         ctx.ui.formatted_output(" - ".join((src.name, str(src.summary))))
     else:
         ctx.ui.formatted_output(str(spec))
         if sourcedb:
             revdeps = [
                 name
                 for name, dep in sourcedb.get_rev_deps(spec.source.name)
             ]
             print(_('Reverse Build Dependencies:'), util.strlist(revdeps))
             print()
示例#5
0
 def print_metadata(metadata, packagedb=None):
     if ctx.get_option('short'):
         pkg = metadata.package
         ctx.ui.formatted_output(" - ".join((pkg.name, str(pkg.summary))))
     else:
         ctx.ui.formatted_output(str(metadata.package))
         if packagedb:
             revdeps = [
                 name for name, dep in packagedb.get_rev_deps(
                     metadata.package.name)
             ]
             ctx.ui.formatted_output(" ".join(
                 (_("Reverse Dependencies:"), util.strlist(revdeps))))
示例#6
0
def remove(A, ignore_dep=False, ignore_safety=False):
    """
    Removes the given packages from the system
    @param A: list of package names -> list_of_strings
    @param ignore_dep: removes packages without looking into theirs reverse deps if True
    @param ignore_safety: system.base packages can also be removed if True
    """
    inary.db.historydb.HistoryDB().create_history("remove")
    componentdb = inary.db.componentdb.ComponentDB()
    installdb = inary.db.installdb.InstallDB()

    A = [str(x) for x in A]

    # filter packages that are not installed
    A_0 = A = set(A)

    if not ctx.get_option(
            'ignore_safety'
    ) and not ctx.config.values.general.ignore_safety and not ignore_safety:
        if componentdb.has_component('system.base'):
            systembase = set(
                componentdb.get_union_component('system.base').packages)
            refused = A.intersection(systembase)
            if refused:
                raise inary.errors.Error(
                    _("Safety switch prevents the removal of "
                      "following packages:\n") +
                    util.format_by_columns(sorted(refused)))
                A = A - systembase
        else:
            ctx.ui.warning(
                _("Safety switch: The component system.base cannot be found."))

    Ap = []
    for x in A:
        if installdb.has_package(x):
            Ap.append(x)
        else:
            ctx.ui.info(
                _('Package \"{}\" does not exist. Cannot remove.').format(x))
    A = set(Ap)

    if len(A) == 0:
        ctx.ui.info(_('No packages to remove.'))
        return False

    if not ctx.config.get_option('ignore_dependency') and not ignore_dep:
        G_f, order = plan_remove(A)
    else:
        G_f = None
        order = A

    ctx.ui.info(_("""The following list of packages will be removed
in the respective order to satisfy dependencies:"""),
                color='green')
    ctx.ui.info(util.strlist(order))
    if len(order) > len(A_0):
        if not ctx.ui.confirm(_('Would you like to continue?')):
            ctx.ui.warning(_('Package removal declined.'))
            return False

    removal_size = 0
    for pkg in [installdb.get_package(name) for name in order]:
        removal_size += pkg.installedSize

    removal_size, symbol = util.human_readable_size(removal_size)
    ctx.ui.info(_('{:.2f} {} space will be freed.').format(
        removal_size, symbol),
                color='cyan')
    del removal_size, symbol

    if not ctx.ui.confirm(_("Would you like to continue?")):
        ctx.ui.warning(_('Package removal declined.'))
        return False

    if ctx.get_option('dry_run'):
        return

    ctx.ui.notify(ui.packagestogo, order=order)

    for x in order:
        if installdb.has_package(x):
            atomicoperations.remove_single(x)
            if x in installdb.installed_extra:
                installdb.installed_extra.remove(x)
                with open(
                        os.path.join(ctx.config.info_dir(),
                                     ctx.const.installed_extra),
                        "w") as ie_file:
                    ie_file.write("\n".join(installdb.installed_extra) +
                                  ("\n" if installdb.installed_extra else ""))

        else:
            ctx.ui.info(
                _('Package \"{}\" is not installed. Cannot remove.').format(x))
示例#7
0
def install_pkg_files(package_URIs, reinstall=False):
    """install a number of inary package files"""

    installdb = inary.db.installdb.InstallDB()
    ctx.ui.debug('A = {}'.format(str(package_URIs)))

    for x in package_URIs:
        if not x.endswith(ctx.const.package_suffix):
            raise Exception(
                _('Mixing file names and package names not supported yet.'))

    # filter packages that are already installed
    tobe_installed, already_installed = [], set()

    if not reinstall:
        for x in package_URIs:
            pkg_name = util.parse_package_name_get_name(os.path.basename(x))
            if installdb.has_package(pkg_name):
                already_installed.add(pkg_name)
            else:
                tobe_installed.append(x)
        if already_installed:
            ctx.ui.warning(
                _("The following package(s) are already installed "
                  "and are not going to be installed again:"))
            ctx.ui.info(util.format_by_columns(sorted(already_installed)))
        package_URIs = tobe_installed

    if ctx.config.get_option('ignore_dependency'):
        # simple code path then
        for x in package_URIs:
            atomicoperations.install_single_file(x, reinstall)
        return True

    # read the package information into memory first
    # regardless of which distribution they come from
    d_t = {}
    dfn = {}
    for x in package_URIs:
        try:
            package = inary.package.Package(x)
            package.read()
        except zipfile.BadZipfile:
            # YALI needed to get which file is broken
            raise zipfile.BadZipfile(x)
        name = str(package.metadata.package.name)
        d_t[name] = package.metadata.package
        dfn[name] = x

    # check packages' DistributionReleases and Architecture
    if not ctx.get_option('ignore_check'):
        for x in list(d_t.keys()):
            pkg = d_t[x]
            if pkg.distributionRelease > ctx.config.values.general.distribution_release:
                raise Exception(
                    _('Package \"{0}\" is not compatible with your distribution release \'{1}\' \'{2}\'.'
                      ).format(x, ctx.config.values.general.distribution,
                               ctx.config.values.general.distribution_release))
            if pkg.architecture != ctx.config.values.general.architecture:
                raise Exception(
                    _('Package \"{0}\" (\'{1}\') is not compatible with your \'{2}\' architecture.'
                      ).format(x, pkg.architecture,
                               ctx.config.values.general.architecture))

    def satisfiesDep(dep):
        # is dependency satisfied among available packages
        # or packages to be installed?
        return dep.satisfied_by_installed() or dep.satisfied_by_dict_repo(d_t)

    # for this case, we have to determine the dependencies
    # that aren't already satisfied and try to install them
    # from the repository
    dep_unsatis = []
    for name in list(d_t.keys()):
        pkg = d_t[name]
        deps = pkg.runtimeDependencies()
        for dep in deps:
            if not satisfiesDep(dep) and dep.package not in [
                    x.package for x in dep_unsatis
            ]:
                dep_unsatis.append(dep)

    # now determine if these unsatisfied dependencies could
    # be satisfied by installing packages from the repo
    for dep in dep_unsatis:
        if not dep.satisfied_by_repo() and not ctx.config.get_option(
                'ignore_satisfy'):
            raise Exception(
                _('External dependencies not satisfied: \"{}\", \"{}\"').
                format(dep, name))

    # if so, then invoke install_pkg_names
    extra_packages = [x.package for x in dep_unsatis]
    if extra_packages:
        ctx.ui.warning(
            _("The following packages will be installed "
              "in order to satisfy dependencies:"))
        ctx.ui.info(util.format_by_columns(sorted(extra_packages)))
        if not ctx.ui.confirm(_('Would you like to continue?')):
            raise Exception(_('External dependencies not satisfied.'))
        install_pkg_names(extra_packages, reinstall=False, extra=False)

    class PackageDB:
        @staticmethod
        def get_package(key, repo=None):
            return d_t[str(key)]

    packagedb = PackageDB()
    installdb = inary.db.installdb.InstallDB()

    A = list(d_t.keys())

    if len(A) == 0:
        ctx.ui.info(_('No packages to install.'))
        return

    # try to construct a inary graph of packages to
    # install / reinstall

    G_f = pgraph.PGraph(packagedb, installdb)  # construct G_f
    G_f.reinstall = reinstall

    # find the "install closure" graph of G_f by package
    # set A using packagedb
    for x in A:
        G_f.packages.append(x)
    B = A
    while len(B) > 0:
        Bp = set()
        for x in B:
            pkg = packagedb.get_package(x)
            G_f.add_package(x)
            # for dep in pkg.runtimeDependencies():
            #   G_f.add_package(dep)
        B = Bp
    order = G_f.topological_sort()
    if not ctx.get_option('ignore_package_conflicts'):
        conflicts = operations.helper.check_conflicts(order, packagedb)
        if conflicts:
            operations.remove.remove_conflicting_packages(conflicts)
    order.reverse()
    ctx.ui.info(_('Installation order: ') + util.strlist(order))

    if ctx.get_option('dry_run'):
        return True

    ctx.ui.notify(ui.packagestogo, order=order)

    for x in order:
        atomicoperations.install_single_file(dfn[x], reinstall)

    return True