summaryrefslogtreecommitdiff
path: root/scripts/depsort
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/depsort')
-rwxr-xr-xscripts/depsort116
1 files changed, 115 insertions, 1 deletions
diff --git a/scripts/depsort b/scripts/depsort
index 953260238..2293d9aa4 100755
--- a/scripts/depsort
+++ b/scripts/depsort
@@ -1,3 +1,117 @@
#!/bin/sh -e
-awk '{ for (f=1;f<=NF;f++) { print $(f),$1 } }' | "$(dirname $(readlink -f ${0}))"/tsort
+HERE="$(dirname $(readlink -f ${0}))";
+LIST="${HERE}/../.exclude";
+
+#---------------------------------------------------------------
+# overview
+
+##
+# Usage:
+#
+# $ ./scripts/deplist system | ./scripts/depsort
+#
+# This script reads a list of packages (stdin) of the form:
+#
+# pkg1 dep1 dep2 ...
+# pkg2 ...
+#
+# and computes a topological sort, then prints to stdout.
+#
+# If the file called '$LIST' exists, it will be used as a filter
+# to exclude those packages, their dependencies, and transitive
+# dependencies as well, from the build plan.
+#
+# Entries must be one per line of the form REPO/PACKAGE:
+#
+# user/rust
+#
+# It is possible to end up with a surprisingly small build plan
+# if a more essential package is excluded, so this mechanism
+# should only be used to temporarily avoid problematic packages
+# or known package families e.g. "all java-related".
+
+
+#---------------------------------------------------------------
+# supporting routines
+
+##
+# Appends text to the end of each line of stdin, in this case it
+# is to assist 'grep' later on.
+#
+# We strictly search for ending in space or end of line instead
+# of with the flag '-F', which is string literal, to avoid any
+# partial and undesirable matches, e.g. 'foo' in 'foo3'.
+#
+# This is a function because it is used multiple times and may
+# need to be updated in the future.
+#
+suffix ()
+{
+ sed -e 's@$@\\( \\|$\\)@g';
+}
+
+
+#---------------------------------------------------------------
+# initialization
+
+##
+# We need to create a few temporary files in order to support
+# handling transitive dependencies because it is not possible to
+# reuse 'foo' as in: 'tee >( ... > foo) | bar -f foo'.
+#
+data=$(mktemp); # stdin
+user=$(mktemp); # processed '$LIST'
+real=$(mktemp); # processed derivation of dependencies
+
+##
+# Capture stdin because it needs to be split for filtering.
+# This could in theory be done later, without 'cat', but
+# it is much easier for others to follow when it's here.
+#
+cat > "${data}";
+
+
+#---------------------------------------------------------------
+# preprocessing
+
+##
+# If there is no exclusion file, passthru.
+#
+if test -f "${LIST}"; then
+
+ ##
+ # Preprocess user input '$LIST' to include a suffix that
+ # works better with 'grep'. Write to file for multi-line
+ # support. The '!' before ' grep' is to ignore a no-match
+ # error that will otherwise cause the script to exit early.
+ #
+ suffix < "${LIST}" > "${user}";
+ ! grep -f "${user}" "${data}" \
+ | awk '{print $1}' \
+ | suffix \
+ | grep / `# ensure all lines of form: REPO/PACKAGE` \
+ > "${real}" \
+ ;
+ exclude="grep -vf ${real} ${data}";
+else
+ exclude="cat ${data}";
+fi
+
+#---------------------------------------------------------------
+# filtering
+
+##
+# Enumerate digraph nodes based on (possibly) filtered input.
+#
+# Pipe to 'tsort' for the final build plan.
+#
+${exclude} \
+ | awk '{ for (f=1;f<=NF;f++) { print $(f),$1 } }' \
+ | "${HERE}"/tsort \
+ ;
+
+#---------------------------------------------------------------
+# cleanup
+
+rm -f "${data}" "${user}" "${real}";