Skip to content

Commit

Permalink
CodingGuidelines: document a shell that "fails" "VAR=VAL shell_func"
Browse files Browse the repository at this point in the history
Over the years, we accumulated the community wisdom to avoid the
common "one-short export" construct for shell functions, but seem to
have lost on which exact platform it is known to fail.  Now during
an investigation on a breakage for a recent topic, we found one
example of failing shell.  Let's document that.

This does *not* mean that we can freely start using the construct
once Ubuntu 20.04 is retired.  But it does mean that we cannot use
the construct until Ubuntu 20.04 is fully retired from the machines
that matter.  Moreover, posix explicitly says that the behaviour for
the construct is unspecified.

Helped-by: Kyle Lippincott <spectral@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
gitster committed Jul 23, 2024
1 parent c2b3f2b commit 728a196
Showing 1 changed file with 27 additions and 0 deletions.
27 changes: 27 additions & 0 deletions Documentation/CodingGuidelines
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,33 @@ For shell scripts specifically (not exhaustive):
local variable="$value"
local variable="$(command args)"

- The common construct

VAR=VAL command args

to temporarily set and export environment variable VAR only while
"command args" is running is handy, but this triggers an
unspecified behaviour according to POSIX when used for a command
that is not an external command (like shell functions). Indeed,
dash 0.5.10.2-6 on Ubuntu 20.04, /bin/sh on FreeBSD 13, and AT&T
ksh all make a temporary assignment without exporting the variable,
in such a case. As it does not work portably across shells, do not
use this syntax for shell functions. A common workaround is to do
an explicit export in a subshell, like so:

(incorrect)
VAR=VAL func args

(correct)
(
VAR=VAL &&
export VAR &&
func args
)

but be careful that the effect "func" makes to the variables in the
current shell will be lost across the subshell boundary.

- Use octal escape sequences (e.g. "\302\242"), not hexadecimal (e.g.
"\xc2\xa2") in printf format strings, since hexadecimal escape
sequences are not portable.
Expand Down

0 comments on commit 728a196

Please sign in to comment.