mirror of
https://github.com/koalaman/shellcheck.git
synced 2025-09-30 00:39:19 +08:00
Compare commits
19 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
cb57b4a74f | ||
|
e3f0243c0e | ||
|
66b5f13c6f | ||
|
a7a404a5a8 | ||
|
0761f5c923 | ||
|
b55149b22d | ||
|
4097bb5154 | ||
|
1b207b3d43 | ||
|
135b4aa485 | ||
|
cb76951ad2 | ||
|
705e476e4c | ||
|
e705552c97 | ||
|
198aa4fc3d | ||
|
f4044fbcc7 | ||
|
2827b35696 | ||
|
de95c376ea | ||
|
5e1b1e010a | ||
|
620c9c2023 | ||
|
359b1467a2 |
14
.snapsquid.conf
Normal file
14
.snapsquid.conf
Normal file
@@ -0,0 +1,14 @@
|
||||
# In 2015, cabal-install had a http bug triggered when proxies didn't keep
|
||||
# the connection open. This version made it into Ubuntu Xenial as used by
|
||||
# Snapcraft. In June 2018, Snapcraft's proxy started triggering this bug.
|
||||
#
|
||||
# https://bugs.launchpad.net/launchpad-buildd/+bug/1797809
|
||||
#
|
||||
# Workaround: add more proxy
|
||||
|
||||
visible_hostname localhost
|
||||
http_port 8888
|
||||
cache_peer 10.10.10.1 parent 8222 0 no-query default
|
||||
cache_peer_domain localhost !.internal
|
||||
http_access allow all
|
||||
|
13
CHANGELOG.md
13
CHANGELOG.md
@@ -1,17 +1,26 @@
|
||||
## ???
|
||||
## v0.6.0 - 2018-12-02
|
||||
### Added
|
||||
- Command line option --severity/-S for filtering by minimum severity
|
||||
- Command line option --wiki-link-count/-W for showing wiki links
|
||||
- SC2152/SC2151: Warn about bad `exit` values like `1234` and `"foo"`
|
||||
- SC2236/SC2237: Suggest -n/-z instead of ! -z/-n
|
||||
- SC2238: Warn when redirecting to a known command name, e.g. ls > rm
|
||||
- SC2239: Warn if the shebang is not an absolute path, e.g. #!bin/sh
|
||||
- SC2240: Warn when passing additional arguments to dot (.) in sh/dash
|
||||
- SC1133: Better diagnostics when starting a line with |/||/&&
|
||||
|
||||
### Changed
|
||||
- Most warnings now have useful end positions
|
||||
- SC1117 about unknown double-quoted escape sequences has been retired
|
||||
|
||||
### Fixed
|
||||
- SC2021 no longer triggers for equivalence classes like '[=e=]'
|
||||
- SC2021 no longer triggers for equivalence classes like `[=e=]`
|
||||
- SC2221/SC2222 no longer mistriggers on fall-through case branches
|
||||
- SC2081 about glob matches in `[ .. ]` now also triggers for `!=`
|
||||
- SC2086 no longer warns about spaces in `$#`
|
||||
- SC2164 no longer suggests subshells for `cd ..; cmd; cd ..`
|
||||
- `read -a` is now correctly considered an array assignment
|
||||
- SC2039 no longer warns about LINENO now that it's POSIX
|
||||
|
||||
## v0.5.0 - 2018-05-31
|
||||
### Added
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# Build-only image
|
||||
FROM ubuntu:17.10 AS build
|
||||
FROM ubuntu:18.04 AS build
|
||||
USER root
|
||||
WORKDIR /opt/shellCheck
|
||||
|
||||
|
@@ -133,6 +133,10 @@ On OS X with homebrew:
|
||||
|
||||
brew install shellcheck
|
||||
|
||||
On OpenBSD:
|
||||
|
||||
pkg_add shellcheck
|
||||
|
||||
On openSUSE
|
||||
|
||||
zypper in ShellCheck
|
||||
@@ -168,6 +172,11 @@ Alternatively, you can download pre-compiled binaries for the latest release her
|
||||
|
||||
or see the [storage bucket listing](https://shellcheck.storage.googleapis.com/index.html) for checksums, older versions and the latest daily builds.
|
||||
|
||||
Distro packages already come with a `man` page. If you are building from source, it can be installed with:
|
||||
|
||||
pandoc -s -t man shellcheck.1.md -o shellcheck.1
|
||||
sudo mv shellcheck.1 /usr/share/man/man1
|
||||
|
||||
## Travis CI
|
||||
|
||||
Travis CI has now integrated ShellCheck by default, so you don't need to manually install it.
|
||||
|
2
Setup.hs
2
Setup.hs
@@ -33,4 +33,4 @@ myPreSDist _ _ = do
|
||||
putStrLn $ "pandoc exited with " ++ show result
|
||||
return emptyHookedBuildInfo
|
||||
where
|
||||
pandoc_cmd = "pandoc -s -t man shellcheck.1.md -o shellcheck.1"
|
||||
pandoc_cmd = "pandoc -s -f markdown-smart -t man shellcheck.1.md -o shellcheck.1"
|
||||
|
@@ -1,5 +1,5 @@
|
||||
Name: ShellCheck
|
||||
Version: 0.5.0
|
||||
Version: 0.6.0
|
||||
Synopsis: Shell script analysis tool
|
||||
License: GPL-3
|
||||
License-file: LICENSE
|
||||
@@ -28,6 +28,8 @@ Extra-Source-Files:
|
||||
shellcheck.1.md
|
||||
-- built with a cabal sdist hook
|
||||
shellcheck.1
|
||||
-- convenience script for stripping tests
|
||||
striptests
|
||||
-- tests
|
||||
test/shellcheck.hs
|
||||
|
||||
|
@@ -37,9 +37,16 @@ parts:
|
||||
source: ./
|
||||
build-packages:
|
||||
- cabal-install
|
||||
- squid3
|
||||
build: |
|
||||
# See comments in .snapsquid.conf
|
||||
[ "$http_proxy" ] && {
|
||||
squid3 -f .snapsquid.conf
|
||||
export http_proxy="http://localhost:8888"
|
||||
sleep 3
|
||||
}
|
||||
cabal sandbox init
|
||||
cabal update
|
||||
cabal update || cat /var/log/squid/*
|
||||
cabal install -j
|
||||
install: |
|
||||
install -d $SNAPCRAFT_PART_INSTALL/usr/bin
|
||||
|
@@ -1197,11 +1197,12 @@ prop_checkComparisonAgainstGlob2 = verifyNot checkComparisonAgainstGlob "[[ $cow
|
||||
prop_checkComparisonAgainstGlob3 = verify checkComparisonAgainstGlob "[ $cow = *foo* ]"
|
||||
prop_checkComparisonAgainstGlob4 = verifyNot checkComparisonAgainstGlob "[ $cow = foo ]"
|
||||
prop_checkComparisonAgainstGlob5 = verify checkComparisonAgainstGlob "[[ $cow != $bar ]]"
|
||||
prop_checkComparisonAgainstGlob6 = verify checkComparisonAgainstGlob "[ $f != /* ]"
|
||||
checkComparisonAgainstGlob _ (TC_Binary _ DoubleBracket op _ (T_NormalWord id [T_DollarBraced _ _]))
|
||||
| op `elem` ["=", "==", "!="] =
|
||||
warn id 2053 $ "Quote the right-hand side of " ++ op ++ " in [[ ]] to prevent glob matching."
|
||||
checkComparisonAgainstGlob _ (TC_Binary _ SingleBracket op _ word)
|
||||
| (op == "=" || op == "==") && isGlob word =
|
||||
| op `elem` ["=", "==", "!="] && isGlob word =
|
||||
err (getId word) 2081 "[ .. ] can't match globs. Use [[ .. ]] or case statement."
|
||||
checkComparisonAgainstGlob _ _ = return ()
|
||||
|
||||
|
@@ -61,6 +61,7 @@ commandChecks = [
|
||||
,checkGrepRe
|
||||
,checkTrapQuotes
|
||||
,checkReturn
|
||||
,checkExit
|
||||
,checkFindExecWithSingleArgument
|
||||
,checkUnusedEchoEscapes
|
||||
,checkInjectableFindSh
|
||||
@@ -92,6 +93,7 @@ commandChecks = [
|
||||
,checkWhich
|
||||
,checkSudoRedirect
|
||||
,checkSudoArgs
|
||||
,checkSourceArgs
|
||||
]
|
||||
|
||||
buildCommandMap :: [CommandCheck] -> Map.Map CommandName (Token -> Analysis)
|
||||
@@ -280,15 +282,28 @@ prop_checkReturn4 = verifyNot checkReturn "return $((a|b))"
|
||||
prop_checkReturn5 = verify checkReturn "return -1"
|
||||
prop_checkReturn6 = verify checkReturn "return 1000"
|
||||
prop_checkReturn7 = verify checkReturn "return 'hello world'"
|
||||
checkReturn = CommandCheck (Exactly "return") (f . arguments)
|
||||
checkReturn = CommandCheck (Exactly "return") (returnOrExit
|
||||
(\c -> err c 2151 "Only one integer 0-255 can be returned. Use stdout for other data.")
|
||||
(\c -> err c 2152 "Can only return 0-255. Other data should be written to stdout."))
|
||||
|
||||
prop_checkExit1 = verifyNot checkExit "exit"
|
||||
prop_checkExit2 = verifyNot checkExit "exit 1"
|
||||
prop_checkExit3 = verifyNot checkExit "exit $var"
|
||||
prop_checkExit4 = verifyNot checkExit "exit $((a|b))"
|
||||
prop_checkExit5 = verify checkExit "exit -1"
|
||||
prop_checkExit6 = verify checkExit "exit 1000"
|
||||
prop_checkExit7 = verify checkExit "exit 'hello world'"
|
||||
checkExit = CommandCheck (Exactly "exit") (returnOrExit
|
||||
(\c -> err c 2241 "The exit status can only be one integer 0-255. Use stdout for other data.")
|
||||
(\c -> err c 2242 "Can only exit with status 0-255. Other data should be written to stdout/stderr."))
|
||||
|
||||
returnOrExit multi invalid = (f . arguments)
|
||||
where
|
||||
f (first:second:_) =
|
||||
err (getId second) 2151
|
||||
"Only one integer 0-255 can be returned. Use stdout for other data."
|
||||
multi (getId first)
|
||||
f [value] =
|
||||
when (isInvalid $ literal value) $
|
||||
err (getId value) 2152
|
||||
"Can only return 0-255. Other data should be written to stdout."
|
||||
invalid (getId value)
|
||||
f _ = return ()
|
||||
|
||||
isInvalid s = s == "" || any (not . isDigit) s || length s > 5
|
||||
@@ -1008,5 +1023,16 @@ checkSudoArgs = CommandCheck (Basename "sudo") f
|
||||
-- This mess is why ShellCheck prefers not to know.
|
||||
parseOpts = getBsdOpts "vAknSbEHPa:g:h:p:u:c:T:r:"
|
||||
|
||||
prop_checkSourceArgs1 = verify checkSourceArgs "#!/bin/sh\n. script arg"
|
||||
prop_checkSourceArgs2 = verifyNot checkSourceArgs "#!/bin/sh\n. script"
|
||||
prop_checkSourceArgs3 = verifyNot checkSourceArgs "#!/bin/bash\n. script arg"
|
||||
checkSourceArgs = CommandCheck (Exactly ".") f
|
||||
where
|
||||
f t = whenShell [Sh, Dash] $
|
||||
case arguments t of
|
||||
(file:arg1:_) -> warn (getId arg1) 2240 $
|
||||
"The dot command does not support arguments in sh/dash. Set them as variables."
|
||||
_ -> return ()
|
||||
|
||||
return []
|
||||
runTests = $( [| $(forAllProperties) (quickCheckWithResult (stdArgs { maxSuccess = 1 }) ) |])
|
||||
|
@@ -94,7 +94,7 @@ outputWiki errRef = do
|
||||
where
|
||||
showErr (_, code, msg) =
|
||||
putStrLn $ " " ++ wikiLink ++ "SC" ++ show code ++ " -- " ++ shorten msg
|
||||
limit = 40
|
||||
limit = 36
|
||||
shorten msg =
|
||||
if length msg < limit
|
||||
then msg
|
||||
|
@@ -1916,8 +1916,9 @@ readNewlineList =
|
||||
where
|
||||
checkBadBreak = optional $ do
|
||||
pos <- getPosition
|
||||
try $ lookAhead (oneOf "|&") -- |, || or &&
|
||||
parseProblemAt pos ErrorC 1133 "Unexpected start of line. If breaking lines, |/||/&& should be at the end of the previous one."
|
||||
try $ lookAhead (oneOf "|&") -- See if the next thing could be |, || or &&
|
||||
parseProblemAt pos ErrorC 1133
|
||||
"Unexpected start of line. If breaking lines, |/||/&& should be at the end of the previous one."
|
||||
readLineBreak = optional readNewlineList
|
||||
|
||||
prop_readSeparator1 = isWarning readScript "a &; b"
|
||||
|
@@ -16,10 +16,14 @@ and is still highly experimental.
|
||||
|
||||
Make sure you're plugged in and have screen/tmux in place,
|
||||
then re-run with $0 --run to continue.
|
||||
|
||||
Also note that 'dist' will be deleted.
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
echo "Deleting 'dist'..."
|
||||
rm -rf dist
|
||||
|
||||
log=$(mktemp) || die "Can't create temp file"
|
||||
date >> "$log" || die "Can't write to log"
|
||||
@@ -63,7 +67,8 @@ opensuse:latest zypper install -y cabal-install ghc
|
||||
ubuntu:18.04 apt-get update && apt-get install -y cabal-install
|
||||
ubuntu:17.10 apt-get update && apt-get install -y cabal-install
|
||||
|
||||
# Misc
|
||||
# Misc Haskell including current and latest Stack build
|
||||
ubuntu:18.10 set -e; apt-get update && apt-get install -y curl && curl -sSL https://get.haskellstack.org/ | sh -s - -f && cd /mnt && exec test/stacktest
|
||||
haskell:latest true
|
||||
|
||||
# Known to currently fail
|
||||
|
27
test/stacktest
Executable file
27
test/stacktest
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
# This script builds ShellCheck through `stack` using
|
||||
# various resolvers. It's run via distrotest.
|
||||
|
||||
resolvers=(
|
||||
nightly-"$(date -d "3 days ago" +"%Y-%m-%d")"
|
||||
)
|
||||
|
||||
die() { echo "$*" >&2; exit 1; }
|
||||
|
||||
[ -e "ShellCheck.cabal" ] ||
|
||||
die "ShellCheck.cabal not in current dir"
|
||||
[ -e "stack.yaml" ] ||
|
||||
die "stack.yaml not in current dir"
|
||||
command -v stack ||
|
||||
die "stack is missing"
|
||||
|
||||
stack setup || die "Failed to setup with default resolver"
|
||||
stack build --test || die "Failed to build/test with default resolver"
|
||||
|
||||
for resolver in "${resolvers[@]}"
|
||||
do
|
||||
stack --resolver="$resolver" setup || die "Failed to setup $resolver"
|
||||
stack --resolver="$resolver" build --test || die "Failed build/test with $resolver!"
|
||||
done
|
||||
|
||||
echo "Success"
|
Reference in New Issue
Block a user