Merge branch 'master' of https://github.com/safaariman/pisi
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2014, marcin.bojara (at) gmail.com
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# Please read the COPYING file.
|
||||
#
|
||||
|
||||
import gettext
|
||||
import optparse
|
||||
|
||||
import pisi.cli.command as command
|
||||
import pisi.context as ctx
|
||||
import pisi.db
|
||||
import pisi.util as util
|
||||
|
||||
__trans = gettext.translation('pisi', fallback=True)
|
||||
_ = __trans.gettext
|
||||
|
||||
|
||||
class ListOrphaned(command.Command, metaclass=command.autocommand):
|
||||
__doc__ = _("""List orphaned packages
|
||||
|
||||
Usage: list-orphaned
|
||||
|
||||
Lists packages installed as dependency, but no longer needed by any other installed package.
|
||||
""")
|
||||
|
||||
def __init__(self, args):
|
||||
super(ListOrphaned, self).__init__(args)
|
||||
self.installdb = pisi.db.installdb.InstallDB()
|
||||
|
||||
name = ("list-orphaned", "lo")
|
||||
|
||||
def options(self):
|
||||
|
||||
group = optparse.OptionGroup(self.parser, _("list-orphaned options"))
|
||||
group.add_option("-a", "--all", action="store_true",
|
||||
default=False, help=_("Show all packages without reverse dependencies"))
|
||||
group.add_option("-x", "--exclude", action="append",
|
||||
default=None, help=_("Ignore packages and components whose basenames match pattern."))
|
||||
self.parser.add_option_group(group)
|
||||
|
||||
def run(self):
|
||||
|
||||
self.init(database = True, write = False)
|
||||
orphaned = self.installdb.get_no_rev_deps() if self.options.all else self.installdb.get_orphaned()
|
||||
|
||||
if self.options.exclude:
|
||||
orphaned = pisi.blacklist.exclude(orphaned, ctx.get_option('exclude'))
|
||||
|
||||
if orphaned:
|
||||
ctx.ui.info(_("Orphaned packages:"))
|
||||
ctx.ui.info(util.format_by_columns(sorted(orphaned)))
|
||||
else: ctx.ui.info(_("No orphaned packages"))
|
||||
+18
-13
@@ -10,55 +10,59 @@
|
||||
# Please read the COPYING file.
|
||||
#
|
||||
|
||||
import sys
|
||||
import optparse
|
||||
|
||||
import gettext
|
||||
__trans = gettext.translation('pisi', fallback=True)
|
||||
_ = __trans.gettext
|
||||
import optparse
|
||||
import sys
|
||||
|
||||
import pisi
|
||||
import pisi.cli
|
||||
import pisi.cli.command as command
|
||||
import pisi.cli.addrepo
|
||||
import pisi.cli.blame
|
||||
import pisi.cli.build
|
||||
import pisi.cli.check
|
||||
import pisi.cli.clean
|
||||
import pisi.cli.command as command
|
||||
import pisi.cli.configurepending
|
||||
import pisi.cli.deletecache
|
||||
import pisi.cli.delta
|
||||
import pisi.cli.disablerepo
|
||||
import pisi.cli.emerge
|
||||
import pisi.cli.enablerepo
|
||||
import pisi.cli.fetch
|
||||
import pisi.cli.graph
|
||||
import pisi.cli.history
|
||||
import pisi.cli.index
|
||||
import pisi.cli.info
|
||||
import pisi.cli.install
|
||||
import pisi.cli.history
|
||||
import pisi.cli.listnewest
|
||||
import pisi.cli.listavailable
|
||||
import pisi.cli.listcomponents
|
||||
import pisi.cli.listinstalled
|
||||
import pisi.cli.listnewest
|
||||
import pisi.cli.listorphaned
|
||||
import pisi.cli.listpending
|
||||
import pisi.cli.listrepo
|
||||
import pisi.cli.listsources
|
||||
import pisi.cli.listupgrades
|
||||
import pisi.cli.rebuilddb
|
||||
import pisi.cli.remove
|
||||
import pisi.cli.removeorphaned
|
||||
import pisi.cli.removerepo
|
||||
import pisi.cli.enablerepo
|
||||
import pisi.cli.disablerepo
|
||||
import pisi.cli.searchfile
|
||||
import pisi.cli.search
|
||||
import pisi.cli.searchfile
|
||||
import pisi.cli.updaterepo
|
||||
import pisi.cli.upgrade
|
||||
|
||||
# FIXME: why does this has to be imported last
|
||||
import pisi.cli.help
|
||||
|
||||
__trans = gettext.translation('pisi', fallback=True)
|
||||
_ = __trans.gettext
|
||||
|
||||
|
||||
class ParserError(pisi.Exception):
|
||||
pass
|
||||
|
||||
|
||||
class PreParser(optparse.OptionParser):
|
||||
"""consumes any options, and finds arguments from command line"""
|
||||
|
||||
@@ -68,11 +72,11 @@ class PreParser(optparse.OptionParser):
|
||||
def error(self, msg):
|
||||
raise ParserError(msg)
|
||||
|
||||
def parse_args(self, args=None):
|
||||
def parse_args(self, args=None, values=None):
|
||||
self.opts = []
|
||||
self.rargs = self._get_args(args)
|
||||
self._process_args()
|
||||
return (self.opts, self.args)
|
||||
return self.opts, self.args
|
||||
|
||||
def _process_args(self):
|
||||
args = []
|
||||
@@ -81,6 +85,7 @@ class PreParser(optparse.OptionParser):
|
||||
first_arg = False
|
||||
while rargs:
|
||||
arg = rargs[0]
|
||||
|
||||
def option():
|
||||
if not self.allow_interspersed_args and first_arg:
|
||||
self.error(_('Options must precede non-option arguments'))
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2014, marcin.bojara (at) gmail.com
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# Please read the COPYING file.
|
||||
#
|
||||
|
||||
import gettext
|
||||
import optparse
|
||||
|
||||
import pisi.api
|
||||
import pisi.cli.command as command
|
||||
import pisi.context as ctx
|
||||
import pisi.db
|
||||
|
||||
__trans = gettext.translation('pisi', fallback=True)
|
||||
_ = __trans.gettext
|
||||
|
||||
|
||||
class RemoveOrphaned(command.PackageOp, metaclass=command.autocommand):
|
||||
__doc__ = _("""Remove orphaned packages
|
||||
|
||||
Usage: remove-orphaned
|
||||
|
||||
Remove all orphaned packages from the system.
|
||||
""")
|
||||
|
||||
def __init__(self,args):
|
||||
super(RemoveOrphaned, self).__init__(args)
|
||||
self.installdb = pisi.db.installdb.InstallDB()
|
||||
|
||||
name = ("remove-orphaned", "ro")
|
||||
|
||||
def options(self):
|
||||
group = optparse.OptionGroup(self.parser, _("remove-orphaned options"))
|
||||
|
||||
super(RemoveOrphaned, self).options(group)
|
||||
group.add_option("-x", "--exclude", action="append",
|
||||
default=None, help=_("When removing orphaned, ignore packages and components whose basenames match pattern."))
|
||||
|
||||
self.parser.add_option_group(group)
|
||||
|
||||
def run(self):
|
||||
|
||||
self.init(database = True, write = False)
|
||||
orphaned = self.installdb.get_orphaned()
|
||||
if ctx.get_option('exclude'):
|
||||
orphaned = pisi.blacklist.exclude(orphaned, ctx.get_option('exclude'))
|
||||
|
||||
pisi.api.remove(orphaned)
|
||||
+3
-2
@@ -36,8 +36,9 @@ def is_char_valid(char):
|
||||
|
||||
def is_method_missing(exception):
|
||||
"""Tells if exception is about missing method in COMAR script"""
|
||||
if exception._dbus_error_name in ("tr.org.pardus.comar.python.missing",
|
||||
"tr.org.pardus.comar.Missing"):
|
||||
if exception.get_dbus_name() in ("tr.org.pardus.comar.python.missing", "tr.org.pardus.comar.Missing"):
|
||||
return True
|
||||
if exception.__context__.get_dbus_name() in ("tr.org.pardus.comar.python.missing", "tr.org.pardus.comar.Missing"):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
@@ -95,6 +95,7 @@ class Constants(metaclass=Singleton):
|
||||
self.__c.needs_reboot = "needsreboot"
|
||||
self.__c.files_db = "files.db"
|
||||
self.__c.repos = "repos"
|
||||
self.__c.installed_extra = "installedextra"
|
||||
|
||||
#file/directory permissions
|
||||
self.__c.umask = 0o022
|
||||
|
||||
@@ -67,6 +67,15 @@ class InstallDB(lazydb.LazyDB):
|
||||
def init(self):
|
||||
self.installed_db = self.__generate_installed_pkgs()
|
||||
self.rev_deps_db = self.__generate_revdeps()
|
||||
self.installed_extra = self.__generate_installed_extra()
|
||||
|
||||
def __generate_installed_extra(self):
|
||||
ie = []
|
||||
ie_path = os.path.join(ctx.config.info_dir(), ctx.const.installed_extra)
|
||||
if os.path.isfile(ie_path):
|
||||
with open(ie_path) as ie_file:
|
||||
ie.extend(ie_file.read().strip().split("\n"))
|
||||
return ie
|
||||
|
||||
def __generate_installed_pkgs(self):
|
||||
def split_name(dirname):
|
||||
@@ -249,6 +258,19 @@ class InstallDB(lazydb.LazyDB):
|
||||
|
||||
return rev_deps
|
||||
|
||||
def get_orphaned(self):
|
||||
"""
|
||||
get list of packages installed as extra dependency,
|
||||
but without reverse dependencies now.
|
||||
"""
|
||||
return [x for x in self.installed_extra if not self.get_rev_deps(x)]
|
||||
|
||||
def get_no_rev_deps(self):
|
||||
"""
|
||||
get installed packages list which haven't reverse dependencies.
|
||||
"""
|
||||
return [x for x in self.installed_db if not self.get_rev_deps(x)]
|
||||
|
||||
def pkg_dir(self, pkg, version, release):
|
||||
return pisi.util.join_path(ctx.config.packages_dir(), pkg + '-' + version + '-' + release)
|
||||
|
||||
|
||||
+3
-1
@@ -20,10 +20,12 @@ import string
|
||||
# lower borks for international locales. What we want is ascii lower.
|
||||
lower_map = str.maketrans(string.ascii_uppercase, string.ascii_lowercase)
|
||||
|
||||
|
||||
class Singleton(object):
|
||||
_the_instances = {}
|
||||
|
||||
def __new__(type):
|
||||
if not type.__name__ in Singleton._the_instances:
|
||||
if type.__name__ not in Singleton._the_instances:
|
||||
Singleton._the_instances[type.__name__] = object.__new__(type)
|
||||
return Singleton._the_instances[type.__name__]
|
||||
|
||||
|
||||
@@ -27,7 +27,8 @@ import pisi.pgraph as pgraph
|
||||
import pisi.ui as ui
|
||||
import pisi.db
|
||||
|
||||
def install_pkg_names(A, reinstall = False):
|
||||
|
||||
def install_pkg_names(A, reinstall=False, extra=False):
|
||||
"""This is the real thing. It installs packages from
|
||||
the repository, trying to perform a minimum number of
|
||||
installs"""
|
||||
@@ -78,7 +79,8 @@ def install_pkg_names(A, reinstall = False):
|
||||
if ctx.get_option('dry_run'):
|
||||
return True
|
||||
|
||||
if set(order) - A_0:
|
||||
extra_packages = set(order) - A_0
|
||||
if extra_packages:
|
||||
if not ctx.ui.confirm(_('There are extra packages due to dependencies. Do you want to continue?')):
|
||||
return False
|
||||
|
||||
@@ -91,10 +93,18 @@ def install_pkg_names(A, reinstall = False):
|
||||
conflicts = operations.helper.check_conflicts(order, packagedb)
|
||||
|
||||
paths = []
|
||||
extra_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)
|
||||
if x in extra_packages or (extra and x in A):
|
||||
extra_paths[install_op.package_fname] = x
|
||||
elif reinstall and 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 ""))
|
||||
|
||||
|
||||
# fetch to be installed packages but do not install them.
|
||||
if ctx.get_option('fetch_only'):
|
||||
@@ -107,6 +117,12 @@ def install_pkg_names(A, reinstall = False):
|
||||
ctx.ui.info(util.colorize(_("Installing %d / %d") % (paths.index(path)+1, len(paths)), "yellow"))
|
||||
install_op = atomicoperations.Install(path)
|
||||
install_op.install(False)
|
||||
try:
|
||||
with open(os.path.join(ctx.config.info_dir(), ctx.const.installed_extra), "a") as ie_file:
|
||||
ie_file.write("%s\n" % extra_paths[path])
|
||||
installdb.installed_extra.append(extra_paths[path])
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
return True
|
||||
|
||||
@@ -199,7 +215,7 @@ def install_pkg_files(package_URIs, reinstall = False):
|
||||
ctx.ui.info(util.format_by_columns(sorted(extra_packages)))
|
||||
if not ctx.ui.confirm(_('Do you want to continue?')):
|
||||
raise pisi.Error(_('External dependencies not satisfied'))
|
||||
install_pkg_names(extra_packages, reinstall=True)
|
||||
install_pkg_names(extra_packages, reinstall=True, extra=True)
|
||||
|
||||
class PackageDB:
|
||||
def get_package(self, key, repo = None):
|
||||
|
||||
@@ -10,19 +10,20 @@
|
||||
# Please read the COPYING file.
|
||||
#
|
||||
|
||||
import gettext
|
||||
import sys
|
||||
|
||||
import gettext
|
||||
import pisi
|
||||
import pisi.atomicoperations as atomicoperations
|
||||
import pisi.context as ctx
|
||||
import pisi.db
|
||||
import pisi.pgraph as pgraph
|
||||
import pisi.ui as ui
|
||||
import pisi.util as util
|
||||
|
||||
__trans = gettext.translation('pisi', fallback=True)
|
||||
_ = __trans.gettext
|
||||
|
||||
import pisi
|
||||
import pisi.context as ctx
|
||||
import pisi.atomicoperations as atomicoperations
|
||||
import pisi.pgraph as pgraph
|
||||
import pisi.util as util
|
||||
import pisi.ui as ui
|
||||
import pisi.db
|
||||
|
||||
def remove(A, ignore_dep = False, ignore_safety = False):
|
||||
"""remove set A of packages from system (A is a list of package names)"""
|
||||
@@ -81,6 +82,10 @@ in the respective order to satisfy dependencies:
|
||||
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 %s is not installed. Cannot remove.') % x)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user