home *** CD-ROM | disk | FTP | other *** search
- # app.py - the application main program of Computer Janitor
- # Copyright (C) 2008, 2009 Canonical, Ltd.
- #
- # 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, version 3 of the License.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-
- import ConfigParser
- import logging
- import logging.handlers
- import optparse
- import os
- import sys
-
- import computerjanitor
- import computerjanitorapp
- _ = computerjanitorapp.setup_gettext()
-
-
- DEFAULT_PLUGINS_DIRS = "/usr/share/computerjanitor/plugins"
- DEFAULT_STATE_FILE = "/var/lib/computer-janitor/state.dat"
-
-
- class SourcesListProblem(computerjanitor.Exception):
-
- def __init__(self, missing_package):
- self._str = _("Essential package %s is missing. There may be "
- "problems with apt sources.list or Packages files may "
- "be missing?") % missing_package
-
-
- class AsciiFormatter(logging.Formatter):
-
- def format(self, record): # pragma: no cover
- msg = logging.Formatter.format(self, record)
- return msg.encode('ascii', 'replace')
-
-
- def setup_logging(): # pragma: no cover
- if os.environ.get("COMPUTER_JANITOR_DEBUG", None) == "yes":
- level = logging.DEBUG
- elif os.environ.get("COMPUTER_JANITOR_UNITTEST", None) == "yes":
- level = logging.CRITICAL
- else:
- level = logging.INFO
- logging.basicConfig(level=level, format="%(levelname)s: %(message)s")
-
- try:
- formatter = AsciiFormatter(
- "computer-janitor %(levelname)s: %(message)s")
- handler = logging.handlers.SysLogHandler("/dev/log")
- handler.setLevel(level)
- handler.setFormatter(formatter)
- logging.getLogger().addHandler(handler)
- except:
- # We're OK with something going wrong.
- logging.debug(_("Logging to syslog cannot be set up."))
-
-
- class Application(object):
-
- """The main class for the program."""
-
- whitelist_dirs = ["/etc/computer-janitor.d"]
-
- def __init__(self, apt=None):
- self.state = computerjanitorapp.State()
- self.parser = self.create_option_parser()
- self.apt = computerjanitor.apt
- if apt is not None:
- self.apt = apt
- self.refresh_apt_cache()
-
- # The Plugin API requires that we have a config that is a
- # ConfigParser. We don't use it for anything, for now.
- self.config = ConfigParser.ConfigParser()
-
- def run(self, ui_class,
- plugin_manager_class=computerjanitor.PluginManager):
- setup_logging()
- logging.debug(_("Running application, with:"))
- logging.debug(" plugin_manager_class=%s" % plugin_manager_class)
-
- options, args = self.parse_options()
-
- pluginpath = os.environ.get("COMPUTER_JANITOR_PLUGINS",
- DEFAULT_PLUGINS_DIRS)
- plugindirs = pluginpath.split(":")
- pm = plugin_manager_class(self, plugindirs)
-
- ui = ui_class(self, pm)
- ui.run(options, args)
-
- def create_option_parser(self): # pragma: no cover
- parser = optparse.OptionParser(version="%%prog %s" %
- computerjanitorapp.VERSION)
-
- parser.usage = _("""
- %prog [options] find
- %prog [options] cleanup [CRUFT]...
- %prog [options] ignore [CRUFT]...
- %prog [options] unignore [CRUFT]...
-
- %prog finds and removes cruft from your system.
-
- Cruft is anything that shouldn't be on the system, but is. Stretching
- the definition, it is also things that should be on the system, but
- aren't.""")
-
- parser.add_option("--all", action="store_true",
- help=_("Make the 'cleanup' command remove all "
- "packages, if none are given on the "
- "command line."))
-
- parser.add_option("--state-file", metavar="FILE",
- default=DEFAULT_STATE_FILE,
- help=_("Store state of each piece of cruft in "
- "FILE. (Default is %default)."))
-
- parser.add_option("--no-act", action="store_true",
- help=_("Don't actually remove anything, just "
- "pretend to do so. This is useful for "
- "testing stuff."))
-
- parser.add_option("--verbose", action="store_true",
- help=_("Verbose operation: make find show an "
- "explanation for each piece of cruft "
- "found."))
-
- return parser
-
- def parse_options(self, args=None):
- return self.parser.parse_args(args=args)
-
- def refresh_apt_cache(self):
- self.apt_cache = self.apt.Cache()
- self.apt_cache._depcache.ReadPinFile("/var/lib/synaptic/preferences")
-
- def verify_apt_cache(self):
- for name in ["dash", "gzip"]:
- if name not in self.apt_cache:
- raise SourcesListProblem(name)
- if not self.apt_cache[name].candidateDownloadable:
- raise SourcesListProblem(name)
-
- def whitelist_files(self, dirnames):
- """Find files with whitelists in a list of directories.
-
- The directory is scanned for files ending in ".whitelist".
- Subdirectories are not scanned.
-
- """
-
- list = []
- for dirname in dirnames:
- try:
- basenames = os.listdir(dirname)
- whitelists = [x for x in basenames if x.endswith(".whitelist")]
- list += [os.path.join(dirname, x) for x in whitelists]
- except os.error:
- pass
-
- return list
-
- def whitelisted_cruft(self, dirnames=None):
- """Return list of cruft that is whitelisted."""
-
- dirnames = dirnames or self.whitelist_dirs
-
- list = []
- for filename in self.whitelist_files(dirnames):
- f = file(filename, "r")
- for line in f.readlines():
- line = line.strip()
- if line and not line.startswith("#"):
- list.append(line)
- f.close()
-
- return list
-
- def remove_whitelisted(self, crufts, dirnames=None):
- whitelisted = self.whitelisted_cruft(dirnames=dirnames)
- return [c for c in crufts if c.get_name() not in whitelisted]
-