#!/usr/bin/python # Written by Alec Warner (warnera6@egr.msu.edu) # 4-22-05 # Distributed under the terms of the GNU General Public License v2 # I hereby also place this work in the Public Domain. # GPL v2 is required per the module section of the GPL see below. # http://www.gnu.org/licenses/gpl-faq.html#GPLModuleLicense import sys sys.path.insert( 0,"/usr/lib/portage/pym" ) import portage import os class fakefile: def __init__(self,file): self.found = "0" self.name = file cmdline = sys.argv[1:] SCAN = "1" DEL = "0" RECURSE = "1" FORCE = "0" QUIET = "0" dirs = [] for arg in cmdline: if "--remove" in arg: DEL = "1" SCAN = "0" elif "--scan" in arg: SCAN = "1" elif "--recurse" in arg: RECURSE = "1" elif "--force" in arg: FORCE = "1" elif "--quiet" in arg: QUIET = "1" elif "--help" in arg: print "Usage: localpurge.py [--scan] [--remove] [--recurse] {dir1...dir2...dirN..}" print "--scan will only print orphaned files, --remove will delete them." print "--scan is set by default, but if you want it to print orphaned files and remove them specify" print "'--remove --scan'" print "--force will not prompt for deletions." print "--quiet will give no output for progress." print "--recurse will make the script run recursively from all directories specified." print "This script when run as root with --remove --recurse on / has HIGH potential to completely destroy" print "your Gentoo system. Please Please PLEASE use caution when using this to purge old files. Not all" print "files that are essential to your system are owned by packages in portage. These files will also be" print "purged by this script." sys.exit(0) else: #Directories should end in "/" if arg[-1:] != "/": arg += "/" dirs.append(arg) # We only need this once :) # This pulls all installed pkgs out of the db try: if QUIET == "0": print "Fetching a package set..." InstalledPkgs = portage.db["/"]["vartree"].dbapi.cpv_all() except: print "Fatal Portage Error." sys.exit(1) filelist = [] # For each directory specified if RECURSE == "1": for directory in dirs: for root, dirs, files in os.walk( directory, topdown=False ): for file in files: if os.path.isfile( os.path.join( root, file ) ): filelist.append( fakefile( os.path.join( root, file ) ) ) elif RECURSE == "0": for directory in dirs: try: os.chdir(directory) files = os.listdir(".") except: print "Cannot chdir to " + directory + " or permissions are incorrect." #A hack to get a found = true/false attribute for file in files: if os.path.isfile( directory + file ): filelist.append( fakefile(directory + file) ) # elif os.path.isdir( directory + file ): # print "Directory : " + directory + file + " skipped." for pkg in InstalledPkgs: mysplit = pkg.split("/") #cnt is a list of all installed files relating to pkg try: cnt = portage.dblink(mysplit[0], mysplit[1], "/", portage.settings).getcontents() except: print "Fatal Portage Error." sys.exit(2) if not cnt: pass if QUIET == "0": sys.stdout.write(".") sys.stdout.flush() # if pkg owns any files in the directory, found = 1 for file in filelist: if file.name in cnt.keys(): file.found = "1" # if no pkg owns a file in directory, print/delete it if QUIET == "0": print for file in filelist: if file.found == "0": if SCAN == "1": print "The file " + file.name + " has been orphaned." if DEL == "1": if FORCE =="0": print "Delete: " + file.name + "(Y/N)? ", sys.stdout.flush() input = sys.stdin.read(2) # sys.stdout.write("\n") # sys.stdout.flush() if "Y" in input: print "Deleting " + file.name + "." try: os.remove( file.name ) except: print "Could not rm " + file.name + "." else: print "Deleting " + file.name + "." try: os.remove( file.name ) except: print "Could not rm " + file.name + "."