) for the url in the original post. Given the age, I'd expect it to need some adjusting, but I've never used it.
Code: Select all
#!/usr/bin/env python
#
# ------------ pye ---------------------
#
# Let's you choose from a numbered list of packages
# to emerge.
# Thomas Ferencz 2004
# strangedr@gentoo.org
#
import sys, os, popen2, portage, os.path
sys.path = ["/usr/lib/portage/pym"]+sys.path
from output import blue, red, green
from time import localtime, strftime, time
from getopt import *
VERSION = "0.8.4.1"
count = 0
pkgdict = {}
digest = {}
prune = False
info = False
category = False
eopts = False
confpath = os.path.expanduser('~')+"/.pye/pye.conf"
versionrequest = False
masked = False
def parse_pyeconf(mypath):
"""Parse $HOME/.pye/pye.conf if exists"""
if os.path.isfile(mypath):
confvar = True
conf = open(mypath, 'r')
for line in conf.readlines():
if "EMERGEOPTS" in line:
line = line.split("=")[1]
optsvar = "-"+line.strip()
if "SILENT" in line:
if "yes" in line:
silentvar = True
else:
silentvar = False
if "MASKFILE_ETC_PORTAGE_PACKAGEMASK" in line:
if "yes" in line:
maskfilevar = "/etc/portage/package.mask"
else:
maskfilevar = os.path.expanduser("~")+"/.pye/pye.mask"
conf.close()
return confvar, optsvar, silentvar, maskfilevar
def parsethis(be):
"""Extract cat/packagename out of emerge -p output"""
a = be.find("]")+2
newbe = be[a:]
newbe = newbe.lstrip()
b = newbe.find("[")
if b == -1:
b = newbe.find(" ")
if b == -1:
b = newbe.find("\n")
newbe = newbe[:b]
newestbe = newbe.strip()
ki = portage.catpkgsplit(newestbe)
if ki == None:
ki = newestbe.split('/')
return ki
def mergethis(package):
"""Merge given package and return True if successful."""
os.system("emerge %s" % package)
global pkgdict
package = package.split("/")[1]
vartree = portage.vartree()
installed_pkg = vartree.dep_bestmatch(package)
inst_pkgparts = portage.catpkgsplit(installed_pkg)
pklist = pkgdict.values()
intended_pkg = [value for value in pklist if package == value[1]]
if inst_pkgparts == intended_pkg[0]:
return True
else:
return False
def usage():
"""Invoked by --help or -h in arguments"""
sys.stdout.write("""\nThis script let's you choose from a numbered list of packages to emerge.
Usage: pye [options] [target]
where [target] can be world, system, gnome, kde etc.,
or any specific package or portage category,
and [options] are listed below. --pretend is hardwired.
If no [target] is given, '-puD world' is implied.
Options:
-v or --version prints current version number
-h or --help give you this screen
-e or --emergeopts <options> specify the options you would pass to emerge;
e.g. if you'd call emerge -uvD system, then this option would be -e uvD
If no --emergeopts are given, pye will look for its configfile in
~/.pye/pye.conf, and take --emergeopts from there.
-p or --prune will list all installed packages, from which you can pick the ones
to unmerge (proceed carefully!)
-s or --sync performs an emerge --sync before listing the packages
-i or --info <package> will print all information for <package> from
/var/db/pkg/category/package
-c or --category lists all packages in a category to choose from\n\n""")
sys.exit(0)
def print_choices():
"""Print choices for package selection"""
print
print """You can now enter the numbers of packages you want to emerge/unmerge/exclude.
You have the following possibilities:
* you can simply enter the numbers comma-separated, e.g. 1,3,5,6,8
* you can also specify ranges: 2,4-7,9,11-16
* "a" or "all" merges all packages in the list
* "!" excludes the specified packages (and merges the rest): !4,6-8,13
* "x" excludes _and_ masks them in /etc/portage/package.mask or ~/.pye/pye.mask
* "q" quits pye """
print
def pkginfo(package):
"""List all available info for package from /var/db/pkg"""
basedir = "/var/db/pkg"
vartree = portage.vartree()
actualpkg = vartree.dep_bestmatch(package)
pkgdir = os.path.join(basedir, actualpkg)
if os.path.isdir(pkgdir):
infolist = os.listdir(pkgdir)
printinfo(infolist, pkgdir)
else:
print red("Package not found in /var/db/pkg\n")
def printinfo(mylist, mydir):
"""Print infos for a package"""
for filename in mylist:
if "ebuild" in filename or "environment" in filename:
continue
fullname = os.path.join(mydir, filename)
if not os.path.isfile(fullname):
continue
else:
infofile = open(fullname, 'r')
print green(filename)+":"
print
try:
for line in infofile.readlines():
print blue(line)
infofile.close()
except TypeError:
continue
def getexcludes(mylist, mydict, mymask, mymaskfile):
"""Exclude the given packages from the total and mask them if necessary"""
totallist = mydict.keys()
mylist[0] = mylist[0][1:]
for num in mylist:
if "-" in num:
start, stop = num.split("-")
mylist.remove(num)
for n in range(int(start), int(stop)+1):
mylist.append(str(n))
newlist = [mydict[item][0]+"/"+mydict[item][1] for item in totallist if str(item) not in mylist]
if mymask:
if not os.path.isfile(mymaskfile):
myfile = file(mymaskfile, "w")
else:
myfile = file(mymaskfile, 'a')
for elem in mylist:
elem = mydict[eval(elem)][0]+"/"+mydict[eval(elem)][1]+"\n"
myfile.write(elem)
myfile.close
return newlist
if not os.path.isdir(os.path.expanduser("~")+"/.pye"):
pyedir = os.path.expanduser("~")+"/.pye"
os.mkdir(pyedir)
cfile = file(pyedir+"/pye.conf", "w")
cfile.write("EMERGEOPTS =\n")
cfile.write("SILENT = no\n")
cfile.write("MASKFILE_ETC_PORTAGE_PACKAGEMASK = no")
cfile.close()
mfile = pyedir+"/pye.mask"
os.system("touch %s" % mfile)
conf, defaultopts, silent, maskfile = parse_pyeconf(confpath)
try:
opts, args = getopt(sys.argv[1:], "hve:psic", ["help", "version", "emergeopts=", "prune", "sync", "info", "category"])
except GetoptError, error:
print red("That's a no-no: "), error, blue("try pye -h or pye --help to see your options")
print
sys.exit(1)
if len(opts) == 0 and len(args) == 0:
emergeopts = "uD"
args = "world"
for opt, arg in opts:
if opt in ("-h", "--help"):
usage()
if opt in ("-v", "--version"):
versionrequest = True
if opt in ("-s", "--sync"):
syncarg = "--sync"
os.system("emerge %s" % syncarg)
sys.stdout.write(blue("\nFinished syncing, now listing packages:\n"))
if opt in ("-p", "--prune"):
prune = True
if opt in ("-e", "--emergeopts"):
eopts = True
emergeopts = "-"+arg
if opt in ("-i", "--info"):
info = True
if opt in ("-c", "--category"):
category = True
emergeopts = "-s"
if info:
if len(args) == 0 or "world" in args or "system" in args:
print red("You must specify a package with --info")
sys.exit(1)
else:
pkg = args[0]
pkginfo(pkg)
sys.exit(0)
if category:
if len(args) == 0 or "world" in args or "system" in args:
print red("You must specify a valid portage category [foo-bar/foo] with --category")
sys.exit(1)
else:
args[0] = "@"+args[0]
if versionrequest:
sys.stdout.write(green("pick your emerge "+VERSION+"\n"))
sys.exit(0)
if not eopts and conf and not info and not prune and not category:
emergeopts = defaultopts
#print "emergeopts: ", green(emergeopts)
sys.stdout.write(green("One moment...\n"))
if prune:
vartree = portage.vartree()
allpacks = vartree.getallcpv()
for item in allpacks:
line = red(str(count)+'): ')+blue(item)+'\n'
pkgdict[count] = portage.catpkgsplit(item)
count = count+1
sys.stdout.write(line)
else:
(r, w) = popen2.popen4('emerge -p %s %s' % (emergeopts, args[0]))
for line in r.readlines():
if line[:7] == "[blocks":
sys.stdout.write(red(line))
continue
if line[:7] == "[ebuild" or (line[:1] == "*" and "s" in emergeopts):
excludefile = file(os.path.expanduser("~")+"/.pye/pye.mask", "r")
packparts = parsethis(line)
testpack = "/".join(packparts[:2])
for sor in excludefile.readlines():
if testpack in sor:
masked = True
if not masked:
line = blue(str(count))+green("): ")+line
pkgdict[count] = packparts
count = count+1
elif masked:
line = ""
masked = False
sys.stdout.write(line)
r.close()
w.close()
if len(pkgdict) == 0:
print blue("No packages to emerge.\n")
sys.exit(0)
print
yesno = "n"
while yesno == "n":
packstring = ""
packlist=[]
if not silent:
print_choices()
emergethis = raw_input(blue("Enter your choices now: "))
if emergethis == 'q':
sys.exit(0)
elif emergethis in ['a', 'all']:
packlist = [v[0]+"/"+v[1] for v in pkgdict.values()]
else:
packnumlist = emergethis.split(",")
if "!" in packnumlist[0]:
exclude = False
packlist = getexcludes(packnumlist, pkgdict, exclude, maskfile)
elif "x" in packnumlist[0]:
exclude = True
packlist = getexcludes(packnumlist, pkgdict, exclude, maskfile)
else:
for num in packnumlist:
if "-" in num:
start, stop = num.split("-")
for n in range(int(start), int(stop)+1):
packlist.append(pkgdict[n][0]+"/"+pkgdict[n][1])
else:
packlist.append(pkgdict[eval(num)][0]+"/"+pkgdict[eval(num)][1])
packstring = " ".join(packlist)
print
if prune:
sys.stdout.write(green("I'm about to unmerge the following package(s): "))
sys.stdout.write(red(packstring)+'\n')
yesno = raw_input(green("Is this correct? Choose an option: u(nmerge)/n(o)/q(uit): "))
else:
sys.stdout.write(green("I'm about to emerge the following packages: "))
sys.stdout.write(red(packstring)+'\n')
yesno = raw_input(green("Is this correct? Choose an option: e(merge)/n(o)/q(uit): "))
print
if yesno in ['q', 'quit']:
sys.exit(0)
if yesno == 'e':
for elem in packlist:
start = time()
merged = mergethis(elem)
duration = (time() - start) / 60
if merged:
digest[elem] = "Merged in "+str(duration)[:4]+" minutes"
else:
digest[elem] = "Failed"
sys.stdout.write(blue("This is digest of pye on "+strftime("%a, %d %b %Y %H:%M:%S", localtime())+":\n\n"))
for key in digest.keys():
if digest[key] == "Failed":
sys.stdout.write(blue(key+": ")+red(digest[key]+"\n"))
else:
sys.stdout.write(blue(key+": "+digest[key]+"\n"))
sys.stdout.write(green("Check /var/log/emerge for details. Exiting.\n\n"))
sys.exit(0)
elif prune and yesno == 'u':
os.system("emerge unmerge %s" % packstring)
else:
sys.stdout.write(red("No package given... exiting."))
sys.exit(0)