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

Diff of /src/packages/gentoo.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 1.2 Revision 1.16
1#!/usr/bin/python -OO 1#!/usr/bin/python -O
2"""These functions mainly take ebuild info (grabbed from the database and 2"""These functions mainly take ebuild info (grabbed from the database and
3 convert it to HTML. See the "main" function at the bottom.""" 3 convert it to HTML. See the "main" function at the bottom."""
4 4
5__version__ = "$Revision: 1.2 $" 5__revision__ = "$Revision: 1.16 $"
6# $Source: /var/cvsroot/gentoo/src/packages/gentoo.py,v $" 6# $Source: /var/cvsroot/gentoo/src/packages/gentoo.py,v $
7 7
8import config 8import config
9import os 9import os
10import time 10import time
11import string
11import sys 12import sys
12import ebuilddb 13import ebuilddb
13import bugs 14import bugs
14import changelogs 15import changelogs
15from cgi import escape 16from cgi import escape
16from urllib import quote 17from urllib import quote
17 18
18# import portage, but temporarily redirect stderr 19endversion={"pre":-2,"p":0,"alpha":-4,"beta":-3,"rc":-1}
19try: 20# as there's no reliable way to set {}.keys() order
20 portage 21# netversion_keys will be used instead of endversion.keys
21except NameError: 22# to have fixed search order, so that "pre" is checked
22 null = open('/dev/null', 'w') 23# before "p"
23 tmp = sys.stderr 24endversion_keys = ["pre", "p", "alpha", "beta", "rc"]
24 sys.stderr = null
25 sys.path = ["/usr/lib/portage/pym"]+sys.path
26 import portage
27 sys.stderr = tmp
28 25
29tree = portage.portdbapi('/usr/portage')
30
31def is_masked(ebuild):
32 """Return true if ebuild is masked"""
33
34 return (not tree.visible(['%(category)s/%(name)s-%(version)s' % ebuild]))
35
36def is_new(db,ebuild): 26def is_new(db, ebuild):
37 """Check for newness. An ebuild is considered new if it is the 27 """Check for newness."""
38 only ebuild with that category/name in ebuild and it has no prevarch""" 28
39
40 c = db.cursor() 29 c = db.cursor()
41 query = ('SELECT prevarch FROM ebuild WHERE category="%s" AND name="%s"' 30 query = ('SELECT new FROM package WHERE category="%s" AND name="%s"'
42 % (ebuild['category'], ebuild['name'])) 31 % (ebuild['category'], ebuild['name']))
43 c.execute(query) 32 c.execute(query)
44 results = c.fetchall() 33 results = c.fetchall()
45 if len(results) == 1 and results[0][0] is None: 34 if len(results) == 1 and results[0][0]:
46 return 1 35 return 1
47 return 0 36 return 0
48 37
49def changelog_to_html(changelog): 38changelog_to_html = changelogs.bugs_to_html
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 39
60def homepage_to_html(homepage): 40def homepage_to_html(homepage):
61 """convert HOMEPAGE entry to HTML""" 41 """convert HOMEPAGE entry to HTML"""
62 if not homepage.strip(): return "?" 42 if not homepage.strip():
43 return "?"
63 homepage = homepage.replace('|',' ') 44 homepage = homepage.replace('|',' ')
64 pieces = homepage.split() 45 pieces = homepage.split()
65 count = len(pieces) 46 count = len(pieces)
66 if count == 1: 47 if count == 1:
67 return ('<a class="homepage" href="%s">' 48 return ('<a class="homepage" href="%s">'
68 'Homepage</a>' % pieces[0]) 49 'Homepage</a>' % pieces[0])
69 50
70 html = ['[<a href="%s">%s</a>]' % (page, index + 1) for index, 51 html = ['[<a href="%s">%s</a>]' % (page, index + 1) for index,
71 page in enumerate(pieces)] 52 page in enumerate(pieces)]
72 return " ".join(['<span class="homepage">Homepages'] + html + 53 return " ".join(['<span class="homepage">Homepages'] + html +
73 ['</span>']) 54 ['</span>'])
74 55
75def license_to_html(license): 56def license_to_html(license):
57 """Create link to license[s]"""
76 if not license.strip(): return "?" 58 if not license.strip(): return "?"
77 license = license.replace('|',' ') 59 license = license.replace('|',' ')
60 license = license.replace('(', '')
61 license = license.replace(')', '')
78 pieces = license.split() 62 pieces = license.split()
79 html = ['<a href="http://www.gentoo.org/cgi-bin/viewcvs.cgi/*checkout*/' 63 html = ['<a href="http://www.gentoo.org/cgi-bin/viewcvs.cgi/*checkout*/'
80 'licenses/%s">%s</a>' % (piece, piece) for piece in pieces] 64 'licenses/%s">%s</a>' % (piece, piece) for piece in pieces]
81 return '<br>\n'.join(html) 65 return '<br>\n'.join(html)
82 66
83def package_to_html(pkginfo,db): 67def package_to_html(pkginfo, db, full=False):
84 """This function needs a database (db) connection because it performs a query_to_dict 68 """This function needs a database (db) connection because it performs a
85 on the package""" 69 query_to_dict on the package"""
86 70
87 table_begin = '<table class="ebuild">' 71 table_begin = '<table class="ebuild">'
88 name = '<tr><td class="fields">%s</td></tr>' % pkginfo['name'] 72 name = '<tr><td class="fields">%s</td></tr>' % pkginfo['name']
73 if full:
74 image = ('<img class="pkgimg"alt="" src="%s/%s/%s.jpg" align="right">' %
75 (config.ICONS, pkginfo['category'], pkginfo['name'])
76 )
77 else:
78 image = ''
89 description = ('<tr><td class="item">' 79 description = ('<tr><td class="item">'
90 '<img align="right" alt="" src="%s/%s.png">'
91 '<b>Description: </b>%s</td></tr>' % (config.ICONS, 80 '%s<b>Description: </b>%s</td></tr>'
92 pkginfo['category'], escape(pkginfo['description']))) 81 % (image, escape(pkginfo['description']))
82 )
93 ebuilds = get_recent_releases(pkginfo,db) 83 ebuilds = get_recent_releases(pkginfo, db)
94 releases = '<tr><td>%s</td></tr>' % archs_to_html(ebuilds, 'Releases') 84 releases = '<tr><td>%s</td></tr>' % archs_to_html(ebuilds, 'Releases')
95 bug_string = ''
96 #bug_string = ('<br><h3>Related bugs:</h3>\n%s' 85 #bug_string = ('<br><h3>Related bugs:</h3>\n%s'
97 # % bugs_to_html(pkginfo['name'])) 86 # % bugs_to_html(pkginfo['name']))
98 general = '<tr><td>%s</td></tr>' % general_info_to_html(pkginfo) 87 general = '<tr><td>%s</td></tr>' % general_info_to_html(pkginfo)
88 #similar = '<tr><td>%s</td></tr>' % create_similar_pkgs_link(pkginfo)
99 table_end = '</table>' 89 table_end = '</table>'
100 rows = '\n\t'.join([name, description, releases, general]) 90 rows = '\n\t'.join([name, description, releases, general])
101 return '\n\t'.join([table_begin, rows, table_end]) 91 return '\n\t'.join([table_begin, rows, table_end])
102 92
103def archs_to_html(ebuilds, heading = None): 93def archs_to_html(ebuilds, heading = None):
94 """Create table for availability on each architecture"""
104 heading = heading or '&nbsp;' 95 heading = heading or '&nbsp;'
105 table_begin = '<table class="releases">' 96 table_begin = '<table class="releases">'
106 header_row = ''.join(['<tr><td><b>%s</b></td>' % heading] + 97 header_row = ''.join(['<tr><td><b>%s</b></td>' % heading] +
107 ['<th class="arch">%s</th>' % i for i in config.ARCHLIST] + 98 ['<th class="arch">%s</th>' % i.replace('-',' ') for i in config.ARCHLIST] +
108 ['</tr>'] 99 ['</tr>']
109 ) 100 )
110 rows = [] 101 rows = []
102 ebuilds.sort(cmp_ebuilds)
103 ebuilds.reverse()
111 for ebuild in ebuilds: 104 for ebuild in ebuilds:
112 masked = is_masked(ebuild)
113 archs = ebuild['arch'].split() 105 archs = ebuild['arch'].split(',')
114 row_start = ('<tr>\n\t<th class="releases"><a href="%sebuilds/?%s-%s"' 106 row_start = ('<tr>\n\t<th class="releases"><a href="%sebuilds/?%s-%s"'
115 ' title="%s">%s</a></th>\n' % (config.FEHOME, 107 ' title="%s">%s</a></th>\n' % (config.FEHOME,
116 ebuild['name'], ebuild['version'], ebuild['time'], 108 ebuild['name'], ebuild['version'], ebuild['time'],
117 ebuild['version'])) 109 ebuild['version']))
118 row_data = [] 110 row_data = []
119 for arch in config.ARCHLIST: 111 for arch in config.ARCHLIST:
120 if arch in archs: 112 if arch in archs:
121 arch_string = '+' 113 arch_string = '+'
122 elif '~%s' % arch in archs: 114 elif '~%s' % arch in archs:
123 arch_string = '~' 115 arch_string = '~'
124 else: 116 else:
125 arch_string = '-' 117 arch_string = '-'
126 if arch_string != '-' and masked: 118 if arch_string != '-' and ebuild['masked']:
127 arch_string = 'M' + arch_string 119 arch_string = 'M' + arch_string
128 row_data.append('\t<td class="archcell" arch="%s">%s</td>' 120 row_data.append('\t<td class="archcell" arch="%s">%s</td>'
129 % (arch_string, arch_string)) 121 % (arch_string, arch_string))
130 row_end = '</tr>' 122 row_end = '</tr>'
131 rows.append('\n\t'.join([row_start] + row_data + [row_end])) 123 rows.append('\n\t'.join([row_start] + row_data + [row_end]))
132 table_end = '</table>' 124 table_end = '</table>'
133 return '\n\t'.join([table_begin] + [header_row] + rows + [table_end]) 125 return '\n\t'.join([table_begin] + [header_row] + rows + [table_end])
134 126
135def ebuild_to_html(ebinfo, new=0, show_bugs=0): 127def ebuild_to_html(ebinfo, new=0, show_bugs=0, full = False):
128 """Convert ebuild (dict) to html, if new, print out a "this is new" notice
129 if show_bugs, show bugs for this particular ebuild (requires access to
130 bugzilla"""
136 if new: 131 if new:
137 new_string = """ &nbsp;&nbsp;<span class="new">new!</span> """ 132 new_string = """ &nbsp;&nbsp;<span class="new">new!</span> """
138 else: 133 else:
139 new_string = "" 134 new_string = ""
140 135
141 table_begin = '<table class="ebuild">' 136 table_begin = '<table class="ebuild">'
142 name_and_date = ('<tr><td class="fields">' 137 name_and_date = ('<tr><td class="fields">'
143 '<a href="%spackages/?category=%s;name=%s">%s</a> %s%s<br>' 138 '<a href="%spackages/?category=%s;name=%s">%s</a> %s%s<br>'
144 '<span class="time">%s</span>' 139 '<span class="time">%s</span>'
145 '</td></tr>' % (config.FEHOME, quote(ebinfo['category']), 140 '</td></tr>' % (config.FEHOME, quote(ebinfo['category']),
146 quote(ebinfo['name']), 141 quote(ebinfo['name']),
147 ebinfo['name'], 142 ebinfo['name'],
148 ebinfo['version'], 143 ebinfo['version'],
149 new_string, 144 new_string,
150 ebinfo['time'].localtime().strftime("%c %Z"))) 145 ebinfo['time'].strftime("%c %Z")))
146
147 if full:
148 image = ('<img class="pkgimg" alt="" src="%s/%s/%s.jpg" align="right">' %
149 (config.ICONS, ebinfo['category'], ebinfo['name'])
151 150 )
151 else:
152 image = ''
152 desc_and_changes = ('<tr><td class="item" valign="top">' 153 desc_and_changes = ('<tr><td class="item" valign="top">'
153 '<img alt="" align="right" src="%simages/%s.png">'
154 '<p><b>Description:</b> %s</p>' 154 '<p><b>Description:</b> %s %s</p>'
155 '<p><b>Changes:</b><br>' 155 '<p><b>Changes:</b><br>'
156 '%s</p></td></tr>' % ( 156 '%s</p></td></tr>' % (
157 config.FEHOME,
158 ebinfo['category'],
159 escape(ebinfo['description']), 157 escape(ebinfo['description']),
158 image,
160 changelog_to_html(ebinfo['changelog']))) 159 changelog_to_html(ebinfo['changelog'])))
161 160
162 archs = '<tr><td>%s</td></tr>' % archs_to_html([ebinfo]) 161 archs = '<tr><td>%s</td></tr>' % archs_to_html([ebinfo])
163 general = '<tr><td>%s</td></tr>' % general_info_to_html(ebinfo) 162 general = '<tr><td>%s</td></tr>' % general_info_to_html(ebinfo)
164 table_end = '</table>' 163 table_end = '</table>'
165 164
166 if 1 == 1:
167 bug_string = '' 165 bug_string = ''
168 else: 166 if show_bugs:
169 bug_string = '<br><h3>Related bugs:</h3>%s' % bugs_to_html(ebinfo['name']) 167 bug_string = bugs_to_html(ebinfo['name'])
170 168 if bug_string:
169 bug_string = '<br><h3 class="bugs">Related bugs:</h3>%s' \
170 % bug_string
171
171 return '\n\t'.join([table_begin, 172 return '\n\t'.join([table_begin,
172 name_and_date, 173 name_and_date,
173 desc_and_changes, 174 desc_and_changes,
174 archs, 175 archs,
175 general, 176 general,
176 table_end, 177 table_end,
177 bug_string]) 178 bug_string])
178 179
179def general_info_to_html(pkg): 180def general_info_to_html(pkg):
180 """This actually will (should) take either a package or ebuild dict 181 """This actually will (should) take either a package or ebuild dict
181 as an argument""" 182 as an argument"""
182 183
184 import forums
185
183 changelogurl = ('http://www.gentoo.org/cgi-bin/viewcvs.cgi/*checkout*/' 186 changelogurl = ('http://www.gentoo.org/cgi-bin/viewcvs.cgi/*checkout*/'
184 '%s/%s/ChangeLog' % (pkg['category'],pkg['name'])) 187 '%s/%s/ChangeLog' % (pkg['category'],pkg['name']))
185 cat_header = '<th class="category">Category</th>' 188 cat_header = '<th class="category">Category</th>'
186 license_header = '<th class="license">License</th>' 189 license_header = '<th class="license">License</th>'
187 category = ('<td class="category">' 190 category = ('<td class="category">'
188 '<a href="%spackages/?category=%s">%s</a></td>' % (config.FEHOME, 191 '<a href="%spackages/?category=%s">%s</a></td>' % (config.FEHOME,
189 pkg['category'], pkg['category'])) 192 pkg['category'], pkg['category']))
190 homepage = ('<td class="homepage" rowspan="2">%s</td>' 193 homepage = ('<td class="homepage" rowspan="2">%s</td>'
191 % homepage_to_html(pkg['homepage'])) 194 % homepage_to_html(pkg['homepage']))
192 license = ('<td class="license">%s</td>' 195 license = ('<td class="license">%s</td>'
193 % license_to_html(pkg['license'])) 196 % license_to_html(pkg['license']))
194 changelog = ('<td class="changelog" rowspan="2">' 197 changelog = ('<td class="changelog" rowspan="2">'
195 '<a href="%s">ChangeLog</a><td>' % changelogurl) 198 '<a href="%s">ChangeLog</a></td>' % changelogurl)
196 199 similar = ('<td class="similar" rowspan="2">'
200 '%s</td>' % create_similar_pkgs_link(pkg))
201 related_bugs = ('<td class="related_bugs" rowspan="2">'
202 '%s</td>' % create_related_bugs_link(pkg))
203 forums = ('<td class="forums" rowspan="2">'
204 '%s</td>' % forums.create_forums_link(pkg))
205
197 return '\n\t'.join(['<table class="general_info">', 206 return '\n\t'.join(['<table class="general_info">',
198 '<tr>', 207 '<tr>',
199 cat_header, 208 cat_header,
200 homepage, 209 homepage,
201 license_header, 210 license_header,
202 changelog, 211 changelog,
212 similar,
213 related_bugs,
214 forums,
203 '</tr>', 215 '</tr>',
204 '<tr>', 216 '<tr>',
205 category, 217 category,
206 license, 218 license,
207 '</tr>', 219 '</tr>',
208 '</table>']) 220 '</table>'])
209 221
222def 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</a>' % url
244
245def create_related_bugs_link(pkg):
246 """Create a link to related bugs"""
247
248 url = ('http://bugs.gentoo.org/buglist.cgi?query_format='
249 '&amp;short_desc_type=allwords'
250 '&amp;short_desc=%s'
251 '&amp;bug_status=UNCONFIRMED'
252 '&amp;bug_status=NEW'
253 '&amp;bug_status=ASSIGNED'
254 '&amp;bug_status=REOPENED'
255 % escape(pkg['name']))
256
257 return '<a title="bugs.gentoo.org" href="%s">Bugs</a>' % url
258
210def bugs_to_html(package): 259def bugs_to_html(package):
211 """Given package name (no version #s), return html text of bugs as 260 """Given package name (no version #s), return html text of bugs as
212 reported by bugzilla""" 261 reported by bugzilla"""
213 # Right now we have an issue with the bugzilla site. New interface 262 # Right now we have an issue with the bugzilla site. New interface
214 # needs to be written, Bail out. 263 # needs to be written, Bail out.
215 return "" 264 #return ""
216 import urllib2 265 import urllib2
217 url = ('http://bugs.gentoo.org/buglist.cgi?query_format=' 266 url = ('http://bugs.gentoo.org/buglist.cgi?query_format='
218 '&short_desc_type=allwords&short_desc=%s' 267 '&amp;short_desc_type=allwords'
219 '&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED' 268 '&amp;short_desc=%s'
269 '&amp;bug_status=UNCONFIRMED'
270 '&amp;bug_status=NEW'
271 '&amp;bug_status=ASSIGNED'
220 '&bug_status=REOPENED' 272 '&amp;bug_status=REOPENED'
273 '&amp;ctype=csv'
221 '&ctype=csv' % package) 274 % package)
222 fp = urllib2.urlopen(url) 275 fp = urllib2.urlopen(url)
223 factory = bugs.BugFactory() 276 factory = bugs.BugFactory()
224 package_bugs = factory.fromCSV(fp) 277 package_bugs = factory.fromCSV(fp)
225 if package_bugs: 278 if package_bugs:
226 writer = bugs.HTMLWriter(package_bugs, 'bugs.gentoo.org') 279 writer = bugs.HTMLWriter(package_bugs, 'bugs.gentoo.org')
227 return str(writer) 280 return str(writer)
228 else: 281 else:
229 return "None" 282 return ""
230 283
231def get_most_recent(db,max=config.MAXPERPAGE,arch="",branch=""): 284def get_most_recent(db, max=config.MAXPERPAGE, arch="", branch="", new = False):
232 c = db.cursor() 285 c = db.cursor()
233 extra = '' 286 extra = ''
234 if arch: 287 if arch:
235 stable_extra = ('ebuild.arch REGEXP "^%s| %s" ' 288 stable_extra = ('FIND_IN_SET("%s", ebuild.arch) > 0 AND '
236 ' AND ebuild.prevarch NOT REGEXP"^%s| %s"' 289 'FIND_IN_SET("%s", ebuild.prevarch) = 0 ' % (arch, arch))
237 % (arch,arch,arch,arch)) 290 testing_extra = ('FIND_IN_SET("~%s", ebuild.arch) > 0 AND '
238 testing_extra = ('ebuild.arch REGEXP "^~%s| ~%s" ' 291 'FIND_IN_SET("~%s", ebuild.prevarch) = 0 ' % (arch, arch))
239 ' AND ebuild.prevarch NOT REGEXP "^~%s| ~%s"'
240 % (arch,arch,arch,arch))
241 if branch == 'stable': 292 if branch == 'stable':
242 extra = ' AND (%s) ' % stable_extra 293 extra = ' AND (%s) ' % stable_extra
243 elif branch == 'testing': 294 elif branch == 'testing':
244 extra = ' AND (%s) ' % testing_extra 295 extra = ' AND (%s) ' % testing_extra
245 else: 296 else:
246 extra = ' AND ((%s) OR (%s)) ' % (stable_extra, testing_extra) 297 extra = ' AND ((%s) OR (%s)) ' % (stable_extra, testing_extra)
298
299 if new:
300 extra = ('%s AND package.new=1 ' % extra)
301
247 query = """SELECT ebuild.category,ebuild.name,version,when_found,description, 302 query = """SELECT ebuild.category,ebuild.name,version,when_found,description,
248 changelog,arch,homepage,license FROM ebuild,package WHERE ebuild.name=\ 303 changelog,arch,homepage,license,is_masked FROM ebuild,package WHERE ebuild.name=\
249 package.name AND ebuild.category=package.category %s ORDER by when_found DESC \ 304 package.name AND ebuild.category=package.category %s ORDER by when_found DESC \
250 LIMIT %s""" % (extra,max) 305 LIMIT %s""" % (extra,max)
251 c.execute(query) 306 c.execute(query)
252 results = c.fetchall() 307 results = c.fetchall()
253 return results 308 return results
254 309
310def get_most_recent_bumps(db, max=config.MAXPERPAGE):
311 """Return most recent version bumps (pkgs with no prevarch)"""
312 c = db.cursor()
313 query = ('SELECT ebuild.category, ebuild.name, version, when_found, '
314 'description, changelog, arch, homepage, license,is_masked FROM ebuild, package '
315 'WHERE ebuild.name=package.name AND ebuild.category=package.category '
316 'AND prevarch="" AND version NOT LIKE "%%-r_" AND version NOT LIKE '
317 '"%%-r__" AND NOT new ORDER by when_found '
318 'DESC LIMIT %s' % max)
319
320 c.execute(query)
321 results = c.fetchall()
322 return results
323
255def query_to_dict(d): 324def query_to_dict(d):
325 """Convert a SQL query to a dict"""
256 einfo = {} 326 einfo = {}
257 keys = ('category','name','version','time','description','changelog', 327 keys = ('category', 'name', 'version', 'time', 'description', 'changelog',
258 'arch','homepage','license') 328 'arch', 'homepage', 'license', 'masked')
259 for i in range(len(keys)): 329 for i in range(len(keys)):
260 try: 330 try:
261 einfo[keys[i]] = d[i] 331 einfo[keys[i]] = d[i]
262 except IndexError: 332 except IndexError:
263 continue 333 continue
264 return einfo 334 return einfo
265 335
266def get_recent_releases(pkg,db,max=config.MAX_RECENT_RELEASES): 336def get_recent_releases(pkg, db, max=config.MAX_RECENT_RELEASES):
267 """Return MAX_RECENT_RELEASES most recent releases for pkg. Returns and 337 """Return MAX_RECENT_RELEASES most recent releases for pkg. Returns and
268 ebuild-type dict""" 338 ebuild-type dict"""
269 c = db.cursor() 339 c = db.cursor()
270 query = """SELECT category,name,version,when_found,NULL,changelog,arch ,NULL,NULL 340 query = ('SELECT category,name,version,when_found,NULL,changelog,arch ,'
271 FROM ebuild WHERE name="%s" AND 341 'NULL,NULL,is_masked FROM ebuild WHERE name="%s" AND category="%s" ORDER BY '
272 category="%s" ORDER BY version DESC LIMIT %s 342 'version DESC LIMIT %s' % (pkg['name'],pkg['category'],max))
273 """ % (pkg['name'],pkg['category'],max)
274 c.execute(query) 343 c.execute(query)
275 results = c.fetchall() 344 results = c.fetchall()
276 #print results 345 #print results
277 return [ query_to_dict(i) for i in results ] 346 return [ query_to_dict(i) for i in results ]
278 347
348def cmp_ebuilds(a, b):
349 """Compare two ebuilds"""
350 fields_a = pkgsplit('%s-%s' % (a['name'], a['version']))
351 fields_b = pkgsplit('%s-%s' % (b['name'], b['version']))
352 return pkgcmp(fields_a, fields_b)
353
354pkgcache={}
355
356def pkgsplit(mypkg,silent=1):
357 try:
358 if not pkgcache[mypkg]:
359 return None
360 return pkgcache[mypkg][:]
361 except KeyError:
362 pass
363 myparts=string.split(mypkg,'-')
364 if len(myparts)<2:
365 if not silent:
366 print "!!! Name error in",mypkg+": missing a version or name part."
367 pkgcache[mypkg]=None
368 return None
369 for x in myparts:
370 if len(x)==0:
371 if not silent:
372 print "!!! Name error in",mypkg+": empty \"-\" part."
373 pkgcache[mypkg]=None
374 return None
375 #verify rev
376 revok=0
377 myrev=myparts[-1]
378 if len(myrev) and myrev[0]=="r":
379 try:
380 int(myrev[1:])
381 revok=1
382 except SystemExit, e:
383 raise
384 except:
385 pass
386 if revok:
387 if ververify(myparts[-2]):
388 if len(myparts)==2:
389 pkgcache[mypkg]=None
390 return None
391 else:
392 for x in myparts[:-2]:
393 if ververify(x):
394 pkgcache[mypkg]=None
395 return None
396 #names can't have versiony looking parts
397 myval=[string.join(myparts[:-2],"-"),myparts[-2],myparts[-1]]
398 pkgcache[mypkg]=myval
399 return myval
400 else:
401 pkgcache[mypkg]=None
402 return None
403
404 elif ververify(myparts[-1],silent=silent):
405 if len(myparts)==1:
406 if not silent:
407 print "!!! Name error in",mypkg+": missing name part."
408 pkgcache[mypkg]=None
409 return None
410 else:
411 for x in myparts[:-1]:
412 if ververify(x):
413 if not silent:
414 print "!!! Name error in",mypkg+": multiple version parts."
415 pkgcache[mypkg]=None
416 return None
417 myval=[string.join(myparts[:-1],"-"),myparts[-1],"r0"]
418 pkgcache[mypkg]=myval[:]
419 return myval
420 else:
421 pkgcache[mypkg]=None
422 return None
423
424vercache={}
425def ververify(myorigval,silent=1):
426 try:
427 return vercache[myorigval]
428 except KeyError:
429 pass
430 if len(myorigval)==0:
431 if not silent:
432 print "!!! Name error: package contains empty \"-\" part."
433 return 0
434 myval=string.split(myorigval,'.')
435 if len(myval)==0:
436 if not silent:
437 print "!!! Name error: empty version string."
438 vercache[myorigval]=0
439 return 0
440 #all but the last version must be a numeric
441 for x in myval[:-1]:
442 if not len(x):
443 if not silent:
444 print "!!! Name error in",myorigval+": two decimal points in a row"
445 vercache[myorigval]=0
446 return 0
447 try:
448 foo=int(x)
449 except SystemExit, e:
450 raise
451 except:
452 if not silent:
453 print "!!! Name error in",myorigval+": \""+x+"\" is not a valid version component."
454 vercache[myorigval]=0
455 return 0
456 if not len(myval[-1]):
457 if not silent:
458 print "!!! Name error in",myorigval+": two decimal points in a row"
459 vercache[myorigval]=0
460 return 0
461 try:
462 foo=int(myval[-1])
463 vercache[myorigval]=1
464 return 1
465 except SystemExit, e:
466 raise
467 except:
468 pass
469 #ok, our last component is not a plain number or blank, let's continue
470 if myval[-1][-1] in string.lowercase:
471 try:
472 foo=int(myval[-1][:-1])
473 vercache[myorigval]=1
474 return 1
475 # 1a, 2.0b, etc.
476 except SystemExit, e:
477 raise
478 except:
479 pass
480 #ok, maybe we have a 1_alpha or 1_beta2; let's see
481 #ep="endpart"
482 ep=string.split(myval[-1],"_")
483 if len(ep)!=2:
484 if not silent:
485 print "!!! Name error in",myorigval
486 vercache[myorigval]=0
487 return 0
488 try:
489 foo=int(ep[0][-1])
490 chk=ep[0]
491 except SystemExit, e:
492 raise
493 except:
494 # because it's ok last char is not numeric. example: foo-1.0.0a_pre1
495 chk=ep[0][:-1]
496
497 try:
498 foo=int(chk)
499 except SystemExit, e:
500 raise
501 except:
502 #this needs to be numeric or numeric+single letter,
503 #i.e. the "1" in "1_alpha" or "1a_alpha"
504 if not silent:
505 print "!!! Name error in",myorigval+": characters before _ must be numeric or numeric+single letter"
506 vercache[myorigval]=0
507 return 0
508 for mye in endversion_keys:
509 if ep[1][0:len(mye)]==mye:
510 if len(mye)==len(ep[1]):
511 #no trailing numeric; ok
512 vercache[myorigval]=1
513 return 1
514 else:
515 try:
516 foo=int(ep[1][len(mye):])
517 vercache[myorigval]=1
518 return 1
519 except SystemExit, e:
520 raise
521 except:
522 #if no endversions work, *then* we return 0
523 pass
524 if not silent:
525 print "!!! Name error in",myorigval
526 vercache[myorigval]=0
527 return 0
528
529def relparse(myver):
530 "converts last version part into three components"
531 number=0
532 suffix=0
533 endtype=0
534 endnumber=0
535
536 mynewver=string.split(myver,"_")
537 myver=mynewver[0]
538
539 #normal number or number with letter at end
540 divider=len(myver)-1
541 if myver[divider:] not in "1234567890":
542 #letter at end
543 suffix=ord(myver[divider:])
544 number=string.atof(myver[0:divider])
545 else:
546 number=string.atof(myver)
547
548 if len(mynewver)==2:
549 #an endversion
550 for x in endversion_keys:
551 elen=len(x)
552 if mynewver[1][:elen] == x:
553 endtype=endversion[x]
554 try:
555 endnumber=string.atof(mynewver[1][elen:])
556 except:
557 endnumber=0
558 break
559 return [number,suffix,endtype,endnumber]
560
561# vercmp:
562# ripped from portage.py to prevent having to import
563vcmpcache={}
564def vercmp(val1,val2):
565 if val1==val2:
566 #quick short-circuit
567 return 0
568 valkey=val1+" "+val2
569 try:
570 return vcmpcache[valkey]
571 try:
572 return -vcmpcache[val2+" "+val1]
573 except KeyError:
574 pass
575 except KeyError:
576 pass
577
578 # consider 1_p2 vc 1.1
579 # after expansion will become (1_p2,0) vc (1,1)
580 # then 1_p2 is compared with 1 before 0 is compared with 1
581 # to solve the bug we need to convert it to (1,0_p2)
582 # by splitting _prepart part and adding it back _after_expansion
583 val1_prepart = val2_prepart = ''
584 if val1.count('_'):
585 val1, val1_prepart = val1.split('_', 1)
586 if val2.count('_'):
587 val2, val2_prepart = val2.split('_', 1)
588
589 # replace '-' by '.'
590 # FIXME: Is it needed? can val1/2 contain '-'?
591 val1=string.split(val1,'-')
592 if len(val1)==2:
593 val1[0]=val1[0]+"."+val1[1]
594 val2=string.split(val2,'-')
595 if len(val2)==2:
596 val2[0]=val2[0]+"."+val2[1]
597
598 val1=string.split(val1[0],'.')
599 val2=string.split(val2[0],'.')
600
601 #add back decimal point so that .03 does not become "3" !
602 for x in range(1,len(val1)):
603 if val1[x][0] == '0' :
604 val1[x]='.' + val1[x]
605 for x in range(1,len(val2)):
606 if val2[x][0] == '0' :
607 val2[x]='.' + val2[x]
608
609 # extend version numbers
610 if len(val2)<len(val1):
611 val2.extend(["0"]*(len(val1)-len(val2)))
612 elif len(val1)<len(val2):
613 val1.extend(["0"]*(len(val2)-len(val1)))
614
615 # add back _prepart tails
616 if val1_prepart:
617 val1[-1] += '_' + val1_prepart
618 if val2_prepart:
619 val2[-1] += '_' + val2_prepart
620 #The above code will extend version numbers out so they
621 #have the same number of digits.
622 for x in range(0,len(val1)):
623 cmp1=relparse(val1[x])
624 cmp2=relparse(val2[x])
625 for y in range(0,4):
626 myret=cmp1[y]-cmp2[y]
627 if myret != 0:
628 vcmpcache[valkey]=myret
629 return myret
630 vcmpcache[valkey]=0
631 return 0
632
633# pkgcmp:
634# ripped from portage.py to prevent having to import
635def pkgcmp(pkg1,pkg2):
636 """if returnval is less than zero, then pkg2 is newer than pkg1, zero if equal and positive if older."""
637 if pkg1[0] != pkg2[0]:
638 return None
639 mycmp=vercmp(pkg1[1],pkg2[1])
640 if mycmp>0:
641 return 1
642 if mycmp<0:
643 return -1
644 r1=int(pkg1[2][1:])
645 r2=int(pkg2[2][1:])
646 if r1>r2:
647 return 1
648 if r2>r1:
649 return -1
650 return 0
651
279def ebuilds_to_rss(fp,ebuilds,simple=False,subtitle=""): 652def ebuilds_to_rss(fp, ebuilds, simple=False, subtitle=""):
280 """write out ebuild info to RSS file (fp)""" 653 """write out ebuild info to RSS file (fp)"""
654
655 # web link for RSS feed
656 if subtitle:
657 link = '%s/%s' % (config.FEHOME, subtitle.replace(' ','/',1))
658 else:
659 link = config.FEHOME
660
661 pubDate = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime())
281 fp.write("""<?xml version="1.0" encoding="utf-8"?> 662 fp.write("""<?xml version="1.0" encoding="UTF-8"?>
282 <rss version="0.92"> 663 <rss version="2.0">
283 <channel> 664 <channel>
284 <title>Fresh ebuilds %s</title> 665 <title>packages.gentoo.org [ %s ]</title>
285 <link>%s</link> 666 <link>%s</link>
286 <description>Latest ebuilds from the Gentoo Linux portage tree</description> 667 <description>Latest ebuilds from the Gentoo Linux portage tree</description>
287 <![CDATA[<link rel="stylesheet" href="%s" type="text/css" title="styled" />]]>
288 <webMaster>www@gentoo.org</webMaster> 668 <webMaster>www@gentoo.org</webMaster>
669
670 <image>
671 <title>Online Package Database</title>
672 <url>%s</url>
673 <link>%s</link>
674 </image>
675
289 <managingEditor>marduk@gentoo.org</managingEditor> 676 <managingEditor>marduk@gentoo.org</managingEditor>
290 <pubDate>%s</pubDate>""" % (subtitle,config.FEHOME, config.STYLESHEET, 677 <pubDate>%s</pubDate>""" % (subtitle, link, config.RSS_IMAGE,
291 time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime()))) 678 config.FEHOME, pubDate))
292 679
293 for ebuild in ebuilds: 680 for ebuild in ebuilds:
294 if simple: 681 if simple:
295 description = escape(ebuild['description']) 682 description = escape(ebuild['description'])
296 else: 683 else:
297 description = '\n<![CDATA[\n%s\n]]>' % ebuild_to_html(ebuild) 684 description = ('\n'
685 '<![CDATA[\n'
686 '<link rel="stylesheet" type="text/css" href="%s"></link>\n'
687 '%s\n]]>' % (config.STYLESHEET, ebuild_to_html(ebuild, full=True))
688 )
298 689
299 fp.write("""<item> 690 fp.write("""<item>
300 <title>%s %s</title> 691 <title>%s/%s %s</title>
301 <link>%sebuilds/?%s-%s</link> 692 <link>%sebuilds/?%s-%s</link>
302 <description> 693 <description>
303 %s 694 %s
304 </description> 695 </description>
305 <pubDate>%s</pubDate> 696 <pubDate>%s</pubDate>
306 </item> 697 </item>
307 """ % (ebuild['name'], 698 """ % (ebuild['category'],
699 ebuild['name'],
308 ebuild['version'], 700 ebuild['version'],
309 config.FEHOME, 701 config.FEHOME,
310 ebuild['name'], 702 ebuild['name'],
311 ebuild['version'], 703 ebuild['version'],
312 description, 704 description,
313 ebuild['time'].gmtime().strftime("%a, %d %b %Y %H:%M:%S +0000")) 705 ebuild['time'].strftime("%a, %d %b %Y %H:%M:%S +0000"))
314 ) 706 )
315 707
316 fp.write("</channel>\n</rss>\n") 708 fp.write("\n\
317 709 <textInput>\n\
318if __name__ == '__main__': 710 <title>Search the Online Package Database</title>\n\
711 <link>%s/search/</link>\n\
712 <description>emerge -Ss</description>\n\
713 <name>sstring</name>\n\
714 </textInput>\n\
715 </channel>\n\
716 </rss>\n" % config.FEHOME)
717
718def main(argv=None):
719 if argv is None:
720 argv = sys.argv
319 try: 721 try:
320 if sys.argv[1] == '-g': 722 if argv[1] == '-g':
321 ebuilddb.main() 723 ebuilddb.main()
322 except IndexError: 724 except IndexError:
323 pass 725 pass
324 726
325 db = ebuilddb.db_connect() 727 db = ebuilddb.db_connect()
326 branches = ('','stable','testing') 728 branches = ('', 'stable', 'testing')
327 for arch in [''] + config.ARCHLIST: 729 for arch in [''] + config.ARCHLIST:
328 for branch in branches: 730 for branch in branches:
329 fullpath = os.path.join(config.LOCALHOME,"archs",arch,branch,config.INDEX) 731 fullpath = os.path.join(config.LOCALHOME, "archs", arch, branch,
732 config.INDEX)
330 index = open(fullpath,'w') 733 index = open(fullpath,'w')
331 if arch: 734
332 sarch = arch
333 else:
334 sarch = 'all'
335 if branch:
336 sbranch = branch
337 else:
338 sbranch = 'all'
339
340 index.write("""<table border="0" cellpadding="0" cellspacing="5" 735 index.write("""<table border="0" cellpadding="0" cellspacing="5"
341 width="100%">\n""") 736 width="100%">\n""")
342 index.write("""<tr><td valign="top">\n""") 737 index.write("""<tr><td valign="top">\n""")
343 index.write('<!--#include file="archnav.html" -->\n\n</td></tr>\n<tr><td>') 738 index.write('<!--#include file="archnav.html" -->\n\n</td></tr>\n'
739 '<tr><td>')
344 results = get_most_recent(db,arch=arch,branch=branch) 740 results = get_most_recent(db, arch=arch, branch=branch)
345 ebuilds = [ query_to_dict(i) for i in results ] 741 ebuilds = [ query_to_dict(i) for i in results ]
346 for ebuild in ebuilds: 742 for ebuild in ebuilds:
347 new = is_new(db,ebuild) 743 new = is_new(db, ebuild)
348 pkgfilename = "%s/%s-%s.html" % ( 744 pkgfilename = "%s/%s-%s.html" % (
349 config.EBUILD_FILES,ebuild['name'],ebuild['version']) 745 config.EBUILD_FILES,ebuild['name'],ebuild['version'])
350 ebuild_html = ebuild_to_html(ebuild,new) 746 ebuild_html = ebuild_to_html(ebuild, new, show_bugs = False)
351 if arch == '' and branch == '': # and not os.path.exists(pkgfilename): 747 if arch == '' and branch == '':
352 pkgfile = open(pkgfilename,'w') 748 pkgfile = open(pkgfilename,'w')
353 pkgfile.write(ebuild_html) 749 pkgfile.write(ebuild_html)
354 pkgfile.close() 750 pkgfile.close()
355 ebuildfilename = "%s/%s/%s/%s-%s.ebuild" % (ebuilddb.config.PORTAGE_DIR, 751 ebuildfilename = "%s/%s/%s/%s-%s.ebuild" \
752 % (ebuilddb.config.PORTAGE_DIR,
356 ebuild['category'],ebuild['name'],ebuild['name'], 753 ebuild['category'],ebuild['name'],ebuild['name'],
357 ebuild['version']) 754 ebuild['version'])
358 os.system('touch -r %s %s || touch -d "today -1 year" %s' 755 os.system('touch -r %s %s || touch -d "today -1 year" %s'
359 % (ebuildfilename,pkgfilename,pkgfilename)) 756 % (ebuildfilename,pkgfilename,pkgfilename))
360 757
361 try: 758 try:
362 index.write('%s\n\n' % (ebuild_html)) 759 index.write('%s\n\n' % (ebuild_html))
363 except IOError: 760 except IOError:
364 pass 761 continue
365 index.write("""</table>\n""") 762 index.write("""</table>\n""")
366 index.close() 763 index.close()
367 764
368 subtitle = ' %s %s' % (arch,branch) 765 subtitle = ' %s %s' % (arch, branch)
369 rss = open(os.path.join(config.LOCALHOME,"archs",arch,branch,config.RSS),'w') 766 rss = open(os.path.join(config.LOCALHOME, "archs", arch, branch,
767 config.RSS), 'w')
370 ebuilds_to_rss(rss,ebuilds,simple=False,subtitle=subtitle) 768 ebuilds_to_rss(rss, ebuilds, simple=False, subtitle=subtitle)
371 rss.close() 769 rss.close()
372 770
373 rss2 = open(os.path.join(config.LOCALHOME,"archs",arch,branch,config.RSS2),'w') 771 rss2 = open(os.path.join(config.LOCALHOME, "archs", arch, branch,
772 config.RSS2), 'w')
374 ebuilds_to_rss(rss2,ebuilds,simple=True,subtitle=subtitle) 773 ebuilds_to_rss(rss2, ebuilds, simple=True, subtitle=subtitle)
375 rss.close() 774 rss.close()
775
776if __name__ == '__main__':
777 sys.exit(main())

Legend:
Removed from v.1.2  
changed lines
  Added in v.1.16

  ViewVC Help
Powered by ViewVC 1.1.20