Files
entropy/spritz/src/packages.py
T

423 lines
15 KiB
Python

#!/usr/bin/python -tt
# -*- coding: iso-8859-1 -*-
# Yum Exteder (yumex) - A GUI for yum
# Copyright (C) 2006 Tim Lauridsen < tim<AT>yum-extender<DOT>org >
#
# 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.
#
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
from etpgui.packages import EntropyPackage, DummyEntropyPackage
import logging
from spritz_setup import SpritzConf
from entropy.i18n import _
from entropy.const import *
from entropy.exceptions import *
class EntropyPackages:
def __init__(self, EquoInstance):
self.Entropy = EquoInstance
self.logger = logging.getLogger('yumex.Packages')
self.filterCallback = None
self._packages = {}
self.pkgCache = {}
self.currentCategory = None
self._categoryPackages = {}
self.categories = set()
self.unmaskingPackages = set()
self.selected_treeview_item = None
self.selected_advisory_item = None
self.queue = None
def connect_queue(self, queue):
self.queue = queue
def clearPackages(self):
self._packages.clear()
self.selected_treeview_item = None
self.selected_advisory_item = None
self._categoryPackages.clear()
self.unmaskingPackages.clear()
def clearPackagesSingle(self, mask):
if mask in self._packages:
del self._packages[mask]
self.selected_treeview_item = None
self.selected_advisory_item = None
self._categoryPackages.clear()
self.unmaskingPackages.clear()
def clearCache(self):
self.pkgCache.clear()
self.selected_treeview_item = None
self.selected_advisory_item = None
def populatePackages(self,masks):
for flt in masks: self.populateSingle(flt)
def populateSingle(self, mask, force = False):
if self._packages.has_key(mask) and not force: return
self._packages[mask] = self._getPackages(mask)
def setCategoryPackages(self,pkgdict = {}):
self._categoryPackages = pkgdict
def getPackagesByCategory(self,cat=None):
if not cat: cat = self.currentCategory
else: self.currentCategory = cat
if not self._categoryPackages.has_key(cat): self.populateCategory(cat)
return self._categoryPackages[cat]
def populateCategory(self, category):
self.getAllPackages()
catsdata = self.Entropy.list_repo_packages_in_category(category)
catsdata.extend([(x,0) for x in self.Entropy.list_installed_packages_in_category(category)])
pkgsdata = []
def mymf(pkgdata):
try:
yp, new = self.getPackageItem(pkgdata,True)
except RepositoryError:
return 0
return yp
self._categoryPackages[category] = [x for x in map(mymf,catsdata) if type(x) != int]
def populateCategories(self):
self.categories = self.Entropy.list_repo_categories()
def getPackages(self,flt):
if flt == 'all': return self.getAllPackages()
else: return self.doFiltering(self.getRawPackages(flt))
def getAllPackages(self):
pkgs = []
pkgs.extend(self.getPackages('installed'))
pkgs.extend(self.getPackages('available'))
pkgs.extend(self.getPackages('reinstallable'))
pkgs.extend(self.getPackages('updates'))
return pkgs
def setFilter(self,fn = None):
self.filterCallback = fn
def doFiltering(self,pkgs):
if self.filterCallback:
return filter(self.filterCallback,pkgs)
return pkgs
def getRawPackages(self,flt):
self.populateSingle(flt)
return self._packages[flt]
def getPackageItem(self, pkgdata, avail):
new = False
if self.pkgCache.has_key((pkgdata,avail)):
yp = self.pkgCache[(pkgdata,avail)]
else:
new = True
pkgset = None
if isinstance(pkgdata,basestring): # package set
pkgset = True
yp = EntropyPackage(pkgdata, avail, pkgset = pkgset)
self.pkgCache[(pkgdata,avail)] = yp
return yp, new
def _pkg_get_installed(self):
gp_call = self.getPackageItem
def fm(idpackage):
try:
yp, new = gp_call((idpackage,0),True)
except RepositoryError:
return 0
yp.action = 'r'
yp.color = SpritzConf.color_install
return yp
return [x for x in map(fm,self.Entropy.clientDbconn.listAllIdpackages(order_by = 'atom')) if type(x) != int]
def _pkg_get_queued(self):
for qkey in self.queue.packages:
for item in self.queue.packages[qkey]:
yield item
def _pkg_get_available(self):
gp_call = self.getPackageItem
# Get the rest of the available packages.
def fm(match):
try:
yp, new = gp_call(match,True)
except RepositoryError:
return 0
yp.action = 'i'
return yp
return [x for x in map(fm,self.Entropy.calculate_available_packages()) if type(x) != int]
def _pkg_get_updates(self):
# this is required to make all the package options
# to work correclty (for eg: remove)
self._pkg_get_installed()
self._pkg_get_reinstallable()
gp_call = self.getPackageItem
cdb_atomMatch = self.Entropy.clientDbconn.atomMatch
def fm(match):
try:
yp, new = gp_call(match,True)
except RepositoryError:
return 0
key, slot = yp.keyslot
installed_match = cdb_atomMatch(key, matchSlot = slot)
if installed_match[0] != -1: yp.installed_match = installed_match
yp.action = 'u'
yp.color = SpritzConf.color_update
return yp
updates, remove, fine = self.Entropy.calculate_world_updates()
return [x for x in map(fm,updates) if type(x) != int]
def _pkg_get_reinstallable(self):
def fm(match):
idpackage, matched = match
try:
yp, new = self.getPackageItem(matched,True)
except RepositoryError:
return 0
yp.installed_match = (idpackage,0)
yp.action = 'rr'
yp.color = SpritzConf.color_install
return yp
return [x for x in map(fm,self.filterReinstallable(self.Entropy.clientDbconn.listAllPackages(get_scope = True,order_by = 'atom'))) if type(x) != int]
def _pkg_get_masked(self):
gp_call = self.getPackageItem
gmp_action = self.getMaskedPackageAction
gi_match = self.getInstalledMatch
def fm(match):
match, idreason = match
try:
yp, new = gp_call(match,True)
except RepositoryError:
return 0
action = gmp_action(match)
yp.action = action
if action == 'rr': # setup reinstallables
idpackage = gi_match(match)
if idpackage == None: # wtf!?
yp.installed_match = None
else:
yp.installed_match = (idpackage,0)
yp.masked = idreason
yp.color = SpritzConf.color_install
return yp
return [x for x in map(fm,self.getMaskedPackages()) if type(x) != 0]
def _pkg_get_user_masked(self):
masked_objs = self.getPackages("masked")
return [x for x in masked_objs if x.user_masked]
def _pkg_get_user_unmasked(self):
objs = self.getPackages("updates") + self.getPackages("available") + self.getPackages('reinstallable')
return [x for x in objs if x.user_unmasked]
def _pkg_get_pkgset_matches_installed_matches(self, set_deps):
set_matches = []
set_installed_matches = []
install_incomplete = False
remove_incomplete = False
for set_dep in set_deps:
if set_dep.startswith(etpConst['packagesetprefix']):
set_matches.append((set_dep,None,))
set_installed_matches.append((set_dep,None,))
else:
set_match = self.Entropy.atom_match(set_dep)
if set_match[0] != -1: set_matches.append(set_match)
else: install_incomplete = True
set_installed_match = self.Entropy.clientDbconn.atomMatch(set_dep)
if set_match[0] != -1: set_installed_matches.append(set_installed_match)
else: remove_incomplete = True
return set_matches, set_installed_matches, install_incomplete, remove_incomplete
def _pkg_get_pkgset_set_from_desc(self, set_from):
my_set_from = _('Set from')
set_from_desc = _('Unknown')
if set_from in self.Entropy.validRepositories:
avail_repos = self.Entropy.SystemSettings['repositories']['available']
set_from_desc = avail_repos[set_from]['description']
elif set_from == etpConst['userpackagesetsid']:
set_from_desc = _("User configuration")
return "%s: %s" % (my_set_from,set_from_desc,)
def _pkg_get_pkgsets(self):
gp_call = self.getPackageItem
# make sure updates will be marked as such
self.getPackages("updates")
# make sure unavailable packages are marked as such
self.getPackages("available")
# make sure reinstallable packages will be marked as such
self.getPackages("reinstallable")
objects = []
pkgsets = self.getPackageSets()
for set_from, set_name, set_deps in pkgsets:
set_matches, set_installed_matches, install_incomplete, remove_incomplete = self._pkg_get_pkgset_matches_installed_matches(set_deps)
if not (set_matches and set_installed_matches): continue
cat_namedesc = self._pkg_get_pkgset_set_from_desc(set_from)
set_objects = []
def update_yp(yp):
yp.color = SpritzConf.color_install
yp.set_cat_namedesc = cat_namedesc
yp.set_names.add(set_name)
yp.set_from = set_from
yp.set_matches = set_matches
yp.set_installed_matches = set_installed_matches
myobjs = []
broken = False
for match in set_matches:
# set dependency
if match[1] == None:
yp, new = gp_call(match[0],True)
yp.action = "i"
else:
try:
yp, new = gp_call(match,True)
except RepositoryError:
broken = True
break
myobjs.append(yp)
if broken: continue
for yp in myobjs: yp.set_names.clear()
for yp in myobjs: update_yp(yp)
objects += myobjs
return objects
def _pkg_get_fake_updates(self):
# load a pixmap inside the treeview
msg2 = _("Try clicking the %s button in the %s page") % ( _("Update Repositories"),_("Repository Selection"),)
msg = "<big><b><span foreground='%s'>%s</span></b></big>\n%s.\n%s" % (
SpritzConf.color_title,
_('No updates available'),
_("It seems that your system is already up-to-date. Good!"),
msg2,
)
myobj = DummyEntropyPackage(namedesc = msg, dummy_type = SpritzConf.dummy_empty)
return [myobj]
def _getPackages(self,mask):
calls_dict = {
"installed": self._pkg_get_installed,
"queued": self._pkg_get_queued,
"available": self._pkg_get_available,
"updates": self._pkg_get_updates,
"reinstallable": self._pkg_get_reinstallable,
"masked": self._pkg_get_masked,
"user_masked": self._pkg_get_user_masked,
"user_unmasked": self._pkg_get_user_unmasked,
"pkgsets": self._pkg_get_pkgsets,
"fake_updates": self._pkg_get_fake_updates,
}
return calls_dict.get(mask)()
def isReinstallable(self, atom, slot, revision):
for repoid in self.Entropy.validRepositories:
dbconn = self.Entropy.open_repository(repoid)
idpackage, idreason = dbconn.isPackageScopeAvailable(atom, slot, revision)
if idpackage == -1:
continue
return (repoid,idpackage,)
return None
def getPackageSets(self):
return self.Entropy.package_set_list()
def getMaskedPackages(self):
maskdata = []
for repoid in self.Entropy.validRepositories:
dbconn = self.Entropy.open_repository(repoid)
repodata = dbconn.listAllIdpackages(order_by = 'atom')
def fm(idpackage):
idpackage_filtered, idreason = dbconn.idpackageValidator(idpackage)
if idpackage_filtered == -1:
return ((idpackage,repoid,),idreason)
return 0
maskdata += [x for x in map(fm,repodata) if type(x) != int]
return maskdata
def getMaskedPackageAction(self, match):
action = self.Entropy.get_package_action(match)
if action in [2,-1]:
return 'u'
elif action == 1:
return 'i'
else:
return 'rr'
def getInstalledMatch(self, match):
dbconn = self.Entropy.open_repository(match[1])
try:
atom, slot, revision = dbconn.getStrictScopeData(match[0])
except TypeError:
return None
idpackage, idresult = self.Entropy.clientDbconn.isPackageScopeAvailable(atom, slot, revision)
if idpackage == -1:
return None
return idpackage
def filterReinstallable(self, client_scope_data):
clientdata = {}
for idpackage, atom, slot, revision in client_scope_data:
clientdata[(atom,slot,revision,)] = idpackage
del client_scope_data
matched_data = set()
for repoid in self.Entropy.validRepositories:
dbconn = self.Entropy.open_repository(repoid)
repodata = dbconn.listAllPackages(get_scope = True)
mydata = {}
for idpackage, atom, slot, revision in repodata:
mydata[(atom, slot, revision)] = idpackage
def fm_pre(item):
if item in mydata:
return True
return False
def fm(item):
idpackage = mydata[item]
idpackage, idreason = dbconn.idpackageValidator(idpackage)
if idpackage != -1:
return (clientdata[item],(mydata[item],repoid,))
return 0
matched_data |= set([x for x in map(fm,filter(fm_pre,clientdata)) if type(x) != int])
return matched_data
def getCategories(self):
catlist = []
for cat in self.categories:
catlist.append(cat)
catlist.sort()
return catlist