def emerge(A): # A was a list, remove duplicates and expand components A = [str(x) for x in A] A_0 = A = pisilinux.operations.helper.expand_src_components(set(A)) ctx.ui.debug('A = %s' % 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. Do you want 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 = atomicoperations.build(x).new_packages pisilinux.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)
def check_build_dependencies(self): """check and try to install build dependencies, otherwise fail.""" build_deps = self.spec.source.buildDependencies for package in self.spec.packages: build_deps.extend(package.buildDependencies) if not ctx.config.values.general.ignore_safety and not ctx.get_option("ignore_safety"): if self.componentdb.has_component("system.devel"): build_deps_names = set([x.package for x in build_deps]) devel_deps_names = set(self.componentdb.get_component("system.devel").packages) extra_names = devel_deps_names - build_deps_names extra_names = [x for x in extra_names if not self.installdb.has_package(x)] if extra_names: ctx.ui.warning( _("Safety switch: following extra packages in system.devel will be installed: ") + util.strlist(extra_names) ) extra_deps = [dependency.Dependency(package=x) for x in extra_names] build_deps.extend(extra_deps) else: ctx.ui.warning(_("Safety switch: the component system.devel cannot be found")) # find out the build dependencies that are not satisfied... dep_unsatis = [] for dep in build_deps: if not dep.satisfied_by_installed(): dep_unsatis.append(dep) if dep_unsatis: ctx.ui.info(_("Unsatisfied Build Dependencies:") + " " + util.strlist([str(x) for x in dep_unsatis])) def fail(): raise Error(_("Cannot build package due to unsatisfied build dependencies")) if not ctx.config.get_option("ignore_dependency"): for dep in dep_unsatis: if not dep.satisfied_by_repo(): raise Error(_("Build dependency %s cannot be satisfied") % str(dep)) if ctx.ui.confirm(_("Do you want to install the unsatisfied build dependencies")): ctx.ui.info(_("Installing build dependencies.")) if not pisilinux.api.install([dep.package for dep in dep_unsatis], reinstall=True): fail() else: fail() else: ctx.ui.warning(_("Ignoring build dependencies."))
def remove(A, ignore_dep = False, ignore_safety = False): """remove set A of packages from system (A is a list of package names)""" componentdb = pisilinux.db.componentdb.ComponentDB() installdb = pisilinux.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 pisilinux.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 %s does not exist. Cannot remove.') % 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: """) + util.strlist(order)) if len(order) > len(A_0): if not ctx.ui.confirm(_('Do you want 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) else: ctx.ui.info(_('Package %s is not installed. Cannot remove.') % x)
def print_specdata(self, 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()
def print_metadata(self, 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)))) print()
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) = pisilinux.conflict.calculate_conflicts(order, packagedb) if D: raise Exception(_("Selected packages [%s] are in conflict with each other.") % util.strlist(list(D))) if pkg_conflicts: conflicts = "" for pkg in list(pkg_conflicts.keys()): conflicts += _("[%s conflicts with: %s]\n") % (pkg, util.strlist(pkg_conflicts[pkg])) ctx.ui.info(_("The following packages have conflicts:\n%s") % conflicts) if not ctx.ui.confirm(_('Remove the following conflicting packages?')): raise Exception(_("Conflicting packages should be removed to continue")) return list(C)
def install_pkg_files(package_URIs, reinstall = False): """install a number of pisilinux package files""" installdb = pisilinux.db.installdb.InstallDB() ctx.ui.debug('A = %s' % 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: if not x.endswith(ctx.const.delta_package_suffix) and x.endswith(ctx.const.package_suffix): pkg_name, pkg_version = pisilinux.util.parse_package_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 = pisilinux.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 %s is not compatible with your distribution release %s %s.') \ % (x, ctx.config.values.general.distribution, \ ctx.config.values.general.distribution_release)) if pkg.architecture != ctx.config.values.general.architecture: raise Exception(_('Package %s (%s) is not compatible with your %s architecture.') \ % (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(): raise Exception(_('External dependencies not satisfied: %s') % dep) # 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(_('Do you want to continue?')): raise Exception(_('External dependencies not satisfied')) install_pkg_names(extra_packages, reinstall=True) class PackageDB: def get_package(self, key, repo = None): return d_t[str(key)] packagedb = PackageDB() A = list(d_t.keys()) if len(A)==0: ctx.ui.info(_('No packages to install.')) return # try to construct a pisilinux 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 dep.satisfied_by_dict_repo(d_t): 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_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
def pisilinux_installed(*args): packages = util.strlist(args).rstrip() os.system("pisilinux -D%s install %s" % (consts.pisilinux_db, packages))
def pisilinux_removed(*args): packages = util.strlist(args).rstrip() os.system("pisilinux -D%s remove %s" % (consts.pisilinux_db, packages))