#!/usr/bin/env python # # FindPackage # Search, chooses an occurence and prints where some package (or recipe) can # be found, based only on the program name (case insesitive) or on the # program name and program version. # # (C) 2004 Andre Detsch. Released under the GNU GPL. import os, os.path, sys, urllib from GetAvailable import * def FindPackage(p, v=None, r=None, fulllist=False, substring=False, types=None, localdirs=None, forceupdate=False, accessWeb=True, hook=None, availables=None, goboPrograms=None): if not types: types = getGoboVariable('defaultRepositories', 'Scripts/FindPackage.conf', True) if not types: types=['local_package', 'official_package'] ####################################################################### # Phase 1: Get available packages from the selected type(s) ####################################################################### if not availables or forceupdate: # can be used as a cache availables = GetAvailable(types, localdirs, forceupdate=forceupdate, accessWeb=accessWeb, hook=hook, goboPrograms=goboPrograms) ####################################################################### # Phase 2: From returned structure, decide which items fit (based on p, v and r) ####################################################################### relevant_items = [] for t in types: if not t in availables.keys(): continue matched_programs = [] # programs that match for pname in availables[t]['programs'].keys(): if substring: if pname.lower().find(p.lower()) > -1: matched_programs.append(pname) else: if pname.lower() == p.lower(): matched_programs.append(pname) break d = availables[t]['programs'] for mp in matched_programs : if v: if d[mp].has_key(v): if r: if d[mp][v].has_key(r): for u in d[mp][v][r]: relevant_items.append((mp,v,r,t,u)) else: for fr in d[mp][v]: for u in d[mp][v][fr]: relevant_items.append((mp,v,fr,t,u)) else: for fv in d[mp].keys(): for fr in d[mp][fv]: for u in d[mp][fv][fr]: relevant_items.append((mp,fv,fr,t,u)) ################################################################################# # Phase 3: Prepare the output, sorting if required ################################################################################# del availables # Documentation: only the 'relevant_items' are used from now on if v and r: if fulllist: return relevant_items else: return relevant_items[0:1] else: from GuessLatest import GuessLatest found_versions_revisions = [ (i[1]+'-'+i[2]).strip('-') for i in relevant_items ] toReturn = [] while relevant_items: latest = GuessLatest(found_versions_revisions) selected = [ i for i in relevant_items if (i[1]+'-'+i[2]).strip('-') == latest ][0] toReturn.append(selected) if not fulllist: break relevant_items.remove(selected) found_versions_revisions.remove(latest) return toReturn # Proposed addition to FindPackage: # Figure out which is the newest package by checking the date each was # modified on the server datehash = {} hook = None returnedResults = 0 def byNewestOnServer(x, y): for i in (x, y): if datehash.has_key(i): continue try: if i[3][0] == '/': datehash[i] = os.path.getmtime(i[3]) else: u = urllib.urlopen(i[3]) datehash[i] = time.mktime(u.headers.getdate('Last-Modified')) except: Log_Terse("Failed to get date for %s."% i[3]) datehash[i] = '\1' if hook: hook('Sorting by date', len(datehash), returnedResults, False) return cmp(datehash[y], datehash[x]) if __name__ == '__main__': import sys import getopt, os try: if not sys.argv[1:]: sys.argv[1:] = [ '--help' ] opts, args = getopt.gnu_getopt(sys.argv, 't:Wslhnp:', ['types=', 'type=', 'local-dirs=', 'full-list', 'force-update', 'substring', 'no-web', 'help', 'newest-on-server', 'gobo-programs=']) except getopt.GetoptError, detail: print sys.argv[0].split('/')[-1]+': '+str(detail) sys.exit(1) validTypes = ['installed', 'current', 'local_package', 'official_package', 'recipe', 'contrib_package', 'tracked', 'all'] types = None localdirs = None fulllist = False forceupdate = False substring = False noWeb = False newestOnServer = False goboPrograms = None for o, a in opts: if o in ['--types','--type', '-t']: #typesChanged = True types = a.split(',') for i in range(len(types)): if len (types[i]) == 1: for t in validTypes: if types[i][0] == t[0]: types[i] = t break if 'all' in types: types = validTypes[:-1] # don't include 'all' if o == '--local-dirs': localdirs = a.split(',') elif o in ['--full-list', '-l']: fulllist = True elif o == '--force-update': forceupdate = True elif o in ['-n', '--newest-on-server']: fulllist = True newestOnServer = True elif o in ['--substring','-s']: substring = True elif o in ['--gobo-programs', '-p']: goboPrograms = a elif o in ['--no-web', '-W']: noWeb = True if not types: types = [ 'local_package' ] elif o in ['--help', '-h']: print """ FindPackage Searches, chooses an occurence and prints where some package (or recipe) can be found, based only on the program name (case insesitive) or on the program name and program version. Options: -t [t1,t2,...] --types=[t1,t2,...] Sets what kind of packages can be searched, in the passed order. Valid types are: local_package, official_package, contrib_package, installed, recipe, tracked, all Using only the first character from any of the above is also valid: l, o, c, i, r, t, a Default types are: local_package, official_package Notice that when "recipe" type is used, Compile.conf is read to set recipe-store locations and local recipes locations. --local-dirs=[d1,..] Where to look for local binary packages. By default, uses the paths defined at GetAvailable.conf. --force-update Downloads required packages list even if there is a local copy (cached in """+getGoboVariable("goboTemp")+"""/Scripts-"""+os.getenv('USER')+"""/cache/) newer than one hour. -l, --full-list Prints all the occurences that match the passed parameters, not only the "best". -n, --newest-on-server Tries to sort the result set by how recently the packages have been modified on the server. Automatically enables '--full-list'. -s, --substring Match packages whose names contains the passed substring. -W, --no-web Do not try to download anything and don't lists remote recipes and packages (if not explicitly listed in '--types='). Overrides '--force-update' and '--newest-on-server'. -p --gobo-programs Override default """+getGoboVariable("goboPrograms")+""" as path of installed packages Examples of usage: FindPackage kde FindPackage kde 3.2.3 FindPackage KDE 3.2.3 FindPackage --types=recipe kde 3.2.3 FindPackage --types=local_package,official_package kde 3.2.3 FindPackage -t l,o kde 3.2.3 FindPackage --full-list kde 3.2.3 FindPackage --force-update --full-list kde 3.2.3 FindPackage --types=recipe kde-base 3.2.3 FindPackage --types=recipe --substring kd 3.2.3 FindPackage --types=installed gcc """ sys.exit(0) if len (args) >= 2: p = args[1] else: sys.exit(1) if len (args) >= 3: v,r = Split_Version_Revision(args[2]) else : v = '' r = '' if newestOnServer and noWeb: Log_Error("--newest-on-server overridden by --no-web") newestOnServer = False try: import os.path if not os.path.realpath('/dev/fd/1').find('/fd/pipe:') > 0: hook = consoleProgressHook pass except: pass returned = FindPackage(p, v, r, fulllist or substring, substring, types, localdirs, forceupdate, accessWeb=not noWeb, hook=hook, goboPrograms=goboPrograms) if returned: if newestOnServer: returnedResults = len(returned) returned.sort(byNewestOnServer) if (substring and not fulllist): listed_programs = [] for rp, rv, rr, rt, site in returned: if (substring and not fulllist): if rp in listed_programs: continue else: listed_programs.append(rp) print site sys.exit(0) else: sys.exit(1)