2010-05-19 13:11:16 +00:00
#!/usr/bin/env python
2010-05-24 13:38:06 +00:00
# -*- Encoding: utf-8 -*-
2007-02-04 17:35:40 +00:00
###
# Copyright (c) 2006-2007 Dennis Kaarsemaker
2010-05-24 13:38:06 +00:00
# Copyright (c) 2008-2010 Terence Simpson
2007-02-04 17:35:40 +00:00
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of version 2 of the GNU General Public License as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
###
2010-05-24 13:38:06 +00:00
2009-01-19 22:26:32 +00:00
import exceptions
import warnings
warnings . filterwarnings ( " ignore " , " apt API not stable yet " , exceptions . FutureWarning )
2009-10-12 18:26:35 +00:00
import commands , os , apt , urllib
2007-02-04 17:35:40 +00:00
from email import FeedParser
def component ( arg ) :
if ' / ' in arg : return arg [ : arg . find ( ' / ' ) ]
return ' main '
2012-04-10 23:48:30 +00:00
def description ( pkg ) :
if not pkg :
return None
if pkg . has_key ( ' Description-en ' ) :
return pkg [ ' Description-en ' ] . split ( ' \n ' ) [ 0 ]
elif pkg . has_key ( ' Description ' ) :
return pkg [ ' Description ' ] . split ( ' \n ' ) [ 0 ]
return None
2007-02-04 17:35:40 +00:00
class Apt :
def __init__ ( self , plugin ) :
self . aptdir = plugin . registryValue ( ' aptdir ' )
self . distros = [ ]
2008-05-07 02:04:23 +00:00
self . plugin = plugin
2008-10-22 17:31:40 +00:00
self . log = plugin . log
2009-10-12 18:26:35 +00:00
os . environ [ " LANG " ] = " C "
2007-02-04 17:35:40 +00:00
if self . aptdir :
self . distros = [ x [ : - 5 ] for x in os . listdir ( self . aptdir ) if x . endswith ( ' .list ' ) ]
2008-10-22 17:31:40 +00:00
self . distros . sort ( )
2007-02-04 17:35:40 +00:00
self . aptcommand = """ apt-cache \\
- o " Dir::State::Lists= %s / %% s " \\
- o " Dir::etc::sourcelist= %s / %% s.list " \\
2012-04-10 23:48:30 +00:00
- o " Dir::etc::SourceParts= %s / %% s.list.d " \\
2007-02-04 17:35:40 +00:00
- o " Dir::State::status= %s / %% s.status " \\
- o " Dir::Cache= %s /cache " \\
2009-01-19 22:26:32 +00:00
- o " APT::Architecture=i386 " \\
2012-04-10 23:48:30 +00:00
% % s % % s """ % tuple([self.aptdir]*5)
2012-09-27 12:16:42 +00:00
self . aptfilecommand = """ apt-file -s %s / %% s.list -c %s /apt-file/ %% s -l -a i386 search %% s """ % ( self . aptdir , self . aptdir )
2007-02-04 17:35:40 +00:00
2010-05-24 13:38:06 +00:00
def find ( self , pkg , chkdistro , filelookup = True ) :
2012-04-10 13:05:29 +00:00
_pkg = ' ' . join ( [ x for x in pkg . strip ( ) . split ( None , 1 ) [ 0 ] if x . isalnum ( ) or x in ' .-_+/ ' ] )
distro = ' '
2007-02-04 17:35:40 +00:00
if len ( pkg . strip ( ) . split ( ) ) > 1 :
2009-10-12 18:26:35 +00:00
distro = ' ' . join ( [ x for x in pkg . strip ( ) . split ( None , 2 ) [ 1 ] if x . isalnum ( ) or x in ' .-_+ ' ] )
2010-05-24 13:38:06 +00:00
if not distro :
distro = chkdistro
2007-02-04 17:35:40 +00:00
if distro not in self . distros :
2009-10-12 18:26:35 +00:00
return " %s is not a valid distribution: %s " % ( distro , " , " . join ( self . distros ) )
2007-02-04 17:35:40 +00:00
pkg = _pkg
2012-04-12 19:49:50 +00:00
data = commands . getoutput ( self . aptcommand % ( distro , distro , distro , distro , ' search -n ' , pkg ) )
2007-02-04 17:35:40 +00:00
if not data :
if filelookup :
2012-04-12 20:03:02 +00:00
data = commands . getoutput ( self . aptfilecommand % ( distro , distro , pkg ) ) . split ( )
2007-02-04 17:35:40 +00:00
if data :
2008-05-05 11:34:57 +00:00
if data [ 0 ] == ' sh: ' : # apt-file isn't installed
2010-05-24 13:38:06 +00:00
self . log . error ( " PackageInfo/packages: apt-file is not installed " )
2008-05-05 11:34:57 +00:00
return " Please use http://packages.ubuntu.com/ to search for files "
if data [ 0 ] == ' E: ' : # No files in the cache dir
2010-05-24 13:38:06 +00:00
self . log . error ( " PackageInfo/packages: Please run the ' update_apt_file ' script " )
2008-05-05 18:10:49 +00:00
return " Cache out of date, please contact the administrator "
2009-01-19 22:26:32 +00:00
if data [ 0 ] == " Use " and data [ 1 ] == " of " :
2009-10-12 18:26:35 +00:00
url = " http://packages.ubuntu.com/search?searchon=contents&keywords= %s &mode=&suite= %s &arch=any " % ( urllib . quote ( pkg ) , distro )
2009-01-19 22:26:32 +00:00
return url
2010-09-04 15:19:46 +00:00
if len ( data ) > 10 :
return " File %s found in %s (and %d others) http://packages.ubuntu.com/search?searchon=contents&keywords= %s &mode=&suite= %s &arch=any " % ( pkg , ' , ' . join ( data [ : 10 ] ) , len ( data ) - 10 , urllib . quote ( pkg ) , distro )
2007-02-04 17:35:40 +00:00
return " File %s found in %s " % ( pkg , ' , ' . join ( data ) )
return ' Package/file %s does not exist in %s ' % ( pkg , distro )
return " No packages matching ' %s ' could be found " % pkg
pkgs = [ x . split ( ) [ 0 ] for x in data . split ( ' \n ' ) ]
2010-09-04 15:19:46 +00:00
if len ( pkgs ) > 10 :
return " Found: %s (and %d others) http://packages.ubuntu.com/search?keywords= %s &searchon=names&suite= %s §ion=all " % ( ' , ' . join ( pkgs [ : 10 ] ) , len ( pkgs ) - 10 , urllib . quote ( pkg ) , distro )
2007-02-04 17:35:40 +00:00
else :
return " Found: %s " % ' , ' . join ( pkgs [ : 5 ] )
2010-05-24 13:38:06 +00:00
def info ( self , pkg , chkdistro ) :
2009-10-12 18:26:35 +00:00
if not pkg . strip ( ) :
return ' '
2007-02-04 17:35:40 +00:00
_pkg = ' ' . join ( [ x for x in pkg . strip ( ) . split ( None , 1 ) [ 0 ] if x . isalnum ( ) or x in ' .-_+ ' ] )
2010-11-19 14:11:23 +00:00
distro = chkdistro
2007-02-04 17:35:40 +00:00
if len ( pkg . strip ( ) . split ( ) ) > 1 :
distro = ' ' . join ( [ x for x in pkg . strip ( ) . split ( None , 2 ) [ 1 ] if x . isalnum ( ) or x in ' -._+ ' ] )
2008-10-22 17:31:40 +00:00
if distro not in self . distros :
2009-10-12 18:26:35 +00:00
return " %r is not a valid distribution: %s " % ( distro , " , " . join ( self . distros ) )
2008-10-22 17:31:40 +00:00
2007-02-04 17:35:40 +00:00
pkg = _pkg
2012-04-10 23:48:30 +00:00
data = commands . getoutput ( self . aptcommand % ( distro , distro , distro , distro , ' show ' , pkg ) )
data2 = commands . getoutput ( self . aptcommand % ( distro , distro , distro , distro , ' showsrc ' , pkg ) )
2010-05-24 13:38:06 +00:00
if not data or ' E: No packages found ' in data :
return ' Package %s does not exist in %s ' % ( pkg , distro )
maxp = { ' Version ' : ' 0 ' }
packages = [ x . strip ( ) for x in data . split ( ' \n \n ' ) ]
for p in packages :
if not p . strip ( ) :
continue
parser = FeedParser . FeedParser ( )
parser . feed ( p )
p = parser . close ( )
if type ( p ) == type ( " " ) :
self . log . error ( " PackageInfo/packages: apt returned an error, do you have the deb-src URLs in %s .list? " % distro )
return " Package lookup faild "
if not p . get ( " Version " , None ) :
continue
if apt . VersionCompare ( maxp [ ' Version ' ] , p [ ' Version ' ] ) < 0 :
maxp = p
del parser
maxp2 = { ' Version ' : ' 0 ' }
packages2 = [ x . strip ( ) for x in data2 . split ( ' \n \n ' ) ]
for p in packages2 :
if not p . strip ( ) :
continue
parser = FeedParser . FeedParser ( )
parser . feed ( p )
p = parser . close ( )
if type ( p ) == type ( " " ) :
self . log . error ( " PackageInfo/packages: apt returned an error, do you have the deb-src URLs in %s .list? " % distro )
return " Package lookup faild "
if not p [ ' Version ' ] :
2007-02-04 17:35:40 +00:00
continue
2010-05-24 13:38:06 +00:00
if apt . VersionCompare ( maxp2 [ ' Version ' ] , p [ ' Version ' ] ) < 0 :
maxp2 = p
del parser
archs = ' '
if maxp2 . has_key ( ' Architecture ' ) :
2012-04-10 13:05:29 +00:00
archs = [ _ . strip ( ) for _ in maxp2 [ ' Architecture ' ] . split ( ) if _ . strip ( ) ]
for arch in archs :
if arch not in ( ' any ' , ' all ' ) :
continue
else :
archs = ' '
break
if archs :
archs = ' (Only available for %s ) ' % ' ; ' . join ( archs )
2010-05-24 13:38:06 +00:00
maxp [ " Distrobution " ] = distro
return ( " %s (source: %s ): %s . In component %s , is %s . Version %s ( %s ), package size %s kB, installed size %s kB %s " %
2012-04-10 23:48:30 +00:00
( maxp [ ' Package ' ] , maxp [ ' Source ' ] or maxp [ ' Package ' ] , description ( maxp ) , component ( maxp [ ' Section ' ] ) ,
2010-05-24 13:38:06 +00:00
maxp [ ' Priority ' ] , maxp [ ' Version ' ] , distro , int ( maxp [ ' Size ' ] ) / 1024 , maxp [ ' Installed-Size ' ] , archs ) )
2007-02-04 17:35:40 +00:00
2009-10-12 18:26:35 +00:00
# Simple test
if __name__ == " __main__ " :
import sys
argv = sys . argv
argc = len ( argv )
if argc == 1 :
print " Need at least one arg "
sys . exit ( 1 )
if argc > 3 :
print " Only takes 2 args "
sys . exit ( 1 )
class FakePlugin :
class FakeLog :
def error ( * args , * * kwargs ) :
pass
def __init__ ( self ) :
self . log = self . FakeLog ( )
def registryValue ( self , * args , * * kwargs ) :
2010-04-13 01:12:54 +00:00
return " /home/bot/aptdir "
2009-10-12 18:26:35 +00:00
command = argv [ 1 ] . split ( None , 1 ) [ 0 ]
try :
lookup = argv [ 1 ] . split ( None , 1 ) [ 1 ]
except :
print " Need something to lookup "
sys . exit ( 1 )
dists = " hardy "
if argc == 3 :
dists = argv [ 2 ]
plugin = FakePlugin ( )
aptlookup = Apt ( plugin )
if command == " find " :
print aptlookup . find ( lookup , dists )
else :
print aptlookup . info ( lookup , dists )