fd59e4bf210970255f4c48ffb54dd3905e646459
[gentoolkit.git] / bin / epkginfo
1 #!/usr/bin/python
2 ##############################################################################
3 # $Header: $
4 ##############################################################################
5 # Distributed under the terms of the GNU General Public License, v2 or later
6 # Author: Ned Ludd <solar@gentoo.org> (glue all the parts together)
7 # Author: Eldad Zack <eldad@gentoo.org> (earch)
8 # Author : Eric Olinger <EvvL AT RustedHalo DOT net> (metadata)
9
10 # Gentoo metadata xml and arch keyword checking tool.
11
12 import os
13 import sys
14 import re
15 from stat import *
16 from xml.sax import saxutils, make_parser, handler
17 from xml.sax.handler import feature_namespaces
18
19 import portage
20 from portage.output import *
21
22 __version__ = "svn"
23
24 def earch(workdir):
25         """Prints arch keywords for a given dir"""
26         portdir = portage.settings["PORTDIR"]
27         #workdir = "."
28         os.chdir(workdir)
29
30         archdict = {}
31         ebuildlist = []
32         for file in os.listdir(workdir):
33                 if re.search("\.ebuild$",file):
34                         ebuildlist.append(re.split("\.ebuild$",file)[0])
35
36         ebuildlist.sort(lambda x,y: portage.pkgcmp(portage.pkgsplit(x),portage.pkgsplit(y)))
37
38         slot_list = []
39
40         for pkg in ebuildlist:          
41                 portdb = portage.portdbapi(portdir)
42                 aux = portdb.aux_get(workdir.rsplit("/")[-2] + "/" + pkg, ['SLOT', 'KEYWORDS'])
43                 
44                 slot = aux[0]
45                 keywords = keywords = re.split(' ',aux[1])
46                 
47                 if not slot in slot_list:
48                         slot_list.append(slot)
49                 
50                 for arch in keywords:
51                         if arch in archdict:
52                                 archdict[arch].append((pkg, slot))
53                         else:
54                                 archdict[arch] = [ (pkg, slot) ]
55
56         archlist = archdict.keys();
57         archlist.sort()
58
59         slot_list.sort()
60
61         for slot in slot_list:
62                 visible_stable = {}
63                 visible_unstable = {}
64                 
65                 for arch in archlist:
66                         visible_stable[arch] = None
67                         visible_unstable[arch] = None
68                         
69                 for pkg in ebuildlist:
70                         for arch in archlist:
71                                 if (arch and (pkg, slot) in archdict[arch]):
72                                         if arch[0] == "-":
73                                                 pass
74                                         elif "~" == arch[0]:
75                                                 visible_unstable[arch] = pkg
76                                         else:
77                                                 visible_unstable["~" + arch] = None
78                                                 visible_stable[arch] = pkg
79                 
80                 for pkg in ebuildlist:
81                         found = False
82                         for arch in archlist:
83                                 if (pkg, slot) in archdict[arch]:
84                                         found = True
85                         
86                         if not found:
87                                 continue
88                         
89                         if not pkg == ebuildlist[0]:
90                                 print ""
91                                 
92                         print darkgreen("Keywords: ") + pkg + "[" + slot + "]:",
93                         
94                         for arch in archlist:
95                                 if (arch and (pkg, slot) in archdict[arch]):
96                                         if arch[0] == "-":
97                                                 print red(arch),
98                                         elif "~" == arch[0]:
99                                                 if visible_unstable[arch] == pkg:
100                                                         print blue(arch),
101                                         else:
102                                                 if visible_stable[arch] == pkg:
103                                                         print green(arch),
104
105
106 class Metadata_XML(handler.ContentHandler):
107         _inside_herd="No"
108         _inside_maintainer="No"
109         _inside_email="No"
110         _inside_longdescription="No"
111
112         _herd = []
113         _maintainers = []
114         _longdescription = ""
115
116         def startElement(self, tag, attr):
117                 if tag == "herd":
118                         self._inside_herd="Yes"
119                 if tag == "longdescription":
120                         self._inside_longdescription="Yes"
121                 if tag == "maintainer":
122                         self._inside_maintainer="Yes"
123                 if tag == "email":
124                         self._inside_email="Yes"
125
126         def endElement(self, tag):
127                 if tag == "herd":
128                         self._inside_herd="No"
129                 if tag == "longdescription":
130                         self._inside_longdescription="No"
131                 if tag == "maintainer":
132                         self._inside_maintainer="No"
133                 if tag == "email":
134                         self._inside_email="No"
135
136         def characters(self, contents):
137                 if self._inside_herd == "Yes":
138                         self._herd.append(contents)
139
140                 if self._inside_longdescription == "Yes":
141                         self._longdescription = contents
142                         
143                 if self._inside_maintainer=="Yes" and self._inside_email=="Yes":
144                         self._maintainers.append(contents)
145
146
147 def check_metadata(full_package):
148         """Checks that the primary maintainer is still an active dev and list the herd the package belongs to"""
149         metadata_file=portage.settings["PORTDIR"] + "/" + portage.pkgsplit(full_package)[0] + "/metadata.xml"
150         if not os.path.exists(metadata_file):
151                 print darkgreen("Maintainer: ") + red("Error (Missing metadata.xml)")
152                 return 1
153
154         parser = make_parser()
155         handler = Metadata_XML()
156         handler._maintainers = []
157         parser.setContentHandler(handler)
158         parser.parse( metadata_file )
159
160         if handler._herd:
161                 herds = ", ".join(handler._herd)
162                 print darkgreen("Herd: ") + herds
163         else:       
164                 print darkgreen("Herd: ") + red("Error (No Herd)")
165                 return 1
166
167
168         if handler._maintainers:
169                 print darkgreen("Maintainer: ") + ", ".join(handler._maintainers)
170         else:
171                 print darkgreen("Maintainer: ") + "none"
172
173         if len(handler._longdescription) > 1:
174                 print darkgreen("Description: ") + handler._longdescription
175         print darkgreen("Location: ") + os.path.normpath(portage.settings["PORTDIR"] + "/" + portage.pkgsplit(full_package)[0])
176
177
178 def usage(code):
179         """Prints the uage information for this script"""
180         print green("epkginfo"), "(%s)" % __version__
181         print
182         print "Usage: epkginfo [package-cat/]package"
183         sys.exit(code)
184
185
186 # default color setup
187 if ( not sys.stdout.isatty() ) or ( portage.settings["NOCOLOR"] in ["yes","true"] ):
188         nocolor()
189
190 def fc(x,y):
191         return cmp(y[0], x[0])
192
193
194 def grab_changelog_devs(catpkg):
195         try:
196                 os.chdir(portage.settings["PORTDIR"] + "/" + catpkg)
197                 foo=""
198                 r=re.compile("<[^@]+@gentoo.org>", re.I)
199                 s="\n".join(portage.grabfile("ChangeLog"))
200                 d={}
201                 for x in r.findall(s):
202                         if x not in d:
203                                 d[x] = 0
204                         d[x] += 1
205
206                 l=[(d[x], x) for x in d.keys()]
207                 #l.sort(lambda x,y: cmp(y[0], x[0]))
208                 l.sort(fc)
209                 for x in l:
210                         p = str(x[0]) +" "+ x[1].lstrip("<").rstrip(">")
211                         foo += p[:p.find("@")]+", "
212                 return foo
213         except:
214                 raise
215
216 def main ():
217         if len( sys.argv ) < 2:
218                 usage(1)
219
220         for pkg in sys.argv[1:]:
221
222                 if sys.argv[1:][:1] == "-":
223                         print "NOT WORKING?=="+sys.argv[1:]
224                         continue
225
226                 try:
227                         package_list = portage.portdb.xmatch("match-all", pkg)
228                         if package_list:
229
230                                 catpkg = portage.pkgsplit(package_list[0])[0]
231
232                                 print darkgreen("Package: ") + catpkg
233                                 check_metadata(package_list[0])
234                                 earch(portage.settings["PORTDIR"] + "/" + catpkg)
235                                 #print darkgreen("ChangeLog: ") + grab_changelog_devs(catpkg)
236                                 print ""
237                         else:
238                                 print "!!! No package '%s'" % pkg
239                 except:
240                         print red("Error: "+pkg+"\n")
241
242
243 if __name__ == '__main__':
244         main()