#!/usr/bin/env python # For each given packageprefix, remove the files in the tree that it would # collide with. This is useful if you're replacing a large port incrementally # with smaller ones, or if you need to remove a port that's accidentally # installed straight into the tree rather than the packageprefix. from garstowlib import * import os, sys, stat, re, fnmatch def package_of(path): packagesdir = get_packages_dir() return re.sub(r'/.*$', r'', path[len(packagesdir) + 1:]) lib_portfile = Portfile(gar_dir + "/gar.lib.mk") def is_exception(path): packagesdir = get_packages_dir() end = re.sub(r'^[^/]*/', r'', path[len(packagesdir) + 1:]) cols = re.split(r'\s+', lib_portfile.variable("COLLISIONS")) for col in cols: if fnmatch.filter([end], col) != []: return True return False def deconflict(pp, package, allow): prefix = get_stow_dir() packagesdir = get_packages_dir() f = os.popen("find " + pp + " -not -type d", "r") for l in f.readlines(): l = l[:-1] if not l.startswith(pp): die("Bad thing found: " + l) l = get_stow_dir() + l[len(pp):] try: os.lstat(l) except OSError: # File doesn't exist. continue link = l while 1: is_link = stat.S_ISLNK(os.lstat(link).st_mode) if is_link: rl = norm_readlink(link) if is_link and rl.startswith(packagesdir): realpath = rl + l[len(link):] conf_package = package_of(realpath) if conf_package != package: if conf_package not in allow and not is_exception(realpath): die("Trying to remove file from non-allowed package " + conf_package + ": " + realpath) print "Removing packaged file in package " + conf_package + ": " + realpath os.unlink(realpath) if link == l: print "Removing link: " + l os.unlink(l) break link = os.path.dirname(link) if link == prefix: print "Removing unstowed file: " + l os.unlink(l) break f.close() if __name__ == "__main__": if len(sys.argv) < 3: die("Usage: force-deconflict packageprefix package [allow-removal-from-package ...]") pp = sys.argv[1] package = sys.argv[2] allow = sys.argv[3:] if pp.endswith("/"): pp = pp[:-1] if not pp.startswith(get_packages_dir()): die(pp + " is not a package dir") deconflict(pp, package, allow)