1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
#!/bin/sh -e
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}";
|