def plan_install_pkg_names(A): # try to construct a pisi graph of packages to # install / reinstall G_f = pgraph.PGraph(ctx.packagedb) # construct G_f # find the "install closure" graph of G_f by package # set A using packagedb for x in A: G_f.add_package(x) B = A while len(B) > 0: Bp = set() for x in B: pkg = ctx.packagedb.get_package(x) for dep in pkg.runtimeDependencies(): ctx.ui.debug('checking %s' % str(dep)) # we don't deal with already *satisfied* dependencies if not dependency.installed_satisfies_dep(dep): if not dep.package in G_f.vertices(): Bp.add(str(dep.package)) G_f.add_dep(x, dep) B = Bp if ctx.config.get_option('debug'): G_f.write_graphviz(sys.stdout) order = G_f.topological_sort() order.reverse() if not ctx.get_option('ignore_file_conflicts'): conflict.check_conflicts(order, ctx.packagedb) return G_f, order
def package_graph(A, repo=db.itembyrepo.installed, ignore_installed=False): """Construct a package relations graph, containing all dependencies of packages A, if ignore_installed option is True, then only uninstalled deps will be added.""" ctx.ui.debug('A = %s' % str(A)) # try to construct a pisi graph of packages to # install / reinstall G_f = pgraph.PGraph(ctx.packagedb, repo) # construct G_f # find the "install closure" graph of G_f by package # set A using packagedb for x in A: G_f.add_package(x) B = A #state = {} while len(B) > 0: Bp = set() for x in B: pkg = ctx.packagedb.get_package(x, repo) #print pkg for dep in pkg.runtimeDependencies(): if ignore_installed: if dependency.installed_satisfies_dep(dep): continue if not dep.package in G_f.vertices(): Bp.add(str(dep.package)) G_f.add_dep(x, dep) B = Bp return G_f
def plan_remove(A): # try to construct a pisi graph of packages to # install / reinstall # construct G_f G_f = pgraph.PGraph(ctx.packagedb, pisi.db.itembyrepo.installed) # find the (install closure) graph of G_f by package # set A using packagedb for x in A: G_f.add_package(x) B = A while len(B) > 0: Bp = set() for x in B: pkg = ctx.packagedb.get_package(x, pisi.db.itembyrepo.installed) assert (pkg) rev_deps = ctx.packagedb.get_rev_deps(x, pisi.db.itembyrepo.installed) for (rev_dep, depinfo) in rev_deps: # we don't deal with uninstalled rev deps # and unsatisfied dependencies (this is important, too) if ctx.packagedb.has_package(rev_dep, pisi.db.itembyrepo.installed) and \ dependency.installed_satisfies_dep(depinfo): if not rev_dep in G_f.vertices(): Bp.add(rev_dep) G_f.add_plain_dep(rev_dep, x) B = Bp if ctx.config.get_option('debug'): G_f.write_graphviz(sys.stdout) order = G_f.topological_sort() return G_f, order
def configure_pending(): # start with pending packages # configure them in reverse topological order of dependency A = ctx.installdb.list_pending() G_f = pgraph.PGraph(ctx.packagedb, pisi.db.itembyrepo.installed) # construct G_f for x in A.keys(): G_f.add_package(x) B = A while len(B) > 0: Bp = set() for x in B.keys(): pkg = ctx.packagedb.get_package(x, pisi.db.itembyrepo.installed) for dep in pkg.runtimeDependencies(): if dep.package in G_f.vertices(): G_f.add_dep(x, dep) B = Bp if ctx.get_option('debug'): G_f.write_graphviz(sys.stdout) order = G_f.topological_sort() order.reverse() try: for x in order: if ctx.installdb.is_installed(x): pkginfo = A[x] pkgname = util.package_name(x, pkginfo.version, pkginfo.release, False, False) pkg_path = util.join_path(ctx.config.lib_dir(), 'package', pkgname) m = MetaData() metadata_path = util.join_path(pkg_path, ctx.const.metadata_xml) m.read(metadata_path) # FIXME: we need a full package info here! pkginfo.name = x ctx.ui.notify(pisi.ui.configuring, package=pkginfo, files=None) pisi.comariface.post_install( pkginfo.name, m.package.providesComar, util.join_path(pkg_path, ctx.const.comar_dir), util.join_path(pkg_path, ctx.const.metadata_xml), util.join_path(pkg_path, ctx.const.files_xml), ) ctx.ui.notify(pisi.ui.configured, package=pkginfo, files=None) ctx.installdb.clear_pending(x) except ImportError: raise Error(_("comar package is not fully installed"))
def plan_upgrade(A, ignore_build=False): # try to construct a pisi graph of packages to # install / reinstall packagedb = ctx.packagedb G_f = pgraph.PGraph(packagedb) # construct G_f # find the "install closure" graph of G_f by package # set A using packagedb for x in A: G_f.add_package(x) B = A # TODO: conflicts while len(B) > 0: Bp = set() for x in B: pkg = packagedb.get_package(x) for dep in pkg.runtimeDependencies(): # add packages that can be upgraded if dependency.repo_satisfies_dep(dep): if ctx.installdb.is_installed(dep.package): if ctx.get_option('eager'): if not is_upgradable(dep.package): continue else: if dependency.installed_satisfies_dep(dep): continue if not dep.package in G_f.vertices(): Bp.add(str(dep.package)) G_f.add_dep(x, dep) else: ctx.ui.error( _('Dependency %s of %s cannot be satisfied') % (dep, x)) raise Error(_("Upgrade is not possible.")) B = Bp # now, search reverse dependencies to see if anything # should be upgraded B = A while len(B) > 0: Bp = set() for x in B: pkg = packagedb.get_package(x) rev_deps = packagedb.get_rev_deps(x) for (rev_dep, depinfo) in rev_deps: if ctx.get_option('eager'): # add all upgradable reverse deps if is_upgradable(rev_dep): if not rev_dep in G_f.vertices(): Bp.add(rev_dep) G_f.add_plain_dep(rev_dep, x) else: # add only installed but unsatisfied reverse dependencies if ctx.installdb.is_installed(rev_dep) and \ (not dependency.installed_satisfies_dep(depinfo)): if not dependency.repo_satisfies_dep(depinfo): raise Error( _('Reverse dependency %s of %s cannot be satisfied' ) % (rev_dep, x)) if not rev_dep in G_f.vertices(): Bp.add(rev_dep) G_f.add_plain_dep(rev_dep, x) B = Bp if ctx.config.get_option('debug'): G_f.write_graphviz(sys.stdout) order = G_f.topological_sort() order.reverse() if not ctx.get_option('ignore_file_conflicts'): conflict.check_conflicts(order, ctx.packagedb) return G_f, order
def install_pkg_files(package_URIs): """install a number of pisi package files""" from pisi.data.package import Package ctx.ui.debug('A = %s' % str(package_URIs)) for x in package_URIs: if not x.endswith(ctx.const.package_suffix): raise Error( _('Mixing file names and package names not supported yet.')) if ctx.config.get_option('ignore_dependency'): # simple code path then for x in package_URIs: install_single_file(x) return # short circuit # read the package information into memory first # regardless of which distribution they come from d_t = {} dfn = {} for x in package_URIs: package = Package(x) package.read() name = str(package.metadata.package.name) d_t[name] = package.metadata.package dfn[name] = x def satisfiesDep(dep): # is dependency satisfied among available packages # or packages to be installed? return dependency.installed_satisfies_dep(dep) \ or dependency.dict_satisfies_dep(d_t, dep) # 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 d_t.keys(): pkg = d_t[name] deps = pkg.runtimeDependencies() for dep in deps: if not satisfiesDep(dep): dep_unsatis.append(dep) # now determine if these unsatisfied dependencies could # be satisfied by installing packages from the repo # if so, then invoke install_pkg_names extra_packages = [x.package for x in dep_unsatis] if extra_packages: ctx.ui.info( _("""The following packages will be installed in the respective order to satisfy extra dependencies: """) + util.strlist(extra_packages)) if not ctx.ui.confirm(_('Do you want to continue?')): raise Error(_('External dependencies not satisfied')) install_pkg_names(extra_packages) class PackageDB: def get_package(self, key, repo=None): return d_t[str(key)] packagedb = PackageDB() A = d_t.keys() if len(A) == 0: ctx.ui.info(_('No packages to install.')) return # try to construct a pisi graph of packages to # install / reinstall G_f = pgraph.PGraph(packagedb) # construct G_f # find the "install closure" graph of G_f by package # set A using packagedb for x in A: G_f.add_package(x) B = A while len(B) > 0: Bp = set() for x in B: pkg = packagedb.get_package(x) for dep in pkg.runtimeDependencies(): if dependency.dict_satisfies_dep(d_t, dep): if not dep.package in G_f.vertices(): Bp.add(str(dep.package)) G_f.add_dep(x, dep) B = Bp if ctx.config.get_option('debug'): G_f.write_graphviz(sys.stdout) order = G_f.topological_sort() if not ctx.get_option('ignore_file_conflicts'): conflict.check_conflicts(order, packagedb) order.reverse() ctx.ui.info(_('Installation order: ') + util.strlist(order)) if ctx.get_option('dry_run'): return ctx.ui.notify(ui.packagestogo, order=order) for x in order: install_single_file(dfn[x])