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
|
#!/usr/bin/env python2
# vim: set sts=4 sw=4 et :
#
# Author(s): Nirbheek Chauhan
# License: MIT
#
# A small script which sorts the revdeps of a given library according to
# which slot of the given library they depend on. Uses the tinderbox rindex for
# speed, because of which results may be out of date.
#
# Currently prints out a list of revdeps which *don't* use a slot in the
# dependency atom containing the given library
#
import sys
import os
import os.path as osp
import portage
from portage.xml.metadata import MetaDataXML
portdb = portage.portdb
portdb.porttrees = [portage.settings['PORTDIR']]
PORTDIR = portage.settings['PORTDIR']
DEPVARS = ['RDEPEND', 'PDEPEND', 'DEPEND']
#####################
### Configuration ###
#####################
if len(sys.argv) < 2:
print "Usage: %s <cat/pkg>" % sys.argv[0]
sys.exit(1)
KEY = sys.argv[1]
PORTAGE_ONLY = False
IGNORE_OBSOLETE = False
if os.environ.has_key('PORTAGE_ONLY'):
PORTAGE_ONLY = os.environ['PORTAGE_ONLY']
if os.environ.has_key('IGNORE_OBSOLETE'):
IGNORE_OBSOLETE = os.environ['IGNORE_OBSOLETE']
########################
### Output Functions ###
########################
def get_herds():
return osp.join(PORTDIR, 'metadata', 'herds.xml')
def get_md_path(cpv):
"""
x11-libs/gtk+-2.22.0-r1 -> <portdir>/x11-libs/gtk+/metadata.xml
"""
path = osp.join(*portage.catpkgsplit(cpv)[0:2])
return osp.join(PORTDIR, path, 'metadata.xml')
def rdeps_with_slot(slot_rdeps, slot=None):
"""
Prints a list of rev-deps which depend on the specified package and slot
"""
pkg_maints = {}
pkg_herds = {}
if not slot_rdeps.has_key(slot):
# No rdeps using the given slot
return
print "-------------------------------"
print "All packages:"
print "-------------------------------"
for pkg in slot_rdeps[slot]:
pkg_md = MetaDataXML(get_md_path(pkg), get_herds())
for herd in pkg_md.herds():
if not pkg_herds.has_key(herd):
pkg_herds[herd] = []
pkg_herds[herd].append(pkg)
for maint in pkg_md.maintainers():
if not pkg_maints.has_key(maint.email):
pkg_maints[maint.email] = []
pkg_maints[maint.email].append(pkg)
print '\t%s\therds: ' % pkg,
for i in pkg_md.herds():
print '%s' % i,
print '\tmaintainers: ',
for i in pkg_md.maintainers():
print '%s' % i.email,
print
print "-------------------------------"
print "Herd packages:"
print "-------------------------------"
for (herd, pkgs) in pkg_herds.iteritems():
print 'Herd: %s' % herd
for pkg in pkgs:
print '\t%s' % pkg
print "-------------------------------"
print "Maintainer packages:"
print "-------------------------------"
for (maint, pkgs) in pkg_maints.iteritems():
print 'Maintainer: %s' % maint
for pkg in pkgs:
print '\t%s' % pkg
#############################
### Portage API Functions ###
#############################
def get_deps_both(cpv, depvars=DEPVARS):
"""
Parses the dependency variables listed in depvars for cpv
returns (set(dep_cps), set(dep_strs))
"""
dep_cps = set()
dep_strs = set()
raw_deps = []
try:
raw_deps = portdb.aux_get(cpv, depvars)[0].split()
except KeyError:
return (dep_cps, dep_strs)
for dep in portage.dep.use_reduce(' '.join(raw_deps),
matchall=True, flat=True):
# Ignore blockers, etc
if portage.isvalidatom(dep):
dep_strs.add(dep)
dep_cps.add(portage.dep.dep_getkey(dep))
return (dep_cps, dep_strs)
def get_dep_slot(dep):
"""
If the dep atom contains a slot, return that
If the dep atom doesn't contain a slot, but is of the =cat/pkg-ver* type,
check which slots each satisfied cpv has, and return that if they're all the
same; return None if they're different
"""
# FIXME: Use our own portdb so that we match atoms outside of PORTDIR too
slot = portage.dep.dep_getslot(dep)
if slot or not dep.startswith('='):
return slot
cp = portage.dep.dep_getkey(dep)
cpvrs = portage.dep.match_from_list(dep, portdb.xmatch('match-all', cp))
for cpvr in cpvrs:
my_slot = portdb.aux_get(cpvr, ['SLOT'])[0]
if slot and my_slot != slot:
# omg, one of the slots is different
return None
slot = my_slot
return slot
def get_revdeps_rindex(key):
"""
Given a key, returns a reverse-dependency list of that key using the tinderbox rindex
list will be a sorted list of unique cpvs
"""
import urllib2
RINDEX = "http://tinderbox.dev.gentoo.org/misc/rindex"
revdeps = set()
rdeps_raw = urllib2.urlopen('/'.join([RINDEX, key])).read().split()
for i in rdeps_raw:
cpv = i.split(':')[0]
if portage.isvalidatom('='+cpv):
revdeps.add(cpv)
revdeps = list(revdeps)
revdeps.sort()
return revdeps
def get_revdeps_portage(key):
"""
Given a key, returns a reverse-dependency list of that key using portage API
list will be a sorted list of unique cpvs
"""
revdeps = set()
for cp in portdb.cp_all():
cpvrs = portdb.xmatch('match-all', cp)
for cpvr in cpvrs:
if key in get_deps_both(cpvr)[0]:
revdeps.add(cpvr)
revdeps = list(revdeps)
revdeps.sort()
return revdeps
###################
### Actual Work ###
###################
slot_rdeps = {}
revdeps = []
if PORTAGE_ONLY:
revdeps = get_revdeps_portage(KEY)
else:
revdeps = get_revdeps_rindex(KEY)
for rdep in revdeps:
if IGNORE_OBSOLETE:
from obsolete_ebuilds import get_obsolete
if rdep in get_obsolete(portage.pkgsplit(rdep)[0]):
continue
(cps, deps) = get_deps_both(rdep)
if KEY not in cps:
continue
for dep in deps:
if dep.find(KEY) == -1:
continue
slot = get_dep_slot(dep)
if not slot_rdeps.has_key(slot):
slot_rdeps[slot] = []
slot_rdeps[slot].append(rdep)
rdeps_with_slot(slot_rdeps)
|