#!/usr/bin/env python # Command-line frontend for GARStow # Copyright 2003, 2004, 2005 Adam Sampson from garstowlib import * import sys, stat, random def remove_old(args = []): if len(args) != 0: die("usage: garstow remove-old") dirs = {} for (name, st) in list_packagesdir().items(): if stat.S_ISDIR(st.st_mode): dirs[name] = 1 installed = get_installed() for name in installed.values(): del dirs[name] for name in dirs.keys(): print "Removing: " + name rc = run_command(["rm", "-rf", get_packages_dir() + "/" + name]) if rc != 0: die("rm failed") def all_clean(args): if len(args) != 0: die("usage: garstow all-clean") for n in get_package_names().keys(): d = get_package_dir(n) to_clean = ["work", "cookies"] for x in to_clean: if os.access(d + "/" + x, os.F_OK): make_operation(n, "clean") break def show(args): if len(args) != 1: die("usage: garstow show ") package = args[0] print "Package: " + package print "Package version: " + get_version(package) iv = get_installed_version(package) if iv is None: print "Installed version: none" else: print "Installed version: " + iv print "Full name: " + get_package_names()[package] print "Description: " + get_description(package) print "Requires: " + (" ".join(get_dependencies(package))) print "Requires indirectly: " + (" ".join(get_deps_rec(package))) print "Required by: " + (" ".join(get_requirements(package))) print "Required indirectly by: " + (" ".join(get_reqs_rec(package))) def list(args): if len(args) != 0: die("usage: garstow list") pns = get_package_names() ips = get_installed() ps = ips.keys() ps.sort() dead = [] for p in ps: if p in pns: print ips[p] + ": " + get_description(p) else: dead.append(p) if dead != []: for p in dead: print p + ": port no longer exists" def install(args): if len(args) == 0: die("usage: garstow install ...") ips = get_installed() to_install = {} for p in args: if ips.has_key(p): print p + " is already installed." continue to_install[p] = 1 deps = get_deps_rec(p) for d in deps: if not (ips.has_key(d) or to_install.has_key(d)): to_install[d] = 1 ins = to_install.keys() ins.sort(cmp_install) print "Will install: " + (" ".join(ins)) for p in ins: print "Installing " + p + "..." make_operation(p, "install") print "Done." def remove(args): if len(args) == 0: die("usage: garstow remove ...") args.sort(cmp_remove) ips = get_installed() for p in args: if not ips.has_key(p): print p + " is not installed." continue reqs = get_reqs_rec(p) blockers = intersection(ips.keys(), reqs) if len(blockers) != 0: die("Cannot remove " + p + " since depending packages are still installed: " + (" ".join(blockers))) print "Removing " + p + "..." make_operation(p, "unstow") make_operation(p, "clean") del ips[p] print "Done." def depgraph(args): deptree = get_dep_tree() if args == []: s = '' else: s = ' from ' + ' '.join(args) showdeps = {} for p in args: showdeps[p] = deptree[p] for d in get_deps_rec(p): showdeps[d] = deptree[d] deptree = showdeps # Trim the dependencies so that if x -> y -> z and also x -> z, then # the x -> z dependency is dropped. depd = {} cats = {} cat_colours = {} for (p, deps) in deptree.items(): depd[p] = {} for d in get_deps_rec(p): depd[p][d] = 1 cats[p] = get_categories(p)[0] cat_colours[cats[p]] = None for (p, deps) in deptree.items(): left = [] for d in deps: found = False for e in deps: if e != d and d in depd[e]: found = True if not found: left.append(d) deptree[p] = left cols = cat_colours.keys() num_cols = len(cols) for i in range(num_cols): cat_colours[cols[i]] = (1.0 / num_cols) * i print 'digraph "garstow deps' + s + '" {' print 'rankdir=LR;' for (p, deps) in deptree.items(): print '"%s" [shape=box,color=black,style=filled,fillcolor="%f,%f,%f"];' % (p, cat_colours[cats[p]], 0.2, 0.8) for d in deps: print '"%s" -> "%s" [color="%f,%f,%f"];' % (p, d, random.random(), 1.0, 0.5) print '}' def upgrade(args): if len(args) != 0: die("usage: garstow upgrade") inst = {} ips = get_installed() for p, vp in ips.items(): if not p in get_package_names(): print p + ": no longer exists; you should remove it" continue if p in get_ignore_list(): print p + ": installed but is in IGNORE_DEPS; ignoring" continue if get_version(p) != get_installed_version(p): print p + ": out of date, will upgrade" inst[p] = True for dp in recursive_deps(p, True): if (dp not in ips) and (dp not in inst): print dp + ": needed by " + p + ", will install" to_install = inst.keys() to_install.sort(cmp_install) for p in to_install: print "Installing " + p + "..." make_operation(p, "clean") make_operation(p, "install") def config(args): print '''gar_dir="''' + gar_dir + '''" stow_dir="''' + get_stow_dir() + '''" packages_dir="''' + get_packages_dir() + '''"''' commands = { "remove-old" : remove_old, "all-clean" : all_clean, "show" : show, "list" : list, "install" : install, "remove" : remove, "depgraph" : depgraph, "upgrade" : upgrade, "config" : config, } if __name__ == "__main__": if len(sys.argv) < 2: die("usage: garstow (" + ("|".join(commands.keys())) + ") ...") cmd = sys.argv[1] args = sys.argv[2:] if not commands.has_key(cmd): die("unknown command") commands[cmd](args)