3 # Copyright(c) 2004, Karl Trygve Kalleberg <karltk@gentoo.org>
4 # Copyright(c) 2004, Gentoo Foundation
6 # Licensed under the GNU General Public License, v2
11 from errors import FatalError
13 from gentoolkit import *
16 """Package descriptor. Contains convenience functions for querying the
17 state of a package, its contents, name manipulation, ebuild info and
20 def __init__(self,cpv):
22 self._scpv = portage.catpkgsplit(self._cpv)
25 raise FatalError("invalid cpv: %s" % cpv)
27 self._settings = settings
28 self._settingslock = settingslock
29 self._portdir_path = settings["PORTDIR"]
30 if os.path.islink(self._portdir_path):
31 self._portdir_path = os.path.join(os.path.dirname(self._portdir_path), os.readlink(self._portdir_path))
34 """Returns base name of package, no category nor version"""
37 def get_version(self):
38 """Returns version of package, with revision number"""
40 if self._scpv[3] != "r0":
41 v += "-" + self._scpv[3]
44 def get_category(self):
45 """Returns category of package"""
48 def get_settings(self, key):
49 """Returns the value of the given key for this package (useful
50 for package.* files."""
51 self._settingslock.acquire()
52 self._settings.setcpv(self._cpv)
53 v = self._settings[key]
54 self._settingslock.release()
58 """Returns full Category/Package-Version string"""
61 def get_provide(self):
62 """Return a list of provides, if any"""
63 if not self.is_installed():
65 x = [self.get_env_var('PROVIDE')]
70 return vartree.get_provide(self._cpv)
72 def get_dependants(self):
73 """Retrieves a list of CPVs for all packages depending on this one"""
74 raise NotImplementedError("Not implemented yet!")
76 def get_runtime_deps(self):
77 """Returns a linearised list of first-level run time dependencies for this package, on
78 the form [(comparator, [use flags], cpv), ...]"""
79 # Try to use the portage tree first, since emerge only uses the tree when calculating dependencies
81 cd = self.get_env_var("RDEPEND", porttree).split()
83 cd = self.get_env_var("RDEPEND", vartree).split()
84 r,i = self._parse_deps(cd)
87 def get_compiletime_deps(self):
88 """Returns a linearised list of first-level compile time dependencies for this package, on
89 the form [(comparator, [use flags], cpv), ...]"""
90 # Try to use the portage tree first, since emerge only uses the tree when calculating dependencies
92 rd = self.get_env_var("DEPEND", porttree).split()
94 rd = self.get_env_var("DEPEND", vartree).split()
95 r,i = self._parse_deps(rd)
98 def get_postmerge_deps(self):
99 """Returns a linearised list of first-level post merge dependencies for this package, on
100 the form [(comparator, [use flags], cpv), ...]"""
101 # Try to use the portage tree first, since emerge only uses the tree when calculating dependencies
103 pd = self.get_env_var("PDEPEND", porttree).split()
105 pd = self.get_env_var("PDEPEND", vartree).split()
106 r,i = self._parse_deps(pd)
109 def _parse_deps(self,deps,curuse=[],level=0):
110 # store (comparator, [use predicates], cpv)
112 comparators = ["~","<",">","=","<=",">="]
120 tok = tok.replace("?","")
121 sr,l = self._parse_deps(deps[i+2:],curuse=curuse+[tok],level=level+1)
126 sr,l = self._parse_deps(deps[i+2:],curuse,level=level+1)
130 # conjonction, like in "|| ( ( foo bar ) baz )" => recurse
132 sr,l = self._parse_deps(deps[i+1:],curuse,level=level+1)
136 # pkg block "!foo/bar" => ignore it
140 # pick out comparator, if any
142 for c in comparators:
146 r.append((cmp,curuse,tok))
150 def is_installed(self):
151 """Returns true if this package is installed (merged)"""
153 return os.path.exists(self._db.getpath())
155 def is_overlay(self):
156 """Returns true if the package is in an overlay."""
157 dir,ovl = portage.portdb.findname2(self._cpv)
158 return ovl != self._portdir_path
161 """Returns true if this package is masked against installation. Note: We blindly assume that
162 the package actually exists on disk somewhere."""
163 unmasked = portage.portdb.xmatch("match-visible", "=" + self._cpv)
164 return self._cpv not in unmasked
166 def get_ebuild_path(self,in_vartree=0):
167 """Returns the complete path to the .ebuild file"""
169 return vartree.getebuildpath(self._cpv)
171 return portage.portdb.findname(self._cpv)
173 def get_package_path(self):
174 """Returns the path to where the ChangeLog, Manifest, .ebuild files reside"""
175 p = self.get_ebuild_path()
178 return "/".join(sp[:-1])
180 def get_env_var(self, var, tree=""):
181 """Returns one of the predefined env vars DEPEND, RDEPEND, SRC_URI,...."""
184 if not self.is_installed():
188 r = mytree.dbapi.aux_get(self._cpv,[var])
190 raise FatalError("Could not find the package tree")
192 raise FatalError("Should only get one element!")
195 def get_use_flags(self):
196 """Returns the USE flags active at time of installation"""
198 if self.is_installed():
199 return self._db.getfile("USE")
202 def get_contents(self):
203 """Returns the full contents, as a dictionary, on the form
204 [ '/bin/foo' : [ 'obj', '1052505381', '45ca8b8975d5094cd75bdc61e9933691' ], ... ]"""
206 if self.is_installed():
207 return self._db.getcontents()
210 def compare_version(self,other):
211 """Compares this package's version to another's CPV; returns -1, 0, 1"""
213 v2 = portage.catpkgsplit(other.get_cpv())
214 # if category is different
216 return cmp(v1[0],v2[0])
217 # if name is different
219 return cmp(v1[1],v2[1])
222 return portage.pkgcmp(v1[1:],v2[1:])
225 """Estimates the installed size of the contents of this package, if possible.
226 Returns [size, number of files in total, number of uncounted files]"""
227 contents = self.get_contents()
233 size += os.lstat(x).st_size
237 return [size, files, uncounted]
240 """Internal helper function; loads package information from disk,
243 cat = self.get_category()
244 pnv = self.get_name()+"-"+self.get_version()
245 self._db = portage.dblink(cat,pnv,settings["ROOT"],settings)