git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2 0/5] improve one-shot variable detection with shell function

From
ESEric Sunshine <ericsunshine@charter.net>
Date
Jul 26, 2024, 08:15 UTC
Message-ID
<20240726081522.28015-1-ericsunshine@charter.net>
In-Reply-To
<20240722065915.80760-1-ericsunshine@charter.net>
From: Eric Sunshine <sunshine@sunshineco.com>

This is a reroll of [1] which improves check-non-portable-shell's detection of one-shot environment variable assignment with shell functions. Changes since v1:

* commit messages now state the behavior is undefined according to POSIX
  rather than focusing only on the original reason given (that the
  assignments could outlive the shell function invocation)
* t3430 simplified by dropping the subshell altogether in favor of
  `test_commit --author`
* new commit to improve the error message when one-shot assignment with
  shell function is detected
[1]: https://lore.kernel.org/git/20240722065915.80760-1-ericsunshine@charter.net/
Eric Sunshine (5):
  t3430: drop unnecessary one-shot "VAR=val shell-func" invocation
  t4034: fix use of one-shot variable assignment with shell function
  check-non-portable-shell: loosen one-shot assignment error message
  check-non-portable-shell: suggest alternative for `VAR=val shell-func`
  check-non-portable-shell: improve `VAR=val shell-func` detection
 t/check-non-portable-shell.pl | 4 ++--
 t/t3430-rebase-merges.sh      | 3 +--
 t/t4034-diff-words.sh         | 2 +-
 3 files changed, 4 insertions(+), 5 deletions(-)
Range-diff against v1:
1:  5bb6811f68 ! 1:  0d3c0593c9 t3430: modernize one-shot "VAR=val shell-func" invocation
    @@ Metadata
     Author: Eric Sunshine <sunshine@sunshineco.com>
     
      ## Commit message ##
    -    t3430: modernize one-shot "VAR=val shell-func" invocation
    +    t3430: drop unnecessary one-shot "VAR=val shell-func" invocation
     
    -    Unlike "VAR=val cmd" one-shot environment variable assignments which
    -    exist only for the invocation of 'cmd', those assigned by "VAR=val
    -    shell-func" exist within the running shell and continue to do so until
    -    the process exits (or are explicitly unset). check-non-portable-shell.pl
    -    warns when it detects such usage since, more often than not, the author
    -    who writes such an invocation is unaware of the undesirable behavior.
    +    The behavior of a one-shot environment variable assignment of the form
    +    "VAR=val cmd" is undefined according to POSIX when "cmd" is a shell
    +    function. Indeed the behavior differs between shell implementations and
    +    even different versions of the same shell. One such ill-defined behavior
    +    is that, with some shells, the assignment will outlive the invocation of
    +    the function, thus may potentially impact subsequent commands in the
    +    test, as well as subsequent tests. A common way to work around the
    +    problem is to wrap a subshell around the one-shot assignment, thus
    +    ensuring that the assignment is short-lived.
     
    -    A common way to work around the problem is to wrap a subshell around the
    -    variable assignments and function call, thus ensuring that the
    -    assignments are short-lived. However, these days, a more ergonomic
    -    approach is to employ test_env() which is tailor-made for this specific
    -    use-case.
    +    In this test, the subshell is employed precisely for this purpose; other
    +    side-effects of the subshell, such as losing the effect of `test_tick`
    +    which is invoked by `test_commit`, are immaterial.
    +
    +    These days, we can take advantage of `test_commit --author` to more
    +    clearly convey that the test is interested only in overriding the author
    +    of the commit.
     
         Signed-off-by: Eric Sunshine <sunshine@sunshineco.com>
     
    @@ t/t3430-rebase-merges.sh: test_expect_success 'refuse to merge ancestors of HEAD
      	git checkout --orphan unrelated &&
     -	(GIT_AUTHOR_NAME="Parsnip" GIT_AUTHOR_EMAIL="root@example.com" \
     -	 test_commit second-root) &&
    -+	test_env GIT_AUTHOR_NAME="Parsnip" GIT_AUTHOR_EMAIL="root@example.com" \
    -+		test_commit second-root &&
    ++	test_commit --author "Parsnip <root@example.com>" second-root &&
      	test_commit third-root &&
      	cat >script-from-scratch <<-\EOF &&
      	pick third-root
2:  1f35449847 ! 2:  19ee8295ef t4034: fix use of one-shot variable assignment with shell function
    @@ Metadata
      ## Commit message ##
         t4034: fix use of one-shot variable assignment with shell function
     
    -    Unlike "VAR=val cmd" one-shot environment variable assignments which
    -    exist only for the invocation of 'cmd', those assigned by "VAR=val
    -    shell-func" exist within the running shell and continue to do so until
    -    the process exits (or are explicitly unset). In most cases, it is
    -    unlikely that this behavior was intended by the test author, and, even
    -    if those leaked assignments do not impact other tests today, they can
    -    negatively impact tests added later by authors unaware that the variable
    -    assignments are still hanging around. Address this shortcoming by
    -    ensuring that the assignments are short-lived.
    +    The behavior of a one-shot environment variable assignment of the form
    +    "VAR=val cmd" is undefined according to POSIX when "cmd" is a shell
    +    function. Indeed the behavior differs between shell implementations and
    +    even different versions of the same shell, thus should be avoided.
     
         Signed-off-by: Eric Sunshine <sunshine@sunshineco.com>
     
