summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorZach van Rijn <me@zv.io>2022-05-18 22:31:30 +0000
committerZach van Rijn <me@zv.io>2022-05-21 09:24:25 -0500
commitc1e964edbfda1e07d6648521f63dd4acd5b437e4 (patch)
tree574ba9e43323c5193e8b97023bd8148d7b891942 /scripts
parent82f6ae82470ae56ca21b65bb09f368c5635f68a6 (diff)
downloadpackages-c1e964edbfda1e07d6648521f63dd4acd5b437e4.tar.gz
packages-c1e964edbfda1e07d6648521f63dd4acd5b437e4.tar.bz2
packages-c1e964edbfda1e07d6648521f63dd4acd5b437e4.tar.xz
packages-c1e964edbfda1e07d6648521f63dd4acd5b437e4.zip
scripts/depsort: implement package exclusion. fixes adelie-infra/autobuilder#16.
This is included in the 'packages.git' repository because it may be useful to temporarily prevent packages from building in development branches. The build plan is generated from this repository instead of autobuilder in the first place, so putting it here makes sense.
Diffstat (limited to 'scripts')
-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}";