#!/usr/bin/python -O # # $Header: $ # Authors: # Eldad Zack - Original application # Robin H. Johnson - SLOT and masking support # # earch: Gentoo last arch keyword checking tool, with SLOT and masking support # version 0.6 import sys import os import re import string import readline import getopt from output import * # we import portage later sys.path.insert(0, "/usr/lib/portage/pym") version = '0.7' def earch_main(): # force to false opt_masking_reasons = False opt_hide_masked = False opt_category = False opt_help = False opt_remove_pkgs = False opt_ignore_redundant = False opt_follow_etc_portage = False opt_version = False opt_slot = [] # process commandline try: (opts,args) = getopt.gnu_getopt(sys.argv[1:],'cfhHims:rv',['category','masking-reasons','help','hide-masked','version','slot=','remove-pkgs','ignore-redundant','follow-etc-portage']) for optkey,optvalue in opts: if optkey == '-c' or optkey == '--category': opt_category = True if optkey == '-f' or optkey == '--follow-etc-portage': opt_follow_etc_portage = True if optkey == '-m' or optkey == '--masking-reasons': opt_masking_reasons = True if optkey == '-h' or optkey == '--help': opt_help = True if optkey == '-H' or optkey == '--hide-masked': opt_hide_masked = True if optkey == '-i' or optkey == '--ignore-redundant': opt_ignore_redundant = True if optkey == '-r' or optkey == '--remove-pkgs': opt_remove_pkgs = True if optkey == '-s' or optkey == '--slot': opt_slot = re.split(',',optvalue) if optkey == '-v' or optkey == '--version': opt_version = True except getopt.GetoptError: opt_help = True # don't hide masked packages if we are printing reasons if opt_masking_reasons: opt_hide_masked = False # do help if opt_help: earch_help() return # version output if opt_version: earch_version() return if not opt_follow_etc_portage: # this is a cheat to get portage to ignore local user profiles # it must come before the portage module is imported os.environ["PORTAGE_CALLER"]="repoman" # generate (ebuildlist,ebuilddata,pkgkeywords) = earch_data_generate(args,slots=opt_slot,hide_masked=opt_hide_masked,include_category=opt_category,ignore_redundant=opt_ignore_redundant) if opt_remove_pkgs: earch_remove_pkgs(ebuildlist,ebuilddata,pkgkeywords) return earch_data_output(ebuildlist,ebuilddata,pkgkeywords,show_masking_reason=opt_masking_reasons) def earch_version(): print 'earch %s' % (version) def earch_help(): earch_version #'chHmrs:v',['category','masking-reasons','help','hide-masked','version','slot=','remove-pkgs']) print 'Gentoo last arch keyword checking tool, with SLOT and masking support' print print 'Usage:' print 'earch [opts] [CP]' print 'If CP is omitted, the current directory is used.' print print 'Options:' print '-c|--category' print ' Include category in output.' print print '-f|--follow-etc-portage' print ' By default, earch acts like repoman and ignores /etc/portage.' print ' This option disables that behavior.' print print '-h|--help' print ' This help page.' print print '-H|--hide-masked' print ' Exclude all masked versions from output.' print print '-i|--ignore-redundant' print ' Exclude redudant versions from keyword output.' print ' Redundant versions are those output by -r.' print print '-m|--masking-reason' print ' For all masked versions, print masking reason. ' print ' Disables other output.' print print '-r|--remove-pkgs' print ' Show all redundant versions to clean from the tree.' print print '-s|--slot ' print ' SLOT values to provide output for, seperated by commas.' print print '-v|--version' print ' earch version output.' print print 'Explaination of output:' print '# earch [$CATEGORY/$PN]' print '$PF[$SLOT]: $KEYWORDS' print 'If a specific version is masked, a (M) will preceed the keywords.' def earch_data_generate(args,slots=[],hide_masked=False,include_category=False,ignore_redundant=False): import portage portdir = portage.settings["PORTDIR"] portdb = portage.portdbapi(portdir) archslotdict = {} ebuildlist = [] ebuilddata = {} pkgkeywords = {} if len(args) < 1: workdir = "." else: workdir = portdir + "/" + args[0] try: os.chdir(workdir) except: print red("!!!" + " Can't find " + workdir) sys.exit(1) cp_path = os.path.abspath(workdir) cp = re.sub(portdir+'/?','', cp_path, count=1) #print cp cat = re.split('/',cp)[0] #print c for file in os.listdir(workdir): if re.search("\.ebuild$",file): s = re.split("\.ebuild$",file)[0] ebuildlist.append(s) ebuildlist.sort(lambda x,y: portage.pkgcmp(portage.pkgsplit(x),portage.pkgsplit(y))) ebuildlist2 = [] for pkg in ebuildlist: cpv = cat+'/'+pkg aux = portdb.aux_get(cpv,['SLOT','KEYWORDS']) slot = aux[0] keywords = re.split(' ',aux[1]) masking = portage.getmaskingstatus(cpv) is_masked = len(masking) > 0 if hide_masked and is_masked: continue if len(slots) > 0 and not slot in slots: continue if include_category: pkg = cpv ebuildlist2.append(pkg) # store this for usage later ebuilddata[pkg] = {'SLOT':slot, 'KEYWORDS':keywords, 'MASKING':masking} ebuildlist = ebuildlist2 for pkg in ebuildlist: slot = ebuilddata[pkg]['SLOT'] keywords = ebuilddata[pkg]['KEYWORDS'] pkgkeywords[pkg] = {} # ensure the second level tree exists try: archslotdict[slot] except KeyError: archslotdict[slot] = {} # now actually populate the second level tree if len(masking) > 0: prefix = 'M/' else: prefix = '' for arch in keywords: archslotdict[slot][prefix+arch] = pkg for pkg in ebuildlist: slot = ebuilddata[pkg]['SLOT'] masking = ebuilddata[pkg]['MASKING'] for value,key in archslotdict[slot].iteritems(): #value = re.sub('M/','',value) if (key == pkg): pkgkeywords[pkg][value] = True if ignore_redundant: ebuildlist2 = [] for pkg in ebuildlist: if len(pkgkeywords[pkg]) > 0: ebuildlist2.append(pkg) ebuildlist = ebuildlist2 return (ebuildlist,ebuilddata,pkgkeywords) def earch_remove_pkgs(ebuildlist,ebuilddata,pkgkeywords): for pkg in pkgkeywords.keys(): if len(pkgkeywords[pkg]) == 0: print pkg def earch_data_output(ebuildlist,ebuilddata,pkgkeywords,show_masking_reason=False): import portage # disable color as needed if (not sys.stdout.isatty()) or (portage.settings["NOCOLOR"] in ["yes","true","1"]): nocolor() for pkg in ebuildlist: slot = ebuilddata[pkg]['SLOT'] masking = ebuilddata[pkg]['MASKING'] is_masked = len(masking) > 0 if is_masked: m = red(' (M)') else: m = '' print '%s[%s]:%s'%(white(pkg),yellow(slot),m), # print masking reason only if show_masking_reason: print '%s' % (string.join(masking,', ')) continue for value in pkgkeywords[pkg]: value = re.sub('M/','',value) if value[0] == '-': print red(value), elif value[0] == '~': print blue(value), else: print green(value), print if __name__ == "__main__": earch_main()