summaryrefslogtreecommitdiff
path: root/pkgtools/pkglint/files/shell.go
diff options
context:
space:
mode:
authorrillig <rillig@pkgsrc.org>2019-05-06 20:27:17 +0000
committerrillig <rillig@pkgsrc.org>2019-05-06 20:27:17 +0000
commit916339bb022f0f3e4e1da5f753114ce4b8d69709 (patch)
treee2358c7c52324fbad66bfd953ea252d6197ffed5 /pkgtools/pkglint/files/shell.go
parent3e83a6c4d69c38a42d8a7a8b46cba5f3e4ea734d (diff)
downloadpkgsrc-916339bb022f0f3e4e1da5f753114ce4b8d69709.tar.gz
pkgtools/pkglint: update to 5.7.9
Changes since 5.7.8: * Buildlink3.mk files are checked for typos in the identifier that is used for BUILDLINK_TREE, to detect copy-and-paste mistakes. * Having a rationale is recommended for some variables, especially those that make a package fail to build or crash at runtime. This check is only active when -Wextra is given, since it is still actively debated whether such a check is actually useful. * Files called Makefile.php can easily be mistaken to be PHP files. Therefore the recommended naming convention is to have auxiliary files called *.mk. There are already many more files called *.mk than those being called Makefile.*. * The check for unquoted sed substitution commands has been made more detailed, but since it is completely disabled, there's nothing to see for now. * The definitions for MASTER_SITE_* are loaded directly from the pkgsrc infrastructure instead of hard-coding them in pkglint.
Diffstat (limited to 'pkgtools/pkglint/files/shell.go')
-rw-r--r--pkgtools/pkglint/files/shell.go71
1 files changed, 58 insertions, 13 deletions
diff --git a/pkgtools/pkglint/files/shell.go b/pkgtools/pkglint/files/shell.go
index 98e50c70c36..35e23aea7fd 100644
--- a/pkgtools/pkglint/files/shell.go
+++ b/pkgtools/pkglint/files/shell.go
@@ -189,10 +189,30 @@ func (ck *ShellLineChecker) checkVaruseToken(atoms *[]*ShAtom, quoting ShQuoting
// This is ok as long as these variables don't have embedded [$\\"'`].
case quoting == shqDquot && varuse.IsQ():
- ck.mkline.Warnf("The :Q modifier should not be used inside double quotes.")
- ck.mkline.Explain(
+ ck.Warnf("The :Q modifier should not be used inside double quotes.")
+ ck.Explain(
+ "The :Q modifier is intended for embedding a string into a shell program.",
+ "It escapes all characters that have a special meaning in shell programs.",
+ "It only works correctly when it appears outside of \"double\" or 'single'",
+ "quotes or `backticks`.",
+ "",
+ "When it is used inside double quotes or backticks, the resulting string may",
+ "contain more backslashes than intended.",
+ "",
+ "When it is used inside single quotes and the string contains a single quote",
+ "itself, it produces syntax errors in the shell.",
+ "",
"To fix this warning, either remove the :Q or the double quotes.",
- "In most cases, it is more appropriate to remove the double quotes.")
+ "In most cases, it is more appropriate to remove the double quotes.",
+ "",
+ "A special case is for empty strings.",
+ "If the empty string should be preserved as an empty string,",
+ "the correct form is ${VAR:Q}'' with either leading or trailing single or double quotes.",
+ "If the empty string should just be skipped,",
+ "a simple ${VAR:Q} without any surrounding quotes is correct.")
+
+ // TODO: What about single quotes?
+ // TODO: What about backticks?
}
if ck.checkVarUse {
@@ -623,17 +643,42 @@ func (scc *SimpleCommandChecker) checkRegexReplace() {
defer trace.Call0()()
}
- cmdname := scc.strcmd.Name
- isSubst := false
- for _, arg := range scc.strcmd.Args {
- if G.Testing && isSubst && !matches(arg, `"^[\"\'].*[\"\']$`) {
- scc.Warnf("Substitution commands like %q should always be quoted.", arg)
- scc.Explain(
- "Usually these substitution commands contain characters like '*' or",
- "other shell metacharacters that might lead to lookup of matching",
- "filenames and then expand to more than one word.")
+ if !G.Testing {
+ return
+ }
+
+ checkArg := func(arg string) {
+ if matches(arg, `"^[\"\'].*[\"\']$`) {
+ return
}
- isSubst = cmdname == "${PAX}" && arg == "-s" || cmdname == "${SED}" && arg == "-e"
+
+ // Substitution commands that consist only of safe characters cannot
+ // have any side effects, therefore they don't need to be quoted.
+ if matches(arg, `^([\w,.]|\\[.])+$`) {
+ return
+ }
+
+ scc.Warnf("Substitution commands like %q should always be quoted.", arg)
+ scc.Explain(
+ "Usually these substitution commands contain characters like '*' or",
+ "other shell metacharacters that might lead to lookup of matching",
+ "filenames and then expand to more than one word.")
+ }
+
+ checkArgAfter := func(opt string) {
+ args := scc.strcmd.Args
+ for i, arg := range args {
+ if i > 0 && args[i-1] == opt {
+ checkArg(arg)
+ }
+ }
+ }
+
+ switch scc.strcmd.Name {
+ case "${PAX}", "pax":
+ checkArgAfter("-s")
+ case "${SED}", "sed":
+ checkArgAfter("-e")
}
}