Viewing file: system-install-packages (13.61 KB) -rwxr-xr-x Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
#!/usr/bin/python -tt
#
# Copyright 2005-2007 Red Hat, Inc.
#
# Jeremy Katz
#
# 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 2 only
#
# 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 Library 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
import os, sys
# # Python gettext:
# import gettext
import logging
try:
import gtk
import gtk.glade
import gtk.gdk as gdk
import gobject
except Exception, e:
print >> sys.stderr, "Unable to import modules. Maybe you're not running under X?"
sys.exit(1)
from rhpl.exception import installExceptionHandler
from rhpl.translate import _, N_, textdomain
from rpmUtils.miscutils import compareEVR
import rpmUtils.arch
import yum.misc
from yum.packages import parsePackages, YumLocalPackage
from yum import logginglevels
import rpm
from pirut import *
from pirut.constants import *
from pirut.Errors import *
if os.path.exists("data/single.glade"):
gladefn = "data/single.glade"
else:
gladefn = "/usr/share/pirut/ui/single.glade"
# # Python gettext:
# t = gettext.translation(I18N_DOMAIN, "/usr/share/locale", fallback = True)
# _ = t.lgettext
class SinglePackageInstaller(GraphicalYumBase):
def __init__(self):
self.xml = gtk.glade.XML(gladefn, domain=I18N_DOMAIN)
self.mainwin = self.xml.get_widget("InstallerWindow")
self._connectSignals()
self._createPackageStore()
self.mainwin.connect("delete_event", self.quit)
# note that nothing which takes "time" should be called here!
GraphicalYumBase.__init__(self, False)
self.unsignedok = True
self.repos_setup = False
self._enabledRepos = self.repos.listEnabled()
map(lambda x: x.disable(), self._enabledRepos)
def _connectSignals(self):
sigs = { "on_InstallerWindow_destroy": self.quit,
"on_quitButton_clicked": self.quit,
"on_applyButton_clicked": self._apply }
self.xml.signal_autoconnect(sigs)
def _createPackageStore(self):
self.store = gtk.ListStore(gobject.TYPE_PYOBJECT)
tree = self.xml.get_widget("packageList")
tree.set_model(self.store)
column = gtk.TreeViewColumn(None, None)
column.set_clickable(True)
txtr = gtk.CellRendererText()
column.pack_start(txtr, True)
column.set_cell_data_func(txtr, self.get_pkg_info)
tree.append_column(column)
def get_pkg_info(self, col, cell, model, i):
pkg = model.get_value(i, 0)
nevra = "%s" %(pkg,)
desc = pkg.returnSimple('summary')
text = "%s\n%s" %(nevra, desc)
text.strip()
cell.set_property("markup", text)
def doRefresh(self, *args):
self._busyCursor()
self.populatePackages()
self._normalCursor()
def logDialog(self, msg):
print msg
d = gtk.MessageDialog(self.mainwin, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO,
gtk.BUTTONS_OK, msg)
d.show_all()
d.run()
d.destroy()
def errorDialog(self, msg):
print msg
d = gtk.MessageDialog(self.mainwin, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR,
gtk.BUTTONS_OK, msg)
d.show_all()
d.run()
d.destroy()
def _populateLocalPackages(self, pkgs):
self.store.clear()
updates = []
installs = []
for pkg in pkgs:
try:
po = YumLocalPackage(ts=self.rpmdb.readOnlyTS(), filename=pkg)
except yum.Errors.MiscError, e:
log = logging.getLogger("yum")
log.warn("Cannot open file: %s. Skipping." %(pkg,))
continue
if po.hdr[rpm.RPMTAG_SOURCEPACKAGE] == 1: # ugh.
self.logDialog(_("Cannot install source packages."))
continue
inst = self.rpmdb.searchNevra(name=po.name)
for instpo in inst:
(n,a,e,v,r) = po.pkgtup
(inn,ia,ie,iv,ir) = instpo.pkgtup
rc = compareEVR((ie,iv,ir), (e,v,r))
if rc < 0: # update
if n not in self.conf.exactarchlist or a == ia:
updates.append((po, instpo))
else:
self.logDialog(_("Can't install a different arch of %s than already installed.") %(pkg,))
continue
elif rc == 0: # same, ignore
self.logDialog("%s is already installed" %(pkg,))
elif rc > 0:
self.logDialog("A newer version than %s is already installed" %(pkg,))
if len(inst) == 0:
installs.append(po)
for po in installs:
self.localPackages.append(po)
self.tsInfo.addInstall(po = po)
self.store.append([po])
for (po, oldpo) in updates:
self.localPackages.append(po)
self.tsInfo.addUpdate(po, oldpo)
self.store.append([po])
def _populateRepoPackages(self, pkgs):
self.store.clear()
self._ensure_repos()
avail = self.pkgSack.returnPackages()
toBeInstalled = {} # keyed on name
updates = []
# FIXME:
# Parsing command line options that aren't local packages gets complex,
# partly because the user has the option of specifying or not specifying
# arch and version. The code below is lifted verbatim from the cli.py
# implementation of 'yum install'. It perhaps should be moved into the
# yum core in some fashion.
#
########################################
# BEGIN CUT-AND-PASTE from cli.py
#
self.verbose_logger.log(logginglevels.INFO_2,
_('Parsing package install arguments'))
for arg in pkgs:
arglist = [arg]
exactmatch, matched, unmatched = parsePackages(avail, arglist,
casematch=1)
if len(unmatched) > 0: # if we get back anything in unmatched, check it for a virtual-provide
arg = unmatched[0] #only one in there
self.verbose_logger.debug('Checking for virtual provide or file-provide for %s',
arg)
try:
mypkg = self.returnPackageByDep(arg)
except yum.Errors.YumBaseError, e:
self.errorDialog(_('No Match for argument: %s') % arg)
# Continuing on and installing only some packages from the requested
# set is probably not useful
self.quit()
else:
arg = '%s:%s-%s-%s.%s' % (mypkg.epoch, mypkg.name,
mypkg.version, mypkg.release,
mypkg.arch)
emtch, mtch, unmtch = parsePackages(avail, [arg])
exactmatch.extend(emtch)
matched.extend(mtch)
installable = yum.misc.unique(exactmatch + matched)
exactarchlist = self.conf.exactarchlist
# we look through each returned possibility and rule out the
# ones that we obviously can't use
for pkg in installable:
if self.rpmdb.installed(po=pkg):
self.verbose_logger.log(logginglevels.DEBUG_3,
'Package %s is already installed, skipping', pkg)
continue
# everything installed that matches the name
installedByKey = self.rpmdb.searchNevra(name=pkg.name)
comparable = []
for instpo in installedByKey:
if rpmUtils.arch.isMultiLibArch(instpo.arch) == rpmUtils.arch.isMultiLibArch(pkg.arch):
comparable.append(instpo)
else:
self.verbose_logger.log(logginglevels.DEBUG_3,
'Discarding non-comparable pkg %s.%s', instpo.name, instpo.arch)
continue
# go through each package
if len(comparable) > 0:
for instpo in comparable:
if pkg.EVR > instpo.EVR: # we're newer - this is an update, pass to them
if instpo.name in exactarchlist:
if pkg.arch == instpo.arch:
updates.append((pkg, instpo))
else:
updates.append((pkg, instpo))
elif pkg.EVR == instpo.EVR: # same, ignore
continue
elif pkg.EVR < instpo.EVR: # lesser, check if the pkgtup is an exactmatch
# if so then add it to be installed
# if it can be multiply installed
# this is where we could handle setting
# it to be an 'oldpackage' revert.
if pkg in exactmatch and self.allowedMultipleInstalls(pkg):
if not toBeInstalled.has_key(pkg.name): toBeInstalled[pkg.name] = []
toBeInstalled[pkg.name].append(pkg)
else: # we've not got any installed that match n or n+a
self.verbose_logger.log(logginglevels.DEBUG_1, 'No other %s installed, adding to list for potential install', pkg.name)
if not toBeInstalled.has_key(pkg.name): toBeInstalled[pkg.name] = []
toBeInstalled[pkg.name].append(pkg)
# this is where I could catch the installs of compat and multilib
# arches on a single yum install command.
pkglist = []
for name in toBeInstalled.keys():
pkglist.extend(self.bestPackagesFromList(toBeInstalled[name]))
#
# END CUT-AND-PASTE from cli.py
#########################################
for po in pkglist:
self.tsInfo.addInstall(po = po)
self.store.append([po])
for (po, oldpo) in updates:
self.tsInfo.addUpdate(po, oldpo)
self.store.append([po])
def populatePackages(self):
locals = []
others = []
# at some point, we should maybe be smarter here
for pkg in sys.argv[1:]:
if os.path.exists(pkg):
locals.append(pkg)
else:
others.append(pkg)
self.doRefreshRepos(progress = False)
if len(locals) > 0:
self._populateLocalPackages(locals)
if len(others) > 0:
self._populateRepoPackages(others)
if not hasattr(self, "tsInfo") or len(self.tsInfo) <= 0:
self.errorDialog(_("No packages were given for installation."))
self.quit()
def _busyCursor(self):
self.mainwin.window.set_cursor(gdk.Cursor(gdk.WATCH))
self.mainwin.set_sensitive(False)
def _normalCursor(self):
self.mainwin.window.set_cursor(None)
self.mainwin.set_sensitive(True)
def _ensure_repos(self):
if self.repos_setup:
return
map(lambda x: x.enable(), self._enabledRepos)
self.doRefreshRepos()
self.repos_setup = True
def _apply(self, *args):
# do a depsolve to see if we need to grab any other stuff... this is
# kind of a hack knowing what resolveDeps does
self.populateTs(test=1)
deps = self.ts.check()
if deps:
self._ensure_repos()
try:
output = self.applyChanges(self.mainwin)
except PirutError:
self.quit()
except OSError:
d = gtk.MessageDialog(self.mainwin, gtk.DIALOG_MODAL,
gtk.BUTTONS_OK,
_("Unable to install software. Error "
"opening files."))
d.show_all()
d.run()
d.destroy()
self.quit()
d = PirutDetailsDialog(self.mainwin, gtk.MESSAGE_INFO,
gtk.BUTTONS_OK,
_("Software installed successfully."))
if output:
d.format_secondary_text("Some warnings were given.")
d.set_details(buffer = outputDictAsTextBuffer(output))
d.run()
d.destroy()
self.quit()
def run(self):
self.mainwin.show_all()
while gtk.events_pending(): gtk.main_iteration()
self.doRefresh()
gtk.main()
def main():
textdomain(I18N_DOMAIN)
gtk.glade.bindtextdomain(I18N_DOMAIN, "/usr/share/locale")
try:
# right now, we have to run privileged...
if os.getuid() != 0:
raise PirutError(_("Must be run as root."))
pkginst = SinglePackageInstaller()
except PirutError, e:
startupError(e)
pkginst.run()
if __name__ == "__main__":
installExceptionHandler("pirut", "")
main()
bool(false)
|