Skip to content

Commit 92e8388

Browse files
committed
Merge branch 'jc/local-extern-shell-rules'
Document and apply workaround for a buggy version of dash that mishandles "local var=val" construct. * jc/local-extern-shell-rules: t1016: local VAR="VAL" fix t0610: local VAR="VAL" fix t: teach lint that RHS of 'local VAR=VAL' needs to be quoted t: local VAR="VAL" (quote ${magic-reference}) t: local VAR="VAL" (quote command substitution) t: local VAR="VAL" (quote positional parameters) CodingGuidelines: quote assigned value in 'local var=$val' CodingGuidelines: describe "export VAR=VAL" rule
2 parents 548fe35 + 836b221 commit 92e8388

9 files changed

+37
-19
lines changed

Documentation/CodingGuidelines

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,22 @@ For shell scripts specifically (not exhaustive):
188188
hopefully nobody starts using "local" before they are reimplemented
189189
in C ;-)
190190

191+
- Some versions of shell do not understand "export variable=value",
192+
so we write "variable=value" and then "export variable" on two
193+
separate lines.
194+
195+
- Some versions of dash have broken variable assignment when prefixed
196+
with "local", "export", and "readonly", in that the value to be
197+
assigned goes through field splitting at $IFS unless quoted.
198+
199+
(incorrect)
200+
local variable=$value
201+
local variable=$(command args)
202+
203+
(correct)
204+
local variable="$value"
205+
local variable="$(command args)"
206+
191207
- Use octal escape sequences (e.g. "\302\242"), not hexadecimal (e.g.
192208
"\xc2\xa2") in printf format strings, since hexadecimal escape
193209
sequences are not portable.