-:  ---------- > 3:  220ca26d4f check-non-portable-shell: loosen one-shot assignment error message
-:  ---------- > 4:  4910756aab check-non-portable-shell: suggest alternative for `VAR=val shell-func`
3:  89621f72a2 ! 5:  7a15553a5a check-non-portable-shell: improve `VAR=val shell-func` detection
    @@ Metadata
      ## Commit message ##
         check-non-portable-shell: improve `VAR=val shell-func` detection
     
    -    Unlike "VAR=val cmd" one-shot environment variable assignments which
    -    exist only for the invocation of 'cmd', those assigned by "VAR=val
    -    shell-func" exist within the running shell and continue to do so until
    -    the process exits. check-non-portable-shell.pl warns when it detects
    -    such usage since, more often than not, the author who writes such an
    -    invocation is unaware of the undesirable behavior.
    +    The behavior of a one-shot environment variable assignment of the form
    +    "VAR=val cmd" is undefined according to POSIX when "cmd" is a shell
    +    function. Indeed the behavior differs between shell implementations and
    +    even different versions of the same shell, thus should be avoided.
     
    +    As such, check-non-portable-shell.pl warns when it detects such usage.
         However, a limitation of the check is that it only detects such
    -    invocations when variable assignment (i.e. `VAR=val`) is the first
    -    thing on the line. Thus, it can easily be fooled by an invocation such
    -    as:
    +    invocations when variable assignment (i.e. `VAR=val`) is the first thing
    +    on the line. Thus, it can easily be fooled by an invocation such as:
     
             echo X | VAR=val shell-func
     
    @@ t/check-non-portable-shell.pl: sub err {
      		err q(quote "$val" in 'local var=$val');
     -	/^\s*([A-Z0-9_]+=(\w*|(["']).*?\3)\s+)+(\w+)/ and exists($func{$4}) and
     +	/\b([A-Z0-9_]+=(\w*|(["']).*?\3)\s+)+(\w+)/ and !/test_env.+=/ and exists($func{$4}) and
    - 		err '"FOO=bar shell_func" assignment extends beyond "shell_func"';
    + 		err '"FOO=bar shell_func" is not portable (use test_env FOO=bar shell_func)';
      	$line = '';
      	# this resets our $. for each file
4:  7b2e1dd895 < -:  ---------- check-non-portable-shell: suggest alternative for `VAR=val shell-func`
-- 
2.45.2
Previous: Rubén JustoNext: Eric Sunshine
Message 21 of 37 in “improve one-shot variable detection with shell function”
  1. 0/4 improve one-shot variable detection with shell functionEric Sunshine, Jul 22, 2024
  2. 2/4 t4034: fix use of one-shot variable assignment with shell functionEric Sunshine, Jul 22, 2024
  3. 1/4 t3430: modernize one-shot "VAR=val shell-func" invocationEric Sunshine, Jul 22, 2024
  4. Phillip WoodJul 22, 2024
  5. Phillip WoodJul 23, 2024
  6. Eric SunshineJul 26, 2024
  7. Eric SunshineJul 26, 2024
  8. Junio C HamanoJul 22, 2024
  9. Eric SunshineJul 26, 2024
  10. 3/4 check-non-portable-shell: improve `VAR=val shell-func` detectionEric Sunshine, Jul 22, 2024
  11. Rubén JustoJul 22, 2024
  12. Eric SunshineJul 26, 2024
  13. Rubén JustoJul 26, 2024
  14. Kyle LippincottJul 22, 2024
  15. Junio C HamanoJul 22, 2024
  16. Kyle LippincottJul 22, 2024
  17. Junio C HamanoJul 22, 2024
  18. 4/4 check-non-portable-shell: suggest alternative for `VAR=val shell-func`Eric Sunshine, Jul 22, 2024
  19. Rubén JustoJul 22, 2024
  20. Rubén JustoJul 22, 2024
  21. 0/5 improve one-shot variable detection with shell functionEric Sunshine, Jul 26, 2024
  22. 2/5 t4034: fix use of one-shot variable assignment with shell functionEric Sunshine, Jul 26, 2024
  23. 3/5 check-non-portable-shell: loosen one-shot assignment error messageEric Sunshine, Jul 26, 2024
  24. 1/5 t3430: drop unnecessary one-shot "VAR=val shell-func" invocationEric Sunshine, Jul 26, 2024
  25. Junio C HamanoJul 26, 2024
  26. Eric SunshineJul 26, 2024
  27. 4/5 check-non-portable-shell: suggest alternative for `VAR=val shell-func`Eric Sunshine, Jul 26, 2024
  28. Rubén JustoJul 26, 2024
  29. Eric SunshineJul 26, 2024
  30. 5/5 check-non-portable-shell: improve `VAR=val shell-func` detectionEric Sunshine, Jul 26, 2024
  31. Junio C HamanoJul 26, 2024
  32. 0/5 improve one-shot variable detection with shell functionEric Sunshine, Jul 27, 2024
  33. 1/5 t3430: drop unnecessary one-shot "VAR=val shell-func" invocationEric Sunshine, Jul 27, 2024
  34. 2/5 t4034: fix use of one-shot variable assignment with shell functionEric Sunshine, Jul 27, 2024
  35. 4/5 check-non-portable-shell: suggest alternative for `VAR=val shell-func`Eric Sunshine, Jul 27, 2024
  36. 3/5 check-non-portable-shell: loosen one-shot assignment error messageEric Sunshine, Jul 27, 2024
  37. 5/5 check-non-portable-shell: improve `VAR=val shell-func` detectionEric Sunshine, Jul 27, 2024

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.