/[gentoo]/src/packages/gentoo.py
Gentoo

Contents of /src/packages/gentoo.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.7 - (show annotations) (download) (as text)
Sun Oct 17 16:53:21 2004 UTC (9 years, 10 months ago) by marduk
Branch: MAIN
Changes since 1.6: +41 -5 lines
File MIME type: text/x-python
Various fixes & enhancements

1 #!/usr/bin/python -OO
2 """These functions mainly take ebuild info (grabbed from the database and
3 convert it to HTML. See the "main" function at the bottom."""
4
5 __revision__ = "$Revision: 1.6 $"
6 # $Source: /var/cvsroot/gentoo/src/packages/gentoo.py,v $
7
8 import config
9 import os
10 import time
11 import string
12 import sys
13 import ebuilddb
14 import bugs
15 import changelogs
16 from cgi import escape
17 from urllib import quote
18
19 # import portage, but temporarily redirect stderr
20 if 'portage' not in dir():
21 null = open('/dev/null', 'w')
22 tmp = sys.stderr
23 sys.stderr = null
24 sys.path = ["/usr/lib/portage/pym"]+sys.path
25 import portage
26 sys.stderr = tmp
27 sys.path = sys.path[1:]
28
29 tree = portage.portdbapi('/usr/portage')
30
31 def is_masked(ebuild):
32 """Return true if ebuild is masked"""
33
34 return (not tree.visible(['%(category)s/%(name)s-%(version)s' % ebuild]))
35
36 def is_new(db, ebuild):
37 """Check for newness. An ebuild is considered new if it is the
38 only ebuild with that category/name in ebuild and it has no prevarch"""
39
40 c = db.cursor()
41 query = ('SELECT prevarch FROM ebuild WHERE category="%s" AND name="%s"'
42 % (ebuild['category'], ebuild['name']))
43 c.execute(query)
44 results = c.fetchall()
45 if len(results) == 1 and results[0][0] is None:
46 return 1
47 return 0
48
49 def changelog_to_html(changelog):
50 """HTML-ize a changelog entry"""
51 html = ""
52 for char in changelog:
53 if char == '\n':
54 html = "%s<br>" % html
55 else:
56 html = "%s%s" % (html, escape(char))
57 html = changelogs.bugs_to_html(html)
58 return html
59
60 def homepage_to_html(homepage):
61 """convert HOMEPAGE entry to HTML"""
62 if not homepage.strip():
63 return "?"
64 homepage = homepage.replace('|',' ')
65 pieces = homepage.split()
66 count = len(pieces)
67 if count == 1:
68 return ('<a class="homepage" href="%s">'
69 'Homepage</a>' % pieces[0])
70
71 html = ['[<a href="%s">%s</a>]' % (page, index + 1) for index,
72 page in enumerate(pieces)]
73 return " ".join(['<span class="homepage">Homepages'] + html +
74 ['</span>'])
75
76 def license_to_html(license):
77 """Create link to license[s]"""
78 if not license.strip(): return "?"
79 license = license.replace('|',' ')
80 pieces = license.split()
81 html = ['<a href="http://www.gentoo.org/cgi-bin/viewcvs.cgi/*checkout*/'
82 'licenses/%s">%s</a>' % (piece, piece) for piece in pieces]
83 return '<br>\n'.join(html)
84
85 def package_to_html(pkginfo, db):
86 """This function needs a database (db) connection because it performs a
87 query_to_dict on the package"""
88
89 table_begin = '<table class="ebuild">'
90 name = '<tr><td class="fields">%s</td></tr>' % pkginfo['name']
91 description = ('<tr><td class="item">'
92 '<img align="right" alt="" src="%s/%s.png">'
93 '<b>Description: </b>%s</td></tr>' % (config.ICONS,
94 pkginfo['category'], escape(pkginfo['description'])))
95 ebuilds = get_recent_releases(pkginfo, db)
96 releases = '<tr><td>%s</td></tr>' % archs_to_html(ebuilds, 'Releases')
97 #bug_string = ('<br><h3>Related bugs:</h3>\n%s'
98 # % bugs_to_html(pkginfo['name']))
99 general = '<tr><td>%s</td></tr>' % general_info_to_html(pkginfo)
100 similar = '<tr><td>%s</td></tr>' % create_similar_pkgs_link(pkginfo)
101 table_end = '</table>'
102 rows = '\n\t'.join([name, description, releases, general])
103 return '\n\t'.join([table_begin, rows, table_end])
104
105 def archs_to_html(ebuilds, heading = None):
106 """Create table for availability on each architecture"""
107 heading = heading or '&nbsp;'
108 table_begin = '<table class="releases">'
109 header_row = ''.join(['<tr><td><b>%s</b></td>' % heading] +
110 ['<th class="arch">%s</th>' % i.replace('-',' ') for i in config.ARCHLIST] +
111 ['</tr>']
112 )
113 rows = []
114 ebuilds.sort(cmp_ebuilds)
115 ebuilds.reverse()
116 for ebuild in ebuilds:
117 masked = is_masked(ebuild)
118 archs = ebuild['arch'].split()
119 row_start = ('<tr>\n\t<th class="releases"><a href="%sebuilds/?%s-%s"'
120 ' title="%s">%s</a></th>\n' % (config.FEHOME,
121 ebuild['name'], ebuild['version'], ebuild['time'],
122 ebuild['version']))
123 row_data = []
124 for arch in config.ARCHLIST:
125 if arch in archs:
126 arch_string = '+'
127 elif '~%s' % arch in archs:
128 arch_string = '~'
129 else:
130 arch_string = '-'
131 if arch_string != '-' and masked:
132 arch_string = 'M' + arch_string
133 row_data.append('\t<td class="archcell" arch="%s">%s</td>'
134 % (arch_string, arch_string))
135 row_end = '</tr>'
136 rows.append('\n\t'.join([row_start] + row_data + [row_end]))
137 table_end = '</table>'
138 return '\n\t'.join([table_begin] + [header_row] + rows + [table_end])
139
140 def ebuild_to_html(ebinfo, new=0, show_bugs=0):
141 """Convert ebuild (dict) to html, if new, print out a "this is new" notice
142 if show_bugs, show bugs for this particular ebuild (requires access to
143 bugzilla"""
144 if new:
145 new_string = """ &nbsp;&nbsp;<span class="new">new!</span> """
146 else:
147 new_string = ""
148
149 table_begin = '<table class="ebuild">'
150 name_and_date = ('<tr><td class="fields">'
151 '<a href="%spackages/?category=%s;name=%s">%s</a> %s%s<br>'
152 '<span class="time">%s</span>'
153 '</td></tr>' % (config.FEHOME, quote(ebinfo['category']),
154 quote(ebinfo['name']),
155 ebinfo['name'],
156 ebinfo['version'],
157 new_string,
158 ebinfo['time'].localtime().strftime("%c %Z")))
159
160 desc_and_changes = ('<tr><td class="item" valign="top">'
161 '<img alt="" align="right" src="%simages/%s.png">'
162 '<p><b>Description:</b> %s</p>'
163 '<p><b>Changes:</b><br>'
164 '%s</p></td></tr>' % (
165 config.FEHOME,
166 ebinfo['category'],
167 escape(ebinfo['description']),
168 changelog_to_html(ebinfo['changelog'])))
169
170 archs = '<tr><td>%s</td></tr>' % archs_to_html([ebinfo])
171 general = '<tr><td>%s</td></tr>' % general_info_to_html(ebinfo)
172 table_end = '</table>'
173
174 if 1 == 1:
175 bug_string = ''
176 else:
177 bug_string = '<br><h3>Related bugs:</h3>%s' \
178 % bugs_to_html(ebinfo['name'])
179
180 return '\n\t'.join([table_begin,
181 name_and_date,
182 desc_and_changes,
183 archs,
184 general,
185 table_end,
186 bug_string])
187
188 def general_info_to_html(pkg):
189 """This actually will (should) take either a package or ebuild dict
190 as an argument"""
191
192 changelogurl = ('http://www.gentoo.org/cgi-bin/viewcvs.cgi/*checkout*/'
193 '%s/%s/ChangeLog' % (pkg['category'],pkg['name']))
194 cat_header = '<th class="category">Category</th>'
195 license_header = '<th class="license">License</th>'
196 category = ('<td class="category">'
197 '<a href="%spackages/?category=%s">%s</a></td>' % (config.FEHOME,
198 pkg['category'], pkg['category']))
199 homepage = ('<td class="homepage" rowspan="2">%s</td>'
200 % homepage_to_html(pkg['homepage']))
201 license = ('<td class="license">%s</td>'
202 % license_to_html(pkg['license']))
203 changelog = ('<td class="changelog" rowspan="2">'
204 '<a href="%s">ChangeLog</a></td>' % changelogurl)
205 similar = ('<td class="similar" rowspan="2">'
206 '%s</td>' % create_similar_pkgs_link(pkg))
207
208 return '\n\t'.join(['<table class="general_info">',
209 '<tr>',
210 cat_header,
211 homepage,
212 license_header,
213 changelog,
214 similar,
215 '</tr>',
216 '<tr>',
217 category,
218 license,
219 '</tr>',
220 '</table>'])
221
222 def create_similar_pkgs_link(pkg):
223 """Create a link to similar packages"""
224
225 def strip_chars(mystring):
226 newstring = ''
227 for char in mystring:
228 if char not in string.punctuation:
229 newstring = newstring + char
230 else:
231 newstring = newstring + ' '
232 return newstring
233
234 description = strip_chars(pkg['description'].lower())
235
236 words = [word for word in description.split()
237 if word and len(word)>2 and word not in config.EXCLUDED_FROM_SIMILAR]
238 words = words[:config.SIMILAR_MAX_WORDS] + [pkg['name']]
239 #query = ['[[:<:]]%s[[:>:]].*' % word for word in words]
240 query = ['[[:<:]]%s.*' % word for word in words]
241 query = '(%s){%s,}' % ('|'.join(query), config.SIMILAR_MIN_MATCHES)
242 url = '%ssearch/?sstring=%s' % (config.FEHOME, escape(query))
243 return '<a href="%s">Similar Packages</a>' % url
244
245 def bugs_to_html(package):
246 """Given package name (no version #s), return html text of bugs as
247 reported by bugzilla"""
248 # Right now we have an issue with the bugzilla site. New interface
249 # needs to be written, Bail out.
250 return ""
251 import urllib2
252 url = ('http://bugs.gentoo.org/buglist.cgi?query_format='
253 '&short_desc_type=allwords&short_desc=%s'
254 '&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED'
255 '&bug_status=REOPENED'
256 '&ctype=csv' % package)
257 fp = urllib2.urlopen(url)
258 factory = bugs.BugFactory()
259 package_bugs = factory.fromCSV(fp)
260 if package_bugs:
261 writer = bugs.HTMLWriter(package_bugs, 'bugs.gentoo.org')
262 return str(writer)
263 else:
264 return "None"
265
266 def get_most_recent(db, max=config.MAXPERPAGE, arch="", branch=""):
267 c = db.cursor()
268 extra = ''
269 if arch:
270 stable_extra = ('ebuild.arch REGEXP "^%s| %s" '
271 ' AND ebuild.prevarch NOT REGEXP"^%s| %s"'
272 % (arch,arch,arch,arch))
273 testing_extra = ('ebuild.arch REGEXP "^~%s| ~%s" '
274 ' AND ebuild.prevarch NOT REGEXP "^~%s| ~%s"'
275 % (arch,arch,arch,arch))
276 if branch == 'stable':
277 extra = ' AND (%s) ' % stable_extra
278 elif branch == 'testing':
279 extra = ' AND (%s) ' % testing_extra
280 else:
281 extra = ' AND ((%s) OR (%s)) ' % (stable_extra, testing_extra)
282 query = """SELECT ebuild.category,ebuild.name,version,when_found,description,
283 changelog,arch,homepage,license FROM ebuild,package WHERE ebuild.name=\
284 package.name AND ebuild.category=package.category %s ORDER by when_found DESC \
285 LIMIT %s""" % (extra,max)
286 c.execute(query)
287 results = c.fetchall()
288 return results
289
290 def query_to_dict(d):
291 """Convert a SQL query to a dict"""
292 einfo = {}
293 keys = ('category', 'name', 'version', 'time', 'description', 'changelog',
294 'arch', 'homepage', 'license')
295 for i in range(len(keys)):
296 try:
297 einfo[keys[i]] = d[i]
298 except IndexError:
299 continue
300 return einfo
301
302 def get_recent_releases(pkg, db, max=config.MAX_RECENT_RELEASES):
303 """Return MAX_RECENT_RELEASES most recent releases for pkg. Returns and
304 ebuild-type dict"""
305 c = db.cursor()
306 query = ('SELECT category,name,version,when_found,NULL,changelog,arch ,'
307 'NULL,NULL FROM ebuild WHERE name="%s" AND category="%s" ORDER BY '
308 'version DESC LIMIT %s' % (pkg['name'],pkg['category'],max))
309 c.execute(query)
310 results = c.fetchall()
311 #print results
312 return [ query_to_dict(i) for i in results ]
313
314 def cmp_ebuilds(a, b):
315 """Compare two ebuilds"""
316 fields_a = portage.pkgsplit('%s-%s' % (a['name'], a['version']))
317 fields_b = portage.pkgsplit('%s-%s' % (b['name'], b['version']))
318 return portage.pkgcmp(fields_a, fields_b)
319
320 def ebuilds_to_rss(fp, ebuilds, simple=False, subtitle=""):
321 """write out ebuild info to RSS file (fp)"""
322 fp.write("""<?xml version="1.0" encoding="iso-8859-1"?>
323 <rss version="0.92">
324 <channel>
325 <title>packages.gentoo.org [ %s ]</title>
326 <link>%s</link>
327 <description>Latest ebuilds from the Gentoo Linux portage tree</description>
328 <![CDATA[<link rel="stylesheet" href="%s" type="text/css" title="styled" />]]>
329 <webMaster>www@gentoo.org</webMaster>
330 <managingEditor>marduk@gentoo.org</managingEditor>
331 <pubDate>%s</pubDate>""" % (subtitle,config.FEHOME, config.STYLESHEET,
332 time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime())))
333
334 for ebuild in ebuilds:
335 if simple:
336 description = escape(ebuild['description'])
337 else:
338 description = '\n<![CDATA[\n%s\n]]>' % ebuild_to_html(ebuild)
339
340 fp.write("""<item>
341 <title>%s %s</title>
342 <link>%sebuilds/?%s-%s</link>
343 <description>
344 %s
345 </description>
346 <pubDate>%s</pubDate>
347 </item>
348 """ % (ebuild['name'],
349 ebuild['version'],
350 config.FEHOME,
351 ebuild['name'],
352 ebuild['version'],
353 description,
354 ebuild['time'].gmtime().strftime("%a, %d %b %Y %H:%M:%S +0000"))
355 )
356
357 fp.write("</channel>\n</rss>\n")
358
359 def main(argv=None):
360 if argv is None:
361 argv = sys.argv
362 try:
363 if argv[1] == '-g':
364 ebuilddb.main()
365 except IndexError:
366 pass
367
368 db = ebuilddb.db_connect()
369 branches = ('', 'stable', 'testing')
370 for arch in [''] + config.ARCHLIST:
371 for branch in branches:
372 fullpath = os.path.join(config.LOCALHOME, "archs", arch, branch,
373 config.INDEX)
374 index = open(fullpath,'w')
375 if arch:
376 sarch = arch
377 else:
378 sarch = 'all'
379 if branch:
380 sbranch = branch
381 else:
382 sbranch = 'all'
383
384 index.write("""<table border="0" cellpadding="0" cellspacing="5"
385 width="100%">\n""")
386 index.write("""<tr><td valign="top">\n""")
387 index.write('<!--#include file="archnav.html" -->\n\n</td></tr>\n'
388 '<tr><td>')
389 results = get_most_recent(db, arch=arch, branch=branch)
390 ebuilds = [ query_to_dict(i) for i in results ]
391 for ebuild in ebuilds:
392 new = is_new(db, ebuild)
393 pkgfilename = "%s/%s-%s.html" % (
394 config.EBUILD_FILES,ebuild['name'],ebuild['version'])
395 ebuild_html = ebuild_to_html(ebuild, new)
396 if arch == '' and branch == '':
397 pkgfile = open(pkgfilename,'w')
398 pkgfile.write(ebuild_html)
399 pkgfile.close()
400 ebuildfilename = "%s/%s/%s/%s-%s.ebuild" \
401 % (ebuilddb.config.PORTAGE_DIR,
402 ebuild['category'],ebuild['name'],ebuild['name'],
403 ebuild['version'])
404 os.system('touch -r %s %s || touch -d "today -1 year" %s'
405 % (ebuildfilename,pkgfilename,pkgfilename))
406
407 try:
408 index.write('%s\n\n' % (ebuild_html))
409 except IOError:
410 continue
411 index.write("""</table>\n""")
412 index.close()
413
414 subtitle = ' %s %s' % (arch, branch)
415 rss = open(os.path.join(config.LOCALHOME, "archs", arch, branch,
416 config.RSS), 'w')
417 ebuilds_to_rss(rss, ebuilds, simple=False, subtitle=subtitle)
418 rss.close()
419
420 rss2 = open(os.path.join(config.LOCALHOME, "archs", arch, branch,
421 config.RSS2), 'w')
422 ebuilds_to_rss(rss2, ebuilds, simple=True, subtitle=subtitle)
423 rss.close()
424
425 if __name__ == '__main__':
426 sys.exit(main())

  ViewVC Help
Powered by ViewVC 1.1.20