/[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.16 Revision 1.16.2.4
1#!/usr/bin/python -O 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__revision__ = "$Revision: 1.16 $" 5__revision__ = "$Revision: 1.16.2.4 $"
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
13import ebuilddb 13import ebuilddb
14import bugs 14import bugs
15import changelogs 15import changelogs
16from cgi import escape 16from cgi import escape
17from urllib import quote 17from urllib import quote
18 18from portage_versions import pkgcmp, pkgsplit
19endversion={"pre":-2,"p":0,"alpha":-4,"beta":-3,"rc":-1}
20# as there's no reliable way to set {}.keys() order
21# netversion_keys will be used instead of endversion.keys
22# to have fixed search order, so that "pre" is checked
23# before "p"
24endversion_keys = ["pre", "p", "alpha", "beta", "rc"]
25 19
26def is_new(db, ebuild): 20def is_new(db, ebuild):
27 """Check for newness.""" 21 """Check for newness."""
28 22
29 c = db.cursor() 23 c = db.cursor()
58 if not license.strip(): return "?" 52 if not license.strip(): return "?"
59 license = license.replace('|',' ') 53 license = license.replace('|',' ')
60 license = license.replace('(', '') 54 license = license.replace('(', '')
61 license = license.replace(')', '') 55 license = license.replace(')', '')
62 pieces = license.split() 56 pieces = license.split()
63 html = ['<a href="http://www.gentoo.org/cgi-bin/viewcvs.cgi/*checkout*/' 57 html = ['<a href="http://sources.gentoo.org/viewcvs.py/*checkout*/'
64 'licenses/%s">%s</a>' % (piece, piece) for piece in pieces] 58 'gentoo-x86/licenses/%s">%s</a>' % (piece, piece) for piece in pieces]
65 return '<br>\n'.join(html) 59 return '<br>\n'.join(html)
66 60
67def package_to_html(pkginfo, db, full=False): 61def package_to_html(pkginfo, db, full=False):
68 """This function needs a database (db) connection because it performs a 62 """This function needs a database (db) connection because it performs a
69 query_to_dict on the package""" 63 query_to_dict on the package"""
181 """This actually will (should) take either a package or ebuild dict 175 """This actually will (should) take either a package or ebuild dict
182 as an argument""" 176 as an argument"""
183 177
184 import forums 178 import forums
185 179
186 changelogurl = ('http://www.gentoo.org/cgi-bin/viewcvs.cgi/*checkout*/' 180 changelogurl = ('http://sources.gentoo.org/viewcvs.py/*checkout*/'
187 '%s/%s/ChangeLog' % (pkg['category'],pkg['name'])) 181 'gentoo-x86/%s/%s/ChangeLog' % (pkg['category'],pkg['name']))
188 cat_header = '<th class="category">Category</th>' 182 cat_header = '<th class="category">Category</th>'
189 license_header = '<th class="license">License</th>' 183 license_header = '<th class="license">License</th>'
190 category = ('<td class="category">' 184 category = ('<td class="category">'
191 '<a href="%spackages/?category=%s">%s</a></td>' % (config.FEHOME, 185 '<a href="%spackages/?category=%s">%s</a></td>' % (config.FEHOME,
192 pkg['category'], pkg['category'])) 186 pkg['category'], pkg['category']))
220 '</table>']) 214 '</table>'])
221 215
222def create_similar_pkgs_link(pkg): 216def create_similar_pkgs_link(pkg):
223 """Create a link to similar packages""" 217 """Create a link to similar packages"""
224 218
225 def strip_chars(mystring): 219 return '<a href="/similar/?package=%(category)s/%(name)s">Similar</a>' % pkg
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 220
245def create_related_bugs_link(pkg): 221def create_related_bugs_link(pkg):
246 """Create a link to related bugs""" 222 """Create a link to related bugs"""
247 223
248 url = ('http://bugs.gentoo.org/buglist.cgi?query_format=' 224 url = ('http://bugs.gentoo.org/buglist.cgi?query_format='
297 extra = ' AND ((%s) OR (%s)) ' % (stable_extra, testing_extra) 273 extra = ' AND ((%s) OR (%s)) ' % (stable_extra, testing_extra)
298 274
299 if new: 275 if new:
300 extra = ('%s AND package.new=1 ' % extra) 276 extra = ('%s AND package.new=1 ' % extra)
301 277
302 query = """SELECT ebuild.category,ebuild.name,version,when_found,description, 278 query = """SELECT ebuild.category,ebuild.name,version,ebuild.when_found,description,
303 changelog,arch,homepage,license,is_masked FROM ebuild,package WHERE ebuild.name=\ 279 changelog,arch,homepage,license,is_masked FROM ebuild,package WHERE ebuild.name=\
304 package.name AND ebuild.category=package.category %s ORDER by when_found DESC \ 280 package.name AND ebuild.category=package.category %s ORDER by ebuild.when_found DESC \
305 LIMIT %s""" % (extra,max) 281 LIMIT %s""" % (extra,max)
306 c.execute(query) 282 c.execute(query)
307 results = c.fetchall() 283 results = c.fetchall()
308 return results 284 return results
309 285
348def cmp_ebuilds(a, b): 324def cmp_ebuilds(a, b):
349 """Compare two ebuilds""" 325 """Compare two ebuilds"""
350 fields_a = pkgsplit('%s-%s' % (a['name'], a['version'])) 326 fields_a = pkgsplit('%s-%s' % (a['name'], a['version']))
351 fields_b = pkgsplit('%s-%s' % (b['name'], b['version'])) 327 fields_b = pkgsplit('%s-%s' % (b['name'], b['version']))
352 return pkgcmp(fields_a, fields_b) 328 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 329
652def ebuilds_to_rss(fp, ebuilds, simple=False, subtitle=""): 330def ebuilds_to_rss(fp, ebuilds, simple=False, subtitle=""):
653 """write out ebuild info to RSS file (fp)""" 331 """write out ebuild info to RSS file (fp)"""
654 332
655 # web link for RSS feed 333 # web link for RSS feed
705 ebuild['time'].strftime("%a, %d %b %Y %H:%M:%S +0000")) 383 ebuild['time'].strftime("%a, %d %b %Y %H:%M:%S +0000"))
706 ) 384 )
707 385
708 fp.write("\n\ 386 fp.write("\n\
709 <textInput>\n\ 387 <textInput>\n\
710 <title>Search the Online Package Database</title>\n\ 388 <title>Search</title>\n\
711 <link>%s/search/</link>\n\ 389 <link>%s/search/</link>\n\
712 <description>emerge -Ss</description>\n\ 390 <description>Search the Online Package Database</description>\n\
713 <name>sstring</name>\n\ 391 <name>sstring</name>\n\
714 </textInput>\n\ 392 </textInput>\n\
715 </channel>\n\ 393 </channel>\n\
716 </rss>\n" % config.FEHOME) 394 </rss>\n" % config.FEHOME)
717 395

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

  ViewVC Help
Powered by ViewVC 1.1.20