/
shell-checks
executable file
·188 lines (157 loc) · 7.4 KB
/
shell-checks
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
180
181
182
183
184
185
186
187
188
#!/bin/sh
# Wrapper around checkbashisms/shellcheck/whatever other shell checkers I can find
#
# Copyright (C) 2016 Austin English
#
# This software comes with ABSOLUTELY NO WARRANTY.
#
# This is free software, placed under the terms of the GNU Lesser
# Public License version 2.1 (or later), as published by the Free
# Software Foundation. Please see the file COPYING for details.
set -e
set -x
###################################################################################################
# Helpers
###################################################################################################
w_die() {
echo "$* failed"
exit 1
}
w_try() {
"$@"
status=$?
if test $status -ne 0; then
w_die "Note: command $* returned status $status. Aborting."
fi
}
###################################################################################################
# Setup
###################################################################################################
if [ ! -f Makefile ] ; then
w_die "$0 should be run from the top of the source tree"
fi
temp="$(mktemp -d)"
trap 'rm -fr "$temp"' EXIT
###################################################################################################
# Test functions
###################################################################################################
# tests using bashate
test_bashate() {
if [ ! -x "$(command -v bashate 2>/dev/null)" ] && [ "$TRAVIS_OS_NAME" = "osx" ]; then
echo "On OSX and bashate not available, skipping."
else
bashate="$(command -v bashate)"
#echo "======================== Begin bashate version info ==========================="
"$bashate" --help > /dev/null || w_die "bashate must be installed!"
## bashate doesn't have a --version option (as of bashate-0.3.1)
#"$bashate" --version
#echo "======================== End bashate version info ==========================="
# Can't ignore individual things for now, filed bug:
# https://bugs.launchpad.net/bash8/+bug/1698088
# E006=line length check
# E010=do/while same line (in some embedded perl in winetricks)
# E044=Use [[ for non-POSIX comparisions
echo "Checking ${shellscript} with bashate:"
w_try "$bashate" -i E006,E010,E044 "${shellscript}"
fi
}
# tests using checkbashisms
test_checkbashisms() {
# Skip checkbashisms tests on OSX if it's not available (homebrew is unreliable):
# Skip checkbashisms tests on OSX if it's not available (homebrew is unreliable):
if [ ! -x "$(command -v checkbashisms 2>/dev/null)" ] && [ "$TRAVIS_OS_NAME" = "osx" ]; then
echo "On OSX and checkbashisms not available, skipping."
else
checkbashisms="$(command -v checkbashisms)"
echo "======================== Begin checkbashisms version info ==========================="
"$checkbashisms" --help > /dev/null || w_die "checkbashisms must be installed!"
"$checkbashisms" --version
echo "======================== End checkbashisms version info ==========================="
# Check if checkbashisms supports `command -v`. If not, warn, or if on travis, patch it:
cat > "${temp}/command.sh" <<_EOF
#!/bin/sh
command -v grep
_EOF
if ! "$checkbashisms" --posix "${temp}/command.sh"; then
echo "Use a sed expression, to add checkbashisms support for 'command -v', based on the patch from https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=733511"
echo "Creating a copy of the checkbashisms script, in ${temp}, to workaround this issue"
# /usr/bin/ (or /usr/local/bin on OSX) isn't writable on Travis, so we have to patch it in /tmp and use that:
(
sed -e '/qr'\''command\\s+\-\[\^p\]\\s'\''/ { ' -e 's|\[\^p\]|[^pvV]|' -e 's| \-p>| -p/-v/-V>|' -e '}' "$checkbashisms" > "${temp}/checkbashisms.patched" && \
chmod +x "${temp}/checkbashisms.patched"
)
checkbashisms="${temp}/checkbashisms.patched"
else
echo "checkbashisms workaround not needed, using vanilla script"
fi
# FIXME: if we add a third patch, clean this up
# Check if checkbashisms supports `command -v`. If not, warn, or if on travis, patch it:
cat > "${temp}/kill.sh" <<_EOF
#!/bin/sh
sleep 5 & spid="$!"
kill -HUP \$spid
_EOF
if ! "$checkbashisms" --posix "${temp}/kill.sh"; then
echo "Disabling the kill -signal warning"
echo "Creating a copy of the checkbashisms script, in ${temp}, to workaround this issue"
# /usr/bin/ (or /usr/local/bin on OSX) isn't writable on Travis, so we have to patch it in /tmp and use that:
(
sed -e '/bashisms.*kill/d' "$checkbashisms" > "${temp}/checkbashisms.patched.kill" && \
chmod +x "${temp}/checkbashisms.patched.kill"
)
checkbashisms="${temp}/checkbashisms.patched.kill"
fi
echo "Checking ${shellscript} for bashisms:"
w_try "$checkbashisms" --posix "${shellscript}"
fi
}
# tests using shellcheck
test_shellcheck() {
# Skip shellcheck tests on OSX if it's not available (homebrew is unreliable):
if [ ! -x "$(command -v shellcheck 2>/dev/null)" ] && [ "$TRAVIS_OS_NAME" = "osx" ]; then
echo "On OSX and shellcheck not available, skipping."
else
shellcheck="$(command -v shellcheck)"
echo "======================== Begin shellcheck version info ==========================="
"$shellcheck" --version > /dev/null || w_die "shellcheck must be installed!"
"$shellcheck" --version
echo "======================== End shellcheck version info ==========================="
echo "Checking ${shellscript} with shellcheck:"
w_try "$shellcheck" -s sh "${shellscript}"
fi
}
# tests for linkcheck
test_linkcheck() {
# Check for uses of variables in w_download when w_linkcheck_ignore isn't set
# Using w_download https://example.com/${file1} breaks src/linkcheck.sh
# FIXME: technically '$' is valid in a URL, if there's actually a URL using it this will need a tweak
if grep "^ *w_download " src/winetricks | grep -E "ftp|http" | grep -v "w_linkcheck_ignore=1" | sed "s/^ *//" | tr -d "\\\\" | cut -d " " -f2 | grep "\\$"; then
w_die "Do not use variables in these URLs, it breaks src/linkcheck.sh"
else
echo "linkcheck checks passed"
fi
}
###################################################################################################
# Test wrapper
main() {
# Use git ls-files if available, this prevents 'finding' scripts that aren't checked into git.
# E.g., if patching foo fails, then foo.orig would also be 'found'.
# The find fallback is for non git users, e.g., distros packaging winetricks or end users
# running shell-checks from a tarball download.
if [ -d .git ] ; then
files_to_check="$(git ls-files | xargs file | grep -e 'POSIX shell script' | cut -d : -f1)"
else
files_to_check="$(find . -type f -exec file {} \; | grep -e 'POSIX shell script' | cut -d : -f1)"
fi
# Run once tests:
# really, this checks winetricks, to make sure it doesn't break linkcheck.sh:
test_linkcheck
# Generic shellscript checks:
for shellscript in $files_to_check; do
test_bashate
test_checkbashisms
test_shellcheck
done
}
main
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4