From 6ee3d6b975489d5d2aac06e72ad34f5e28ff6770 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Sat, 30 Jul 2011 21:21:32 +0200 Subject: [PATCH] Add support to remove content of packages in the filesystem. --- pakfire/actions.py | 22 +++++----- pakfire/cli.py | 5 ++- pakfire/packages/base.py | 75 ++++++++++++++++++++++++++++++++++ pakfire/packages/file.py | 4 ++ pakfire/packages/installed.py | 4 ++ pakfire/repository/database.py | 11 +++++ pakfire/transaction.py | 2 + 7 files changed, 111 insertions(+), 12 deletions(-) diff --git a/pakfire/actions.py b/pakfire/actions.py index ac1cbc3ed..a4c77d9fa 100644 --- a/pakfire/actions.py +++ b/pakfire/actions.py @@ -10,7 +10,7 @@ from i18n import _ class Action(object): def __init__(self, pakfire, pkg): self.pakfire = pakfire - self.pkg = pkg + self.pkg_solv = self.pkg = pkg # Try to get the binary version of the package from the cache if # any. @@ -18,10 +18,6 @@ class Action(object): if binary_package: self.pkg = binary_package - def __cmp__(self, other): - # XXX ugly - return cmp(self.__repr__(), other.__repr__()) - def __repr__(self): return "<%s %s>" % (self.__class__.__name__, self.pkg.friendly_name) @@ -98,16 +94,20 @@ class ActionUpdate(Action): self._extract(_("Updating")) -class ActionRemove(ActionCleanup): +class ActionRemove(Action): type = "erase" - def run(self): - files = self.pkg.filelist + def __init__(self, *args, **kwargs): + Action.__init__(self, *args, **kwargs) - if not files: - return + # XXX This is ugly, but works for the moment. + self.pkg = self.local.index.db.get_package_from_solv(self.pkg_solv) + assert self.pkg + + def run(self): + self.pkg.remove(_("Removing"), prefix=self.pakfire.path) - self.remove_files(_("Removing: %s") % self.pkg.name, files) + # XXX Remove package from database class ActionReinstall(Action): diff --git a/pakfire/cli.py b/pakfire/cli.py index 87d747584..0fc56e74e 100644 --- a/pakfire/cli.py +++ b/pakfire/cli.py @@ -329,6 +329,8 @@ class CliBuilder(Cli): sub_shell.add_argument("-a", "--arch", help=_("Emulated architecture in the shell.")) + sub_shell.add_argument("-m", "--mode", nargs="?", default="development", + help=_("Mode to run in. Is either 'release' or 'development' (default).")) def parse_command_dist(self): # Implement the "dist" command. @@ -382,7 +384,8 @@ class CliBuilder(Cli): "arch" : self.args.arch, } - pakfire.shell(pkg, distro_config=distro_config, **self.pakfire_args) + pakfire.shell(pkg, builder_mode=self.args.mode, + distro_config=distro_config, **self.pakfire_args) def handle_dist(self): # Get the packages from the command line options diff --git a/pakfire/packages/base.py b/pakfire/packages/base.py index ecf7f99cf..a068831a5 100644 --- a/pakfire/packages/base.py +++ b/pakfire/packages/base.py @@ -2,12 +2,15 @@ import datetime import logging +import os import xml.sax.saxutils import util from pakfire.i18n import _ +from pakfire.util import make_progress + class Package(object): def __init__(self, pakfire, repo=None): self.pakfire = pakfire @@ -350,3 +353,75 @@ class Package(object): def extract(self, path, prefix=None): raise NotImplementedError, "%s" % repr(self) + + def remove(self, message=None, prefix=None): + if prefix in ("/", None): + prefix = "" + + # Make two filelists. One contains all binary files that need to be + # removed, the other one contains the configuration files which are + # kept. files and configfiles are disjunct. + files = [] + configfiles = self.configfiles + + for file in self.filelist: + if file in configfiles: + continue + + assert file.startswith("/") + files.append(file) + + # Load progressbar. + pb = None + if message: + message = "%-10s : %s" % (message, self.friendly_name) + pb = make_progress(message, len(files), eta=False) + + # Sort files by the length of their name to remove all files in + # a directory first and then check, if there are any files left. + files.sort(cmp=lambda x,y: cmp(len(x), len(y)), reverse=True) + + i = 0 + for _file in files: + # Update progress. + if pb: + i += 1 + pb.update(i) + + logging.debug("Removing file: %s" % _file) + + if prefix: + file = os.path.join(prefix, file[1:]) + assert file.startswith("%s/" % prefix) + else: + file = _file + + # If the file was removed by the user, we can skip it. + if not os.path.exists(file): + continue + + # Handle regular files and symlinks. + if os.path.isfile(file) or os.path.islink(file): + try: + os.remove(file) + except OSError: + logging.error("Cannot remove file: %s. Remove manually." % _file) + + # Handle directories. + # Skip removal if the directory is a mountpoint. + elif os.path.isdir(file) and not os.path.ismount(file): + # Try to remove the directory. If it is not empty, OSError is raised, + # but we are okay with that. + try: + os.rmdir(file) + except OSError: + pass + + # Log all unhandled types. + else: + logging.warning("Cannot remove file: %s. Filetype is unhandled." % _file) + + if pb: + pb.finish() + + # XXX Rename config files diff --git a/pakfire/packages/file.py b/pakfire/packages/file.py index 3ee069dcf..a07cab99d 100644 --- a/pakfire/packages/file.py +++ b/pakfire/packages/file.py @@ -305,6 +305,10 @@ class FilePackage(Package): return self.__filelist + @property + def configfiles(self): + return [] # XXX to be done + @property def payload_compression(self): """ diff --git a/pakfire/packages/installed.py b/pakfire/packages/installed.py index 31b03b4f2..bf044af6d 100644 --- a/pakfire/packages/installed.py +++ b/pakfire/packages/installed.py @@ -151,6 +151,10 @@ class DatabasePackage(Package): finally: c.close() + @property + def configfiles(self): + return [] # XXX to be done + def _does_provide_file(self, requires): """ A faster version to find a file in the database. diff --git a/pakfire/repository/database.py b/pakfire/repository/database.py index 89579152a..e6d5aa7cb 100644 --- a/pakfire/repository/database.py +++ b/pakfire/repository/database.py @@ -227,3 +227,14 @@ class DatabaseLocal(Database): yield packages.DatabasePackage(self.pakfire, self.repo, self, row) c.close() + + def get_package_from_solv(self, solv_pkg): + c = self.cursor() + c.execute("SELECT * FROM packages WHERE uuid = ? LIMIT 1", (solv_pkg.uuid,)) + + try: + for row in c: + return packages.DatabasePackage(self.pakfire, self.repo, self, row) + + finally: + c.close() diff --git a/pakfire/transaction.py b/pakfire/transaction.py index 944e6e131..5f2255079 100644 --- a/pakfire/transaction.py +++ b/pakfire/transaction.py @@ -200,3 +200,5 @@ class Transaction(object): action.run() except ActionError, e: logging.error("Action finished with an error: %s - %s" % (action, e)) + + logging.info("") -- 2.39.5