-
Notifications
You must be signed in to change notification settings - Fork 0
/
search-component-modules.sh
executable file
·179 lines (159 loc) · 4.96 KB
/
search-component-modules.sh
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#!/usr/bin/env bash
set -eE
if [ "${BASH_VERSION:0:1}" -lt 4 ]; then
echo -e "\\nYou are using a very old version of Bash. Please install"
echo "version 4.1 or later. If this is an OSX host, see:"
echo "https://apple.stackexchange.com/a/193413 or similar"
exit 13
fi
# Strip all the cruft out of matching strings
# Requires two arguments:
# $1 is the variable name to set the return to
# $2 is the string to cleanse
function cleanse_matches() {
[ -z "$1" ] && return 1
[ -z "$2" ] && return 1
local res split
# It is allowed to include multiple classes on one line. Split
# to catch more than just the first class.
split=$(sed "s|,|\ninclude|g" <<< "$2")
res=$(sed -e "s|^\s*\(->\)*\s*class\s*{\s*['\"]*:*||" \
-e "s|^\s*\(->\)*\s*include\s*['\"]*||" \
-e "s|^\s*\(->\)*\s*contain\s*['\"]*||" \
-e "s|['\"]\s*:*.*||" \
-e "s|\s*#.*||" \
<<< "$split")
unset -v "$1"
printf -v "$1" '%s' "$res"
}
# Print msg on stderr and exit
function fail() {
echo -e "\\n$*\\n" >&2
exit 1
}
# Find all the matching patterns.
# Requires two arguments:
# $1 is the variable name to set the return to
# $2 is the file in which to find matches
function find_matches() {
[ -z "$1" ] && return 1
[ -z "$2" ] && return 1
local res
res=$(grep -Eh -e 'class[[:space:]]*{' \
-e "^[[:space:]]*(->)?[[:space:]]*(contain |include )[[:space:]]*[\"\':a-z0-9]" \
"$2" | grep -v -e '^[[:space:]]*#') || : # No matches is not a failure
unset -v "$1"
printf -v "$1" '%s' "$res"
}
# Print usage and optional warning message
function help() {
local out err
if [ -n "$1" ]; then
out='/dev/stderr'
err=1
echo -e "\\n$1" >$out
else
out='/dev/stdout'
err=0
fi
cat >$out <<-EOF
Usage: $0 -r /path/to/control-repo [-c]
-r Where the control-repo lives
-c Disable color
EOF
exit $err
}
# Convenience function to couple find_matches() with cleanse_matches()
# Requires one argument: The file to be processed
function process_file() {
# Ensure a clean slate
match=
match_cleansed=
find_matches match "$1"
if [ -n "$match" ]; then
cleanse_matches match_cleansed "$match"
fi
}
# Process args
set -- "$@" _eNd_OF_lisT_
while [ "$1" != "_eNd_OF_lisT_" ]; do
case "$1" in
-c) color='no'; shift;;
-r) repos="$2"; shift 2;;
-h) help;;
*) help "Unknown option: $1";;
esac
done
# For prettier output
if [ "$color" == 'no' ]; then
normal=''
grn="$normal"
blue="$normal"
whi="$normal"
else
normal="\\e[0;00m"
grn="\\e[1;32m"
blue="\\e[1;34m"
whi="\\e[1;37m"
fi
# Test args
if [ -z "$repos" ]; then
help "Missing the path to the control-repo"
fi
if [ ! -d "$repos" ] || [ ! -r "$repos" ] || [ ! -x "$repos" ]; then
fail "\"$repos\" is either missing or has bad permissions"
fi
# Now that all vars should be vetted, bail on unset vars
set -u
# These vars will be set/unset with each file parsed. To prevent a shellcheck
# error (SC2154) due to shellcheck not yet supporting "printf -v" style variable
# setting, we will declare them first.
declare match
declare match_cleansed
# Placeholders to aggregate and sort all found modules
allmods=()
uniqmods=()
# Now process all of the component modules
mapfile -t manifests < <(find "$repos" -type f -name \*.pp)
# Print the modules found in each module and print the file name. At the same
# time, collect all of the modules in an array for further processing.
for manifest in "${manifests[@]}"; do
process_file "$manifest"
if [ -n "$match_cleansed" ]; then
line="${manifest//?/-}"
echo -e "\\n${grn}${manifest}\\n${line}${normal}"
echo -e "${whi}${match_cleansed}${normal}"
# Save all found modules in an array for later use
mapfile -t append <<<"$match_cleansed"
allmods+=("${append[@]}")
unset append
fi
done
# Purge duplicates. If a subclass is referenced (like foo::bar or
# foo::bar::baz), strip all by the module name (foo). The first iteration, when
# uniqmods is empty, will trigger an unbound error due to set -u. Ignore that
# for this for loop as we know it is empty.
set +u
for mod in "${allmods[@]}"; do
# If the module begins with :: it will expand to nothing, so strip the ::
[ "${mod%%:*}" == '' ] && mod="${mod:2}"
# Beginning of array
[[ ${uniqmods[*]} =~ ^${mod%%:*}[[:space:]] ]] && continue
# End of array
[[ ${uniqmods[*]} =~ [[:space:]]${mod%%:*}$ ]] && continue
# Only entry in array
[[ ${uniqmods[*]} =~ ^${mod%%:*}$ ]] && continue
# Anywhere else in the array
[[ ${uniqmods[*]} =~ [[:space:]]${mod%%:*}[[:space:]] ]] && continue
uniqmods+=("${mod%%:*}")
done
set -u
# Finally sort the array and print the collection
mapfile -t sortedmods < <(printf '%s\0' "${uniqmods[@]}" |sort -z |xargs -0n1)
echo -e "\\n\\n\\n${blue}##############################################"
echo "ALL unique compoenent modules being pulled in:"
echo -e "##############################################${normal}\\n"
for mod in "${sortedmods[@]}"; do
echo "$mod"
done
# vim: set tw=80 ts=2 sw=2 sts=2 et: