#!/usr/bin/awk -f # # Reads a list of installed packages from stdin (one per line). # Orders them so that dependencies come first. # Only the first word of every line is taken as a package name, # the rest is ignored, but kept with its package on output. # The ordered list is written to stdout. # function get_make_var(name, default) { #if (!(value = ENVIRON[name])) # value = default value = "" _cmd = "make -f /dev/null -V " name if ((_cmd | getline) > 0) value = $1 close (_cmd) if (!value) value = default return value } BEGIN { i = 0 } { if (NF > 0 && $1 ~ /-/ && !($1 in pkgindex)) { order[i] = i pkgname[i] = $1 pkgline[i] = $0 pkgindex[$1] = i++ } } END { num_pkg = i error = 0 PKG_DBDIR = get_make_var("PKG_DBDIR", "/var/db/pkg") for (i = 0; i < num_pkg; i++) { contents = PKG_DBDIR "/" pkgname[i] "/+CONTENTS" while ((res = (getline < contents)) > 0) { if ($1 == "@pkgdep") { ppref = $2 sub(/-[0-9].*$/, "", ppref) pplen = length(ppref) for (j = 0; j < num_pkg; j++) if (substr(pkgname[j], 1, pplen) == ppref) deplist[i] = deplist[i] " " j } } if (res < 0) { print "Package \"" pkgname[i] "\" is not installed!" error = 1 } close (contents) } if (error) exit 1 i = 0 while (i < num_pkg - 1) { pkg = order[i] # Does it have dependencies? if (pkg in deplist) { # Put dependencies in associative array "deps". delete deps split(deplist[pkg], d) for (j in d) deps[d[j]] = 1 # Remove deplist[pkg], so pkg will be skipped if # we hit it again later. delete deplist[pkg] # Search from the end backwards for the last # dependency of pkg. If found, move pkg just # behind that dependency. for (j = num_pkg - 1; j > i; j--) if (order[j] in deps) { # Found the last dependency at "j". # Move pkg from "i" right behind it. for (k = i; k < j; k++) order[k] = order[k + 1] order[j] = pkg # Decrement i, so we visit the same # position again (which now contains # a different package). i-- break } } i++ } for (i = 0; i < num_pkg; i++) print pkgline[order[i]] } #--