summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/Changelog4
-rw-r--r--doc/TODO1
-rw-r--r--portato/backend/__init__.py22
-rw-r--r--portato/backend/package.py114
-rw-r--r--portato/backend/portage_helper.py131
5 files changed, 228 insertions, 44 deletions
diff --git a/doc/Changelog b/doc/Changelog
index 303c2bb..0b5d2e1 100644
--- a/doc/Changelog
+++ b/doc/Changelog
@@ -1,3 +1,7 @@
+0.5.2:
+- removed gentoolkit-dependency
+- added support for portage-2.1.2
+
0.5.1:
- new config parser and new config-layout
- added sync-command option
diff --git a/doc/TODO b/doc/TODO
index ddd97cf..59e6184 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -2,6 +2,7 @@ Backend:
========
- bugs in update world
+- make it correctly work with portage-2.1.2
GUI:
=====
diff --git a/portato/backend/__init__.py b/portato/backend/__init__.py
index ef6811f..ce244c5 100644
--- a/portato/backend/__init__.py
+++ b/portato/backend/__init__.py
@@ -10,24 +10,24 @@
#
# Written by René 'Necoro' Neumann <necoro@necoro.net>
-import sys
+import sys, copy
+from threading import Lock
-# insert the gentoolkit-location into syspath
-sys.path.insert(0, "/usr/lib/gentoolkit/pym")
-
-# import gentoolkit and portage
-import gentoolkit
+# import portage
import portage
+# portage tree vars
+settingslock = Lock()
+settings = portage.config(clone=portage.settings, config_incrementals = copy.deepcopy(portage.settings.incrementals))
+porttree = portage.db[portage.root]["porttree"]
+vartree = portage.db[portage.root]["vartree"]
+virtuals = portage.db[portage.root]["virtuals"]
+trees = portage.db
+
# this is set to "var/lib/portage/world" by default - so we add the leading /
portage.WORLD_FILE = portage.settings["ROOT"]+portage.WORLD_FILE
portage.settings = None # we use our own one ...
-# portage tree vars
-porttree = gentoolkit.porttree
-vartree = gentoolkit.vartree
-trees = portage.db
-
# import our packages
from exceptions import *
from package import *
diff --git a/portato/backend/package.py b/portato/backend/package.py
index 82e0b22..6e32776 100644
--- a/portato/backend/package.py
+++ b/portato/backend/package.py
@@ -15,12 +15,12 @@ from portato.helper import *
from portage_helper import *
import flags
-import portage, portage_dep, gentoolkit
+import portage, portage_dep
from portage_util import unique_array
import types
-class Package (gentoolkit.Package):
+class Package:
"""This is a subclass of the gentoolkit.Package-class which a lot of additional functionality we need in Portato."""
def __init__ (self, cpv):
@@ -29,14 +29,30 @@ class Package (gentoolkit.Package):
@param cpv: The cpv or gentoolkit.Package which describes the package to create.
@type cpv: string (cat/pkg-ver) or gentoolkit.Package-object."""
- if isinstance(cpv, gentoolkit.Package):
- cpv = cpv.get_cpv()
- gentoolkit.Package.__init__(self, cpv)
+ self._cpv = cpv
+ self._scpv = portage.catpkgsplit(self._cpv)
+
+ if not self._scpv:
+ raise FatalError("invalid cpv: %s" % cpv)
+ self._db = None
+ self._settings = settings
+ self._settingslock = settingslock
+
try:
- self._status = portage.getmaskingstatus(self.get_cpv(), settings = gentoolkit.settings)
+ self._status = portage.getmaskingstatus(self.get_cpv(), settings = settings)
except KeyError: # package is not located in the system
self._status = None
+ def is_installed(self):
+ """Returns true if this package is installed (merged)"""
+ self._initdb()
+ return os.path.exists(self._db.getpath())
+
+ def is_overlay(self):
+ """Returns true if the package is in an overlay."""
+ dir,ovl = portage.portdb.findname2(self._cpv)
+ return ovl != settings["PORTDIR"]
+
def is_in_system (self):
"""Returns False if the package could not be found in the portage system.
@@ -302,6 +318,10 @@ class Package (gentoolkit.Package):
return dep_pkgs
+ def get_cpv(self):
+ """Returns full Category/Package-Version string"""
+ return self._cpv
+
def get_cp (self):
"""Returns the cp-string.
@@ -310,6 +330,88 @@ class Package (gentoolkit.Package):
return self.get_category()+"/"+self.get_name()
+ def get_name(self):
+ """Returns base name of package, no category nor version"""
+ return self._scpv[1]
+
+ def get_version(self):
+ """Returns version of package, with revision number"""
+ v = self._scpv[2]
+ if self._scpv[3] != "r0":
+ v += "-" + self._scpv[3]
+ return v
+
+ def get_category(self):
+ """Returns category of package"""
+ return self._scpv[0]
+
+ def get_settings(self, key):
+ """Returns the value of the given key for this package (useful
+ for package.* files."""
+ self._settingslock.acquire()
+ self._settings.setcpv(self._cpv)
+ v = self._settings[key]
+ self._settingslock.release()
+ return v
+
+ def get_ebuild_path(self,in_vartree=0):
+ """Returns the complete path to the .ebuild file"""
+ if in_vartree:
+ return vartree.getebuildpath(self._cpv)
+ else:
+ return portage.portdb.findname(self._cpv)
+
+ def get_package_path(self):
+ """Returns the path to where the ChangeLog, Manifest, .ebuild files reside"""
+ p = self.get_ebuild_path()
+ sp = p.split("/")
+ if len(sp):
+ return string.join(sp[:-1],"/")
+
+ def get_env_var(self, var, tree=""):
+ """Returns one of the predefined env vars DEPEND, RDEPEND, SRC_URI,...."""
+ if tree == "":
+ mytree = vartree
+ if not self.is_installed():
+ mytree = porttree
+ else:
+ mytree = tree
+ r = mytree.dbapi.aux_get(self._cpv,[var])
+ if not r:
+ raise FatalError("Could not find the package tree")
+ if len(r) != 1:
+ raise FatalError("Should only get one element!")
+ return r[0]
+
+ def get_use_flags(self):
+ """Returns the USE flags active at time of installation"""
+ self._initdb()
+ if self.is_installed():
+ return self._db.getfile("USE")
+ return ""
+
+ def compare_version(self,other):
+ """Compares this package's version to another's CPV; returns -1, 0, 1"""
+ v1 = self._scpv
+ v2 = portage.catpkgsplit(other.get_cpv())
+ # if category is different
+ if v1[0] != v2[0]:
+ return cmp(v1[0],v2[0])
+ # if name is different
+ elif v1[1] != v2[1]:
+ return cmp(v1[1],v2[1])
+ # Compaare versions
+ else:
+ return portage.pkgcmp(v1[1:],v2[1:])
+
+ def _initdb(self):
+ """Internal helper function; loads package information from disk,
+ when necessary"""
+ if not self._db:
+ cat = self.get_category()
+ pnv = self.get_name()+"-"+self.get_version()
+ self._db = portage.dblink(cat,pnv,settings["ROOT"],settings)
+
def matches (self, criterion):
"""This checks, whether this package matches a specific verisioning criterion - e.g.: "<=net-im/foobar-1.2".
diff --git a/portato/backend/portage_helper.py b/portato/backend/portage_helper.py
index 6e8fc84..1726323 100644
--- a/portato/backend/portage_helper.py
+++ b/portato/backend/portage_helper.py
@@ -12,7 +12,7 @@
import re, os, copy
-import portage, gentoolkit
+import portage
from portage_util import unique_array
from portato.backend import *
@@ -76,7 +76,30 @@ def find_packages (search_key, masked=False):
@returns: list of found packages
@rtype: backend.Package[]"""
- return geneticize_list(gentoolkit.find_packages(search_key, masked))
+ try:
+ if masked:
+ t = portage.db["/"]["porttree"].dbapi.xmatch("match-all", search_key)
+ t += portage.db["/"]["vartree"].dbapi.match(search_key)
+ else:
+ t = portage.db["/"]["porttree"].dbapi.match(search_key)
+ t += portage.db["/"]["vartree"].dbapi.match(search_key)
+ # catch the "amgigous package" Exception
+ except ValueError, e:
+ if type(e[0]) == types.ListType:
+ t = []
+ for cp in e[0]:
+ if masked:
+ t += portage.db["/"]["porttree"].dbapi.xmatch("match-all", cp)
+ t += portage.db["/"]["vartree"].dbapi.match(cp)
+ else:
+ t += portage.db["/"]["porttree"].dbapi.match(cp)
+ t += portage.db["/"]["vartree"].dbapi.match(cp)
+ else:
+ raise ValueError(e)
+ # Make the list of packages unique
+ t = unique_array(t)
+ t.sort()
+ return geneticize_list(t)
def find_installed_packages (search_key, masked=False):
"""This returns a list of packages which have to fit exactly. Additionally ranges like '<,>,=,~,!' et. al. are possible.
@@ -89,7 +112,18 @@ def find_installed_packages (search_key, masked=False):
@returns: list of found packages
@rtype: backend.Package[]"""
- return geneticize_list(gentoolkit.find_installed_packages(search_key, masked))
+ try:
+ t = portage.db["/"]["vartree"].dbapi.match(search_key)
+ # catch the "amgigous package" Exception
+ except ValueError, e:
+ if type(e[0]) == types.ListType:
+ t = []
+ for cp in e[0]:
+ t += portage.db["/"]["vartree"].dbapi.match(cp)
+ else:
+ raise ValueError(e)
+
+ return geneticize_list(t)
def find_system_packages ():
"""Looks for all packages saved as "system-packages".
@@ -97,8 +131,18 @@ def find_system_packages ():
@returns: a tuple of (resolved_packages, unresolved_packages).
@rtype: (backend.Package[], backend.Package[])"""
- list = gentoolkit.find_system_packages()
- return (geneticize_list(list[0]), geneticize_list(list[1]))
+ pkglist = settings.packages
+ resolved = []
+ unresolved = []
+ for x in pkglist:
+ cpv = x.strip()
+ if len(cpv) and cpv[0] == "*":
+ pkg = find_best_match(cpv)
+ if pkg:
+ resolved.append(pkg)
+ else:
+ unresolved.append(cpv)
+ return (geneticize_list(resolved), geneticize_list(unresolved))
def find_world_packages ():
"""Looks for all packages saved in the world-file.
@@ -106,8 +150,19 @@ def find_world_packages ():
@returns: a tuple of (resolved_packages, unresolved_packages).
@rtype: (backend.Package[], backend.Package[])"""
- list = gentoolkit.find_world_packages()
- return geneticize_list(list[0]),geneticize_list(list[1])
+ f = open(portage.WORLD_FILE)
+ pkglist = f.readlines()
+ resolved = []
+ unresolved = []
+ for x in pkglist:
+ cpv = x.strip()
+ if len(cpv) and cpv[0] != "#":
+ pkg = find_best_match(cpv)
+ if pkg:
+ resolved.append(pkg)
+ else:
+ unresolved.append(cpv)
+ return (geneticize_list(resolved), geneticize_list(unresolved))
def find_all_installed_packages (name=None, withVersion=True):
"""Finds all installed packages matching a name or all if no name is specified.
@@ -121,7 +176,11 @@ def find_all_installed_packages (name=None, withVersion=True):
@rtype: backend.Package[] or cp-string[]"""
if withVersion:
- return geneticize_list(gentoolkit.find_all_installed_packages(find_lambda(name)))
+ t = vartree.dbapi.cpv_all()
+ if name:
+ t = filter(find_lambda(name),t)
+ return geneticize_list(t)
+
else:
t = vartree.dbapi.cp_all()
if name:
@@ -136,7 +195,8 @@ def find_all_uninstalled_packages (name=None):
@returns: all packages found
@rtype: backend.Package[]"""
- return geneticize_list(gentoolkit.find_all_uninstalled_packages(find_lambda(name)))
+ alist = find_all_packages(name)
+ return geneticize_list([x for x in alist if not x.is_installed()])
def find_all_packages (name=None, withVersion=True):
"""Finds all packages matching a name or all if no name is specified.
@@ -149,15 +209,21 @@ def find_all_packages (name=None, withVersion=True):
@returns: all packages/cp-strings found
@rtype: backend.Package[] or cp-string[]"""
+ t = porttree.dbapi.cp_all()
+ t += vartree.dbapi.cp_all()
+ if name:
+ t = filter(find_lambda(name),t)
+ t = unique_array(t)
+
if (withVersion):
- return geneticize_list(gentoolkit.find_all_packages(find_lambda(name)))
+ t2 = []
+ for x in t:
+ t2 += porttree.dbapi.cp_list(x)
+ t2 += vartree.dbapi.cp_list(x)
+ t2 = unique_array(t2)
+ return geneticize_list(t2)
else:
- t = porttree.dbapi.cp_all()
- t += vartree.dbapi.cp_all()
- t = unique_array(t)
- if name:
- t = filter(find_lambda(name),t)
- return t
+ return t;
def find_all_world_packages (name=None):
"""Finds all world packages matching a name or all if no name is specified.
@@ -214,7 +280,7 @@ def list_categories (name=None):
@returns: all categories found
@rtype: string[]"""
- categories = gentoolkit.settings.categories
+ categories = settings.categories
return filter(find_lambda(name), categories)
def split_package_name (name):
@@ -224,20 +290,31 @@ def split_package_name (name):
@type name: string
@returns: list: [category, name, version, rev] whereby rev is "r0" if not specified in the name
@rtype: string[]"""
-
- return gentoolkit.split_package_name(name)
+
+ r = portage.catpkgsplit(name)
+ if not r:
+ r = name.split("/")
+ if len(r) == 1:
+ return ["", name, "", "r0"]
+ else:
+ return r + ["", "r0"]
+ if r[0] == 'null':
+ r[0] = ''
+ return r
def sort_package_list(pkglist):
"""Sorts a package list in the same manner portage does.
@param pkglist: list to sort
@type pkglist: Packages[]"""
-
- return gentoolkit.sort_package_list(pkglist)
+
+ pkglist.sort(package.Package.compare_version)
+ return pkglist
def reload_settings ():
"""Reloads portage."""
- gentoolkit.settings = portage.config(config_incrementals = copy.deepcopy(gentoolkit.settings.incrementals))
+ global settings
+ settings = portage.config(config_incrementals = copy.deepcopy(settings.incrementals))
def update_world (newuse = False, deep = False):
"""Calculates the packages to get updated in an update world.
@@ -259,7 +336,7 @@ def update_world (newuse = False, deep = False):
packages.append(line)
world.close()
- sys = gentoolkit.settings.packages
+ sys = settings.packages
for x in sys:
if x[0] == "*":
x = x[1:]
@@ -268,9 +345,9 @@ def update_world (newuse = False, deep = False):
# Remove everything that is package.provided from our list
# This is copied from emerge.getlist()
for atom in packages[:]:
- for expanded_atom in portage.flatten(portage.dep_virtual([atom], gentoolkit.settings)):
+ for expanded_atom in portage.flatten(portage.dep_virtual([atom], settings)):
mykey = portage.dep_getkey(expanded_atom)
- if mykey in gentoolkit.settings.pprovideddict and portage.match_from_list(expanded_atom, settings.pprovideddict[mykey]):
+ if mykey in settings.pprovideddict and portage.match_from_list(expanded_atom, settings.pprovideddict[mykey]):
packages.remove(atom)
break
@@ -342,7 +419,7 @@ def get_use_desc (flag, package = None):
# fill cache if needed
if use_descs == {} or local_use_descs == {}:
# read use.desc
- fd = open(gentoolkit.settings["PORTDIR"]+"/profiles/use.desc")
+ fd = open(settings["PORTDIR"]+"/profiles/use.desc")
for line in fd.readlines():
line = line.strip()
if line != "" and line[0] != '#':
@@ -351,7 +428,7 @@ def get_use_desc (flag, package = None):
use_descs[fields[0]] = fields[1]
# read use.local.desc
- fd = open(gentoolkit.settings["PORTDIR"]+"/profiles/use.local.desc")
+ fd = open(settings["PORTDIR"]+"/profiles/use.local.desc")
for line in fd.readlines():
line = line.strip()
if line != "" and line[0] != '#':