t/check-non-portable-shell.pl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ sub err {
4747
/\bgrep\b.*--file\b/ and err 'grep --file FILE is not portable (use grep -f FILE)';
4848
/\b[ef]grep\b/ and err 'egrep/fgrep obsolescent (use grep -E/-F)';
4949
/\bexport\s+[A-Za-z0-9_]*=/ and err '"export FOO=bar" is not portable (use FOO=bar && export FOO)';
50+
/\blocal\s+[A-Za-z0-9_]*=\$([A-Za-z0-9_{]|[(][^(])/ and
51+
err q(quote "$val" in 'local var=$val');
5052
/^\s*([A-Z0-9_]+=(\w*|(["']).*?\3)\s+)+(\w+)/ and exists($func{$4}) and
5153
err '"FOO=bar shell_func" assignment extends beyond "shell_func"';
5254
$line = '';

t/lib-parallel-checkout.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ test_checkout_workers () {
2020
BUG "too few arguments to test_checkout_workers"
2121
fi &&
2222

23-
local expected_workers=$1 &&
23+
local expected_workers="$1" &&
2424
shift &&
2525

2626
local trace_file=trace-test-checkout-workers &&

t/t0610-reftable-basics.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ test_expect_success 'init: reinitializing reftable with files backend fails' '
8383
test_expect_perms () {
8484
local perms="$1"
8585
local file="$2"
86-
local actual=$(ls -l "$file") &&
86+
local actual="$(ls -l "$file")" &&
8787

8888
case "$actual" in
8989
$perms*)

t/t1016-compatObjectFormat.sh

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ commit2_oid () {
7979
}
8080

8181
del_sigcommit () {
82-
local delete=$1
82+
local delete="$1"
8383

8484
if test "$delete" = "sha256" ; then
8585
local pattern="gpgsig-sha256"
@@ -91,8 +91,8 @@ del_sigcommit () {
9191

9292

9393
del_sigtag () {
94-
local storage=$1
95-
local delete=$2
94+
local storage="$1"
95+
local delete="$2"
9696

9797
if test "$storage" = "$delete" ; then
9898
local pattern="trailer"
@@ -181,7 +181,7 @@ done
181181
cd "$base"
182182

183183
compare_oids () {
184-
test "$#" = 5 && { local PREREQ=$1; shift; } || PREREQ=
184+
test "$#" = 5 && { local PREREQ="$1"; shift; } || PREREQ=
185185
local type="$1"
186186
local name="$2"
187187
local sha1_oid="$3"
@@ -193,8 +193,8 @@ compare_oids () {
193193

194194
git --git-dir=repo-sha1/.git rev-parse --output-object-format=sha256 ${sha1_oid} > ${name}_sha1_sha256_found
195195
git --git-dir=repo-sha256/.git rev-parse --output-object-format=sha1 ${sha256_oid} > ${name}_sha256_sha1_found
196-
local sha1_sha256_oid=$(cat ${name}_sha1_sha256_found)
197-
local sha256_sha1_oid=$(cat ${name}_sha256_sha1_found)
196+
local sha1_sha256_oid="$(cat ${name}_sha1_sha256_found)"
197+
local sha256_sha1_oid="$(cat ${name}_sha256_sha1_found)"
198198

199199
test_expect_success $PREREQ "Verify ${type} ${name}'s sha1 oid" '
200200
git --git-dir=repo-sha256/.git rev-parse --output-object-format=sha1 ${sha256_oid} > ${name}_sha1 &&

t/t2400-worktree-add.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ test_expect_success '"add" worktree with orphan branch, lock, and reason' '
427427
# Note: Quoted arguments containing spaces are not supported.
428428
test_wt_add_orphan_hint () {
429429
local context="$1" &&
430-
local use_branch=$2 &&
430+
local use_branch="$2" &&
431431
shift 2 &&
432432
local opts="$*" &&
433433
test_expect_success "'worktree add' show orphan hint in bad/orphan HEAD w/ $context" '

t/t4011-diff-symlink.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ TEST_PASSES_SANITIZE_LEAK=true
1313

1414
# Print the short OID of a symlink with the given name.
1515
symlink_oid () {
16-
local oid=$(printf "%s" "$1" | git hash-object --stdin) &&
16+
local oid="$(printf "%s" "$1" | git hash-object --stdin)" &&
1717
git rev-parse --short "$oid"
1818
}
1919

2020
# Print the short OID of the given file.
2121
short_oid () {
22-
local oid=$(git hash-object "$1") &&
22+
local oid="$(git hash-object "$1")" &&
2323
git rev-parse --short "$oid"
2424
}
2525

t/t4210-log-i18n.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ test_expect_success 'log --grep does not find non-reencoded values (latin1)' '
6464
'
6565

6666
triggers_undefined_behaviour () {
67-
local engine=$1
67+
local engine="$1"
6868

6969
case $engine in
7070
fixed)
@@ -85,7 +85,7 @@ triggers_undefined_behaviour () {
8585
}
8686

8787
mismatched_git_log () {
88-
local pattern=$1
88+
local pattern="$1"
8989

9090
LC_ALL=$is_IS_locale git log --encoding=ISO-8859-1 --format=%s \
9191
--grep=$pattern

t/test-lib-functions.sh

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ test_commit () {
385385
shift
386386
done &&
387387
indir=${indir:+"$indir"/} &&
388-
local file=${2:-"$1.t"} &&
388+
local file="${2:-"$1.t"}" &&
389389
if test -n "$append"
390390
then
391391
$echo "${3-$1}" >>"$indir$file"
@@ -1748,7 +1748,7 @@ test_oid () {
17481748
# Insert a slash into an object ID so it can be used to reference a location
17491749
# under ".git/objects". For example, "deadbeef..." becomes "de/adbeef..".
17501750
test_oid_to_path () {
1751-
local basename=${1#??}
1751+
local basename="${1#??}"
17521752
echo "${1%$basename}/$basename"
17531753
}
17541754

@@ -1765,7 +1765,7 @@ test_parse_ls_tree_oids () {
17651765
# Choose a port number based on the test script's number and store it in
17661766
# the given variable name, unless that variable already contains a number.
17671767
test_set_port () {
1768-
local var=$1 port
1768+
local var="$1" port
17691769

17701770
if test $# -ne 1 || test -z "$var"
17711771
then
@@ -1840,7 +1840,7 @@ test_subcommand () {
18401840
shift
18411841
fi
18421842

1843-
local expr=$(printf '"%s",' "$@")
1843+
local expr="$(printf '"%s",' "$@")"
18441844
expr="${expr%,}"
18451845

18461846
if test -n "$negate"
@@ -1930,7 +1930,7 @@ test_readlink () {
19301930
# An optional increment to the magic timestamp may be specified as second
19311931
# argument.
19321932
test_set_magic_mtime () {
1933-
local inc=${2:-0} &&
1933+
local inc="${2:-0}" &&
19341934
local mtime=$((1234567890 + $inc)) &&
19351935
test-tool chmtime =$mtime "$1" &&
19361936
test_is_magic_mtime "$1" $inc
@@ -1943,7 +1943,7 @@ test_set_magic_mtime () {
19431943
# argument. Usually, this should be the same increment which was used for
19441944
# the associated test_set_magic_mtime.
19451945
test_is_magic_mtime () {
1946-
local inc=${2:-0} &&
1946+
local inc="${2:-0}" &&
19471947
local mtime=$((1234567890 + $inc)) &&
19481948
echo $mtime >.git/test-mtime-expect &&
19491949
test-tool chmtime --get "$1" >.git/test-mtime-actual &&

0 commit comments

Comments
 (0)