#!/usr/bin/env python import os, sys, re, getopt from garstowlib import * hide_library_deps = ["gcc", "openssl096", "openssl097", "openldap2.2", "libtool"] ignore_packages = ["compatlibs"] def get_library_deps(package): prefix = get_stow_dir() installed = get_installed() if not package in installed: print "Package " + package + " is not installed" return [] deps = {} os.chdir(get_packages_dir() + "/" + installed[package]) ff = os.popen("find * -type f -and \( -path 'bin/*' -or -path 'sbin/*' -or -path 'libexec/*' -or -name '*.so*' -or -name '*.pd_*' \) -print 2>/dev/null", "r") for l in ff.readlines(): l = l[:-1] lf = os.popen("ldd " + l + " 2>&1", "r") for ll in lf.readlines(): ll = ll[:-1] for m in re.findall(prefix + r'/\S+', ll): dep = get_owning_package(m) if dep != package and dep not in ignore_packages: deps[dep] = True lf.close() ff.close() return deps.keys() def show_library_deps(package): current_deps = get_deps_rec(package) lib_deps = get_library_deps(package) pns = get_package_names() print pns[package] + " uses (maybe indirectly):" for dep in union(current_deps, lib_deps): if dep in current_deps: s = "" elif dep in lib_deps: s = " (missing)" else: s = " (not shared lib dep)" print " " + pns[dep] + s def check_library_deps(package, checked = {}, stack = [], verbose = 0): if package in checked: return if not package in get_package_names(): if stack == []: s = "" else: s = " (in context " + " -> ".join(stack) + ")" print "Package does not exist: " + package + s return current_deps = get_dependencies(package) if package in stack: # Check to see if we're ignoring any of the packages in the # cycle; if so, this doesn't matter. break_cycle = False for p in stack: if p in hide_library_deps: break_cycle = True if not break_cycle: print "Circular dependency: " + " -> ".join(stack[stack.index(package):] + [package]) checked[package] = current_deps return if verbose > 0: print (" " * len(stack)) + "(checking " + package + ")" lib_deps = get_library_deps(package) all_deps = union(current_deps, lib_deps) all_deps.sort(cmp_install) ignore = {} for dep in current_deps: ignore[dep] = True for dep in all_deps: check_library_deps(dep, checked, stack + [package], verbose) for subdep in checked[dep]: ignore[subdep] = True if verbose > 1 and len(ignore) != 0: print (" " * len(stack)) + "(ignored from " + package + ": " + " ".join(ignore.keys()) + ")" missing = [dep for dep in lib_deps if not ((dep in ignore) or (dep in hide_library_deps))] if missing != []: pns = get_package_names() missing_ns = [pns[dep] for dep in missing] print "Missing LIBDEPS from " + pns[package] + ": " + " ".join(missing_ns) checked[package] = missing + ignore.keys() sys.stdout.flush() if __name__ == "__main__": mode = "check" verbose = 0 (opts, args) = getopt.getopt(sys.argv[1:], "sv") for (o, a) in opts: if o == "-s": mode = "show" elif o == "-v": verbose += 1 else: die("unknown argument: " + o) to_check = args if to_check == []: to_check = get_installed().keys() if mode == "check": checked = {} for package in to_check: check_library_deps(package, checked = checked, verbose = verbose) elif mode == "show": for package in to_check: show_library_deps(package)