#!/usr/bin/env python import sys, os, string, getopt, fpformat, signal import portage from output import * progname = os.path.basename(sys.argv[0]) pkgdir = portage.settings["PKGDIR"] dbapi = portage.db["/"]["porttree"].dbapi pretend = False quiet = False ask = False accept_all = False binpkgs = {} def exitsig(signum, frame): sys.exit(128+signum) signal.signal(signal.SIGINT, exitsig) def visit(spam, dir, filelist): global pkg_list if dir[-3:] == 'All': return for file in filelist: if not file[-5:] == ".tbz2": continue path = os.path.join(dir, file) category = os.path.split(dir)[-1] cpv = category+"/"+file[:-5] binpkgs[cpv] = [path] if os.path.islink(path): binpkgs[cpv].append(os.path.realpath(path)) def usage(out): print >>out, "Usage:", progname, "[option]..." print >>out, "Available options:" print >>out, "-a, --ask ask confirmation before deleting files" print >>out, "-h, --help display this short help message" print >>out, "-p, --pretend display files names, but don't actually delete them" print >>out, "-q, --quiet be as quiet as possible" def prettysize(size,pretty=False): units = [" G"," M"," K"] size = size / 1024. while len(units) and size > 1024: size = size / 1024. units.pop() sizestr = fpformat.fix(size,2)+units[-1] if pretty: sizestr = blue("[ ")+" "*(8-len(sizestr))+green(sizestr)+blue(" ]") return sizestr def ask_prompt(): import tty, termios fd = sys.stdin.fileno() origtty = termios.tcgetattr(fd) ch='x' try: tty.setcbreak(fd) while not string.lower(ch) in 'yna': sys.stdout.write("Do you want to delete this package (n/y/a): ") sys.stdout.flush() ch = sys.stdin.read(1) sys.stdout.write(ch) finally: sys.stdout.write('\n') sys.stdout.flush() termios.tcsetattr(fd, termios.TCSADRAIN, origtty) if string.lower(ch) == 'a': global accept_all accept_all = True myanswer = (string.lower(ch) in 'ya') return myanswer try: opts, args = getopt.getopt(sys.argv[1:], "ahpq", ["ask", "help", "pretend", "quiet"]) except getopt.GetoptError: usage(sys.stderr) sys.exit(2) for o, a in opts: if o in ("-h", "--help"): usage(sys.stdout) sys.exit(0) if o in ("-a", "--ask") and not pretend: ask = True if o in ("-p", "--pretend"): pretend = True ask = False if o in ("-q", "--quiet"): quiet = True if not pretend and portage.secpass != 2: print >>sys.stderr, "Permission denied: you must be root to actually delete some binary packages." sys.exit(1) if not quiet: print " "+green("*"),"Building file list..." os.path.walk(pkgdir, visit, None) for mycpv in binpkgs.keys(): if dbapi.cpv_exists(mycpv): del binpkgs[mycpv] mykeys = binpkgs.keys() mykeys.sort() if len(mykeys): if pretend and not quiet: print " "+green("*"),"Here are binary packages that would be deleted:" elif not quiet: print " "+green("*"),"Cleaning binary packages..." else: if not quiet: print " "+green("*"),"Your packages directory was already clean." sys.exit(0) totalsize = 0 for mycpv in mykeys: print binpkgs[mycpv] cpvsize = 0 for file in binpkgs[mycpv]: if os.path.islink(file): continue try: cpvsize += os.path.getsize(file) except: pass if not cpvsize == 0 and (pretend or ask): if quiet: print file else: print prettysize(cpvsize,True)," "+teal(mycpv) if pretend: totalsize += cpvsize elif cpvsize == 0 or not ask or accept_all or ask_prompt(): for file in binpkgs[mycpv]: filesize = 0 if not os.path.exists(file): continue if not os.path.islink(file): try: filesize = os.path.getsize(file) except: pass try: os.unlink(file) except: print >>sys.stderr, "Could not remove", file else: totalsize += filesize if not quiet: if pretend: print " "+green("*"),"Total space that would be freed:",red(prettysize(totalsize)) else: print " "+green("*"),"Total space that has been freed:",red(prettysize(totalsize)) if not pretend: if not quiet: print " "+green("*"),"Cleaning empty directories if any..." for root, dirs, files in os.walk(pkgdir): for name in dirs: try: os.rmdir(os.path.join(root,name)) except: pass sys.exit(0)