def upgrade_base(A = set()): installdb = pisilinux.db.installdb.InstallDB() componentdb = pisilinux.db.componentdb.ComponentDB() if not ctx.config.values.general.ignore_safety and not ctx.get_option('ignore_safety'): if componentdb.has_component('system.base'): systembase = set(componentdb.get_union_component('system.base').packages) extra_installs = [x for x in systembase - set(A) if not installdb.has_package(x)] extra_installs = pisilinux.blacklist.exclude_from(extra_installs, ctx.const.blacklist) if extra_installs: ctx.ui.warning(_("Safety switch forces the installation of " "following packages:")) ctx.ui.info(util.format_by_columns(sorted(extra_installs))) G_f, install_order = operations.install.plan_install_pkg_names(extra_installs) extra_upgrades = [x for x in systembase - set(install_order) if is_upgradable(x)] upgrade_order = [] extra_upgrades = pisilinux.blacklist.exclude_from(extra_upgrades, ctx.const.blacklist) if ctx.get_option('exclude_from'): extra_upgrades = pisilinux.blacklist.exclude_from(extra_upgrades, ctx.get_option('exclude_from')) if ctx.get_option('exclude'): extra_upgrades = pisilinux.blacklist.exclude(extra_upgrades, ctx.get_option('exclude')) if extra_upgrades: ctx.ui.warning(_("Safety switch forces the upgrade of " "following packages:")) ctx.ui.info(util.format_by_columns(sorted(extra_upgrades))) G_f, upgrade_order = plan_upgrade(extra_upgrades, force_replaced=False) # return packages that must be added to any installation return set(install_order + upgrade_order) else: ctx.ui.warning(_('Safety switch: The component system.base cannot be found.')) return set()
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 find_upgrades(packages, replaces): packagedb = pisilinux.db.packagedb.PackageDB() installdb = pisilinux.db.installdb.InstallDB() debug = ctx.config.get_option("debug") security_only = ctx.get_option('security_only') comparesha1sum = ctx.get_option('compare_sha1sum') Ap = [] ds = [] for i_pkg in packages: if i_pkg in list(replaces.keys()): # Replaced packages will be forced for upgrade, cause replaced packages are marked as obsoleted also. So we # pass them. continue if i_pkg.endswith(ctx.const.package_suffix): ctx.ui.debug(_("Warning: package *name* ends with '.pisilinux'")) if not installdb.has_package(i_pkg): ctx.ui.info(_('Package %s is not installed.') % i_pkg, True) continue if not packagedb.has_package(i_pkg): ctx.ui.info(_('Package %s is not available in repositories.') % i_pkg, True) continue pkg = packagedb.get_package(i_pkg) hash = installdb.get_install_tar_hash(i_pkg) (version, release, build, distro, distro_release) = installdb.get_version_and_distro_release(i_pkg) if security_only and not pkg.has_update_type("security", release): continue if pkg.distribution == distro and \ pisilinux.version.make_version(pkg.distributionRelease) > pisilinux.version.make_version(distro_release): Ap.append(i_pkg) else: if int(release) < int(pkg.release): Ap.append(i_pkg) elif comparesha1sum and \ int(release) == int(pkg.release) and \ not pkg.installTarHash == hash: Ap.append(i_pkg) ds.append(i_pkg) else: ctx.ui.info(_('Package %s is already at the latest release %s.') % (pkg.name, pkg.release), True) if debug and ds: ctx.ui.status(_('The following packages have different sha1sum:')) ctx.ui.info(util.format_by_columns(sorted(ds))) return Ap
def upgrade(A=[], repo=None): """Re-installs packages from the repository, trying to perform a minimum or maximum number of upgrades according to options.""" packagedb = pisilinux.db.packagedb.PackageDB() installdb = pisilinux.db.installdb.InstallDB() replaces = packagedb.get_replaces() if not A: # if A is empty, then upgrade all packages A = installdb.list_installed() if repo: repo_packages = set(packagedb.list_packages(repo)) A = set(A).intersection(repo_packages) A_0 = A = set(A) Ap = find_upgrades(A, replaces) A = set(Ap) # Force upgrading of installed but replaced packages or else they will be removed (they are obsoleted also). # This is not wanted for a replaced driver package (eg. nvidia-X). A |= set(pisilinux.util.flatten_list(list(replaces.values()))) A |= upgrade_base(A) A = pisilinux.blacklist.exclude_from(A, ctx.const.blacklist) if ctx.get_option('exclude_from'): A = pisilinux.blacklist.exclude_from(A, ctx.get_option('exclude_from')) if ctx.get_option('exclude'): A = pisilinux.blacklist.exclude(A, ctx.get_option('exclude')) ctx.ui.debug('A = %s' % str(A)) if len(A)==0: ctx.ui.info(_('No packages to upgrade.')) return True ctx.ui.debug('A = %s' % str(A)) if not ctx.config.get_option('ignore_dependency'): G_f, order = plan_upgrade(A, replaces=replaces) else: G_f = None order = list(A) componentdb = pisilinux.db.componentdb.ComponentDB() # Bug 4211 if componentdb.has_component('system.base'): order = operations.helper.reorder_base_packages(order) ctx.ui.status(_('The following packages will be upgraded:')) ctx.ui.info(util.format_by_columns(sorted(order))) total_size, cached_size = operations.helper.calculate_download_sizes(order) total_size, symbol = util.human_readable_size(total_size) ctx.ui.info(util.colorize(_('Total size of package(s): %.2f %s') % (total_size, symbol), "yellow")) needs_confirm = check_update_actions(order) # NOTE: replaces.values() was already flattened above, it can be reused if set(order) - A_0 - set(pisilinux.util.flatten_list(list(replaces.values()))): ctx.ui.warning(_("There are extra packages due to dependencies.")) needs_confirm = True if ctx.get_option('dry_run'): return if needs_confirm and \ not ctx.ui.confirm(_("Do you want to continue?")): return False ctx.ui.notify(ui.packagestogo, order = order) conflicts = [] if not ctx.get_option('ignore_package_conflicts'): conflicts = operations.helper.check_conflicts(order, packagedb) paths = [] for x in order: ctx.ui.info(util.colorize(_("Downloading %d / %d") % (order.index(x)+1, len(order)), "yellow")) install_op = atomicoperations.Install.from_name(x) paths.append(install_op.package_fname) # fetch to be upgraded packages but do not install them. if ctx.get_option('fetch_only'): return if conflicts: operations.remove.remove_conflicting_packages(conflicts) operations.remove.remove_obsoleted_packages() for path in paths: ctx.ui.info(util.colorize(_("Installing %d / %d") % (paths.index(path)+1, len(paths)), "yellow")) install_op = atomicoperations.Install(path, ignore_file_conflicts = True) install_op.install(not ctx.get_option('compare_sha1sum'))
def install_pkg_names(A, reinstall = False): """This is the real thing. It installs packages from the repository, trying to perform a minimum number of installs""" installdb = pisilinux.db.installdb.InstallDB() packagedb = pisilinux.db.packagedb.PackageDB() A = [str(x) for x in A] #FIXME: why do we still get unicode input here? :/ -- exa # A was a list, remove duplicates A_0 = A = set(A) # filter packages that are already installed if not reinstall: Ap = set([x for x in A if not installdb.has_package(x)]) d = A - Ap if len(d) > 0: 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(d))) A = Ap if len(A)==0: ctx.ui.info(_('No packages to install.')) return True A |= operations.upgrade.upgrade_base(A) if not ctx.config.get_option('ignore_dependency'): G_f, order = plan_install_pkg_names(A) else: G_f = None order = list(A) componentdb = pisilinux.db.componentdb.ComponentDB() # Bug 4211 if componentdb.has_component('system.base'): order = operations.helper.reorder_base_packages(order) if len(order) > 1: ctx.ui.info(util.colorize(_("Following packages will be installed:"), "brightblue")) ctx.ui.info(util.format_by_columns(sorted(order))) total_size, cached_size = operations.helper.calculate_download_sizes(order) total_size, symbol = util.human_readable_size(total_size) ctx.ui.info(util.colorize(_('Total size of package(s): %.2f %s') % (total_size, symbol), "yellow")) if ctx.get_option('dry_run'): return True if set(order) - 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) ignore_dep = ctx.config.get_option('ignore_dependency') conflicts = [] if not ctx.get_option('ignore_package_conflicts'): conflicts = operations.helper.check_conflicts(order, packagedb) paths = [] for x in order: ctx.ui.info(util.colorize(_("Downloading %d / %d") % (order.index(x)+1, len(order)), "yellow")) install_op = atomicoperations.Install.from_name(x) paths.append(install_op.package_fname) # fetch to be installed packages but do not install them. if ctx.get_option('fetch_only'): return if conflicts: operations.remove.remove_conflicting_packages(conflicts) for path in paths: ctx.ui.info(util.colorize(_("Installing %d / %d") % (paths.index(path)+1, len(paths)), "yellow")) install_op = atomicoperations.Install(path) install_op.install(False) return True
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