#!/usr/bin/python # Copyright (C) 2009 Canonical # # Authors: # Michael Vogt # # 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. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # We have to import Gio before everything, for dynamic PK to work. try: from gi.repository import Gio except: pass import locale import gettext import logging import os import os.path import sys import time import xapian from optparse import OptionParser from softwarecenter.enums import * from softwarecenter.paths import XAPIAN_BASE_PATH from softwarecenter.db.update import rebuild_database import softwarecenter.paths # dbus may not be available during a upgrade so we # only set it up if its there try: import dbus import dbus.service from gi.repository import GLib, GObject from dbus.mainloop.glib import DBusGMainLoop except ImportError as e: logging.warn("failure to import: '%s'" % e) # add a bit of extra time between sending the "we-rebuild-the-db-now" # signal and the actual rebuilding to help the applications to shutdown # the DB access APP_CATCHUP_DELAY = 2 # the language pack directory that we need for the triggers checking LANGPACKDIR = "/usr/share/locale-langpack" logging.basicConfig(level=logging.INFO) LOG = logging.getLogger("softwarecenter.db.update") class UpdateSoftwarecenterDbus(dbus.service.Object): """ This is a helper to provide the UpdateSoftwarecenterIFace """ def __init__(self, bus_name, object_path='/com/ubuntu/Softwarecenter'): dbus.service.Object.__init__(self, bus_name, object_path) @dbus.service.method('com.ubuntu.Softwarecenter') def IsRebuilding(self): return True @dbus.service.signal(dbus_interface='com.ubuntu.Softwarecenter', signature='b') def DatabaseRebuilding(self, isRebuilding): LOG.debug("Sending DatabaseRebuilding signal '%s'" % isRebuilding) if __name__ == "__main__": try: locale.setlocale(locale.LC_ALL, "") except Exception, e: LOG.warn("setlocale failed with '%s'" % e) # parser parser = OptionParser() parser.add_option("--triggered", "", default="", help="triggered from dpkg") parser.add_option("--local", "", action="store_true", default=False, help="update local database") parser.add_option("--appstream-only", "", action="store_true", default=False, help="appstream app-info only") parser.add_option("--appstream-xml-path", "", default=None, help="set different appstream xml rootdir") parser.add_option("--debug", "", action="store_true", default=False, help="show debug output") parser.add_option("--use-packagekit", action="store_true", help="use PackageKit backend (experimental)", default=False) parser.add_option("--app-install-desktop-dir", "", default=None) parser.add_option("--target-db-path", "", default=None) (options, args) = parser.parse_args() #logging.basicConfig(level=logging.INFO) if options.debug: LOG.setLevel(logging.DEBUG) # setup directories if options.target_db_path: xapian_base_path = options.target_db_path elif options.local: if not os.path.exists('./data'): LOG.error("trying to update local database, ./data does not exist") sys.exit(-1) LOG.info("updating local database") xapian_base_path = './data' else: xapian_base_path = XAPIAN_BASE_PATH if options.appstream_only: LOG.info("updating only information from app-info") if options.appstream_xml_path: softwarecenter.paths.APPSTREAM_XML_PATH = options.appstream_xml_path if options.use_packagekit: LOG.info("using the PackageKit backend") softwarecenter.enums.USE_PACKAGEKIT_BACKEND = True # check if we are dpkg triggered because of langpack change # and avoid unneeded database rebuilds by checking the timestamp # of the app-install-data mo file if options.triggered and options.triggered == LANGPACKDIR: LOG.debug("triggered with '%s'" % options.triggered) mofile = gettext.find("app-install-data") if not mofile: LOG.info("no translation information in database needed") sys.exit(0) mo_time = os.path.getctime(mofile) pathname = os.path.join(xapian_base_path, "xapian") if os.path.exists(pathname): db = xapian.Database(pathname) mo_db_time = db.get_metadata("app-install-mo-time") LOG.debug("mo_time: %s db_mo_time: %s" % (mo_time, mo_db_time)) if str(mo_time) == mo_db_time: LOG.info("translation information in database is up-to-date") sys.exit(0) # setup dbus dbus_controller = None try: DBusGMainLoop(set_as_default=True) bus = dbus.SystemBus() bus_name = dbus.service.BusName('com.ubuntu.Softwarecenter', bus) dbus_controller = UpdateSoftwarecenterDbus(bus_name) dbus_controller.DatabaseRebuilding(True) time.sleep(APP_CATCHUP_DELAY) except: LOG.warn("Failed to setup dbus (ignoring)") # rebuild and send signal when done try: # setup path pathname = os.path.join(xapian_base_path, "xapian") if not os.path.exists(pathname): os.makedirs(pathname) # rebuild the database, the default context is run to ensure # dbus queries are processed print "Updating software catalog...this may take a moment." if options.appstream_only: result = rebuild_database(pathname, debian_sources=False, appstream_sources=True) else: result = rebuild_database( pathname, appinfo_dir=options.app_install_desktop_dir) if result: print "Software catalog update was successful." else: print "There was a problem updating the software catalog. Please try again or check the log." finally: # signal that the xapian db is valid again if dbus_controller: time.sleep(APP_CATCHUP_DELAY) dbus_controller.DatabaseRebuilding(False) context = GLib.main_context_default() while context.pending(): context.iteration()