-
Notifications
You must be signed in to change notification settings - Fork 0
/
ports.py.newjunk
368 lines (279 loc) · 9.59 KB
/
ports.py.newjunk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
#!/usr/bin/python2
# Copyright 2010 Daniel Robbins, Funtoo Technologies, LLC.
#
# FUNTOO TECHNOLOGIES INTERNAL SOURCE CODE
# ALPHA - DO NOT RELEASE - NOT FOR DISTRIBUTION
#
# The unauthorized reproduction or distribution of this copyrighted work is
# illegal, and may result in civil or criminal liability.
# NOTE: Keep the scope of this small so the import list can be minimized
# and easily managed:
import os
import portage.versions
from access import *
# This module implements a simplified mechanism to access the contents of a
# Portage tree. In addition, the PortageRepository class (see below) has
# an elegant design that should support alternate Portage repository layouts
# as well as alternate backend storage formats. An effort has been made to
# keep things simple and extendable.
class Category(object):
def __repr__(self):
return "Category(%s)" % self.atom
def __init__(self,atom,repository=None):
self.atom = atom
self._repository = repository
def __eq__(self,other):
return self.atom == other.atom
def __hash__(self):
return hash(self.atom)
@property
def repository(self):
return self._repository
@repository.setter
def repository(self,repository):
return Category(self.atom,repository=repository)
class CatPkg(object):
# CatPkg is an object that is used to specify a particular group of
# ebuilds that is identified by a category and package name, such
# as "sys-apps/portage".
@property
def cat(self):
#i.e. "sys-apps"
return self.atom.split("/")[0]
@property
def pkg(self):
#i.e. "portage"
return self.atom.split("/")[1]
@property
def p(self):
#i.e. "portage"
return self.pkg
def __repr__(self):
return "CatPkg(%s)" % self.atom
def __init__(self,atom,repository=None):
self.atom = atom
self.repository = repository
def __eq__(self, other):
return self.atom == other.atom
def __hash__(self):
return hash(self.atom)
def __getitem__(self,key):
# This method allows properties to be grabbed using atom["cat"]
# as well as standard atom.cat. This comes in handy when expanding
# strings:
#
# path = "%(cat)s/%(p)s" % atom
if hasattr(self,key):
return getattr(self,key)
class PkgAtom(object):
# Our PkgAtom is different from a dependency, and literally means "a
# specific reference to an individual package". This package could be a
# specific ebuild in a Portage tree, or a specific record in
# /var/db/pkg indicating that the package is installed. An "PkgAtom"
# uniquely references one package without ambiguity.
# LOGICAL TEST OF AN ATOM: Two identical atoms cannot co-exist in a
# single repository.
# LOGICAL TEST OF WHAT IS CONSIDERED ATOM DATA: Any data that can be
# used to specify a uniquely-existing package in a repository, that is
# capable of co-existing with other similar atoms, should be considered
# atom data. Otherwise, the data should not be considered atom data.
# Example: slots *are* part of an PkgAtom for repositories of installed or
# built packages, because foo/bar-1.0:slot=3 and foo/bar-1.0:slot=4 can
# co-exist in these repositories.
# So note that a package *slot* is considered part of the PkgAtom for
# packages that have already been installed or built. However, slot is
# *not* part of the PkgAtom for packages in a Portage tree, as the slot
# can be undefined at this point. For installed packages, the slot can
# be specified as follows:
# sys-apps/portage-2.2_rc67:slot=3
# However, USE variables are not considered PkgAtom data for any type of
# repository because "foo/bar-1.0[gleep]" and "foo/bar-1.0[boing]"
# cannot co-exist independently in a Portage tree *or* installed
# package repository.
# The PkgAtom object provides a standard class for describing a package
# atom, in the abstract. Helper methods/properties are provided to
# access the atom's various attributes, such as package name, category,
# package version, revision, etc. The package atom is not tied to a
# particular Portage repository, and does not have an on-disk path. If
# you want an on-disk path for an PkgAtom, you'd create a new PkgAtom and
# pass it to the PortageRepository object and it will tell you.
# As touched on above, there is a text representation of an PkgAtom that
# is standardized, which is:
# <cat>/<p>{:key1=val1{:key2=val2...}}
# <cat> = category name
# <p> = full package name and version (including optional revision)
# :key=val = optional additional data in key=value format. values can
# consist of any printable character except a colon. Additional key
# values can be specified by appending another colon to the line,
# such as:
# sys-foo/bar-1.0:slot=1:python=2.6:keywords=foo,bar,oni
# (Although you wouldn't want to specify keywords in an PkgAtom as it
# wouldn't pass the LOGICAL TESTS above.)
def __hash__(self):
return hash(self.atom)
def __repr__(self):
return "PkgAtom(%s)" % self.atom
def __init__(self,atom,repository=None):
self.atom = atom
self.repository = repository
self._keysplit = None
self._keys = None
self._cpvs = None
def __getitem__(self,key):
# This method allows properties to be grabbed using atom["cat"]
# as well as standard atom.cat. This comes in handy when expanding
# strings:
#
# path = "%(cat)s/%(p)s" % atom
if hasattr(self,key):
return getattr(self,key)
@property
def keys(self):
# Additional atomdata key/value pairs in dictionary format. These
# are created on initialization and you should not modify the
# keys property directly.
if self._keys == None:
self._keys = {}
for meta in self._keysplit[1:]:
key, val = meta.split("=",1)
self._keys[key] = val
return self._keys
@property
def cpvs(self):
# cpvs = "catpkgsplit string" and is used by other properties
if self._cpvs == None:
self._keysplit = self.atom.split(":")
self._cpvs = portage.versions.catpkgsplit(self._keysplit[0])
return self._cpvs
@property
def cat(self):
#i.e. "sys-apps"
return self.atom.split("/")[0]
@property
def pf(self):
#i.e. "portage-2.2_rc67-r1"
return self.atom.split("/")[1]
@property
def p(self):
#i.e. "portage"
return self.cpvs[1]
@property
def pv(self):
#i.e. "2.2_rc67"
return self.cpvs[2]
@property
def pr(self):
#i.e. "r1"
return self.cpvs[3]
def __eq__(self,other):
# We can only test for atom equality, but cannot otherwise compare them.
# PkgAtoms are equal when they reference the same unique cat/pkg and have
# the same key data.
return self.cpvs == other.cpvs and self.keys == other.keys
class EClassAtom(str):
pass
class Adapter(object):
def __init__(self,**args):
for arg in args.keys():
setattr(self,arg,args[arg])
"""
class AggregateCollection(Collection):
def __init__(self,children):
self.childen = children
def list(self):
atoms = set()
for child in self.children:
atoms = atoms | child.list()
return atoms
def has(self,key):
for child in self.children:
ref = child.has(key)
if ref:
return ref
return None
class PkgAtomAdapter(object):
def __init__(self,path):
self.path = path
def get(self,atomstr):
atom = PkgAtom(atomstr,repository=self.path.repository)
path = self.path.adjpath("%s/%s/%s.ebuild" % ( atom.cat, atom.p, atom.pf ))
if path.exists():
return atom
def list(self,atomstr):
cp = CatPkg(atomstr,repository=self.path.repository)
print cp
path = self.path.adjpath("%s/%s" % ( cp.cat, cp.pkg ))
print path
if path.isdir():
out = set()
for file in path.listdir():
out.add(PkgAtom("")
return path.generate(CatPkg)
return set()
"""
class CatPkgAdapter(object):
def __init__(self,path,repository):
self.path = path
self.repository = repository
def match(self,key):
if key[-7:] == ".ebuild:"
return key[0
def exists(self,atom):
return self.path.adjpath("%s/%s" % ( atom.cat, atom.pkg )).isdir()
def list(self,atom):
return self.path.adjpath("%s" % ( atom.cat )).generate(PkgAtom,repository=self.repository,func = self.match)
class CategoryAdapter(object):
def __init__(self,path,repository):
self.path = path
self.repository = repository
def exists(self,atom):
return self.path.adjpath("%s" % ( atom.cat, atom.pkg )).isdir()
def list(self):
return self.path.generate(Category,repository=self.repository)
class ValidAdapter(object):
def __init__(self,child,vfunc):
self.child = child
self.vfunc = vfunc
self._valid = None
@property
def valid(self):
if self._valid == None:
self._valid = vfunc()
return self._valid
def exists(self,atom):
got = self.child.exists(atom)
if got and got in self.valid:
return got
def list(self):
return self.child.list() & self.valid
class PortageRepository(object):
def __init__(self,path):
self.path = FilePath("",base_path=path)
self.objects = {}
self.objects[Category] = CategoryAdapter(self.path,self)
self.objects[Category] = ValidAdapter(self.objects[Category], lambda: set(self.path.adjpath("profiles/categories").grabfile()))
self.objects[CatPkg] = CatPkgAdapter(self.path,self)
def exists(self,cls,atom):
return self.objects[cls].exists(atom)
def list(self,cls,atom=None):
return self.objects[cls].list(atom)
if __name__ == "__main__":
a = PkgAtom("sys-apps/portage-2.2_rc67-r2")
b = PkgAtom("sys-apps/portage-2.2_rc67-r3")
print a
print repr(a)
print type(a)
print b
print type(b)
c=[a,b]
print c
for x in c:
print x
print
print a,"==",b,":", a == b
c = PkgAtom("sys-apps/portage-2.2_rc67-r2:slot=3:python=2")
d = PkgAtom("sys-apps/portage-2.2_rc67-r2:python=2:slot=3")
print c,"==",d,":", c == d
a = PortageRepository("/var/git/portage-mini-2010")
#print a.exists(PkgAtom,PkgAtom("sys-apps/portage-2.2_rc67-r2"))
print a.list(CatPkg,CatPkg("sys-apps/portage"))