Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

t: avoid incorrect negated commands #5282

Merged
merged 1 commit into from Feb 23, 2023
Merged

Conversation

bk2204
Copy link
Member

@bk2204 bk2204 commented Feb 10, 2023

When set -e is enabled, not all commands trigger an error exit if they return false. For example, it's clear that commands in an if or while statement don't cause an error if they are false.

What is less obvious, however, is that negated commands and negated pipelines also have no effect on set -e. From POSIX 1003.1-2017 (on sh -e):

When this option is on, if a simple command fails for any of the
reasons listed in Consequences of Shell Errors or returns an exit
status value >0, and is not part of the compound list following a
while, until, or if keyword, and is not a part of an AND or OR list,
and is not a pipeline preceded by the ! reserved word, then the
shell shall immediately exit.

As such, writing something like ! grep will never fail. Fortunately, we can append && exit 1 instead of the ! and that will work correctly.

To make this work, run the following command to make the code properly check the exit status of our commands:

git grep -l '! [a-z]' t | \
  xargs ruby -pi -e '$_.gsub!(/^(\s+)! ([a-z].*)$/, "\\1\\2 && exit 1")'

Fixes #5183

@bk2204 bk2204 force-pushed the negated-grep branch 4 times, most recently from ddbab88 to e959493 Compare February 15, 2023 21:45
When `set -e` is enabled, not all commands trigger an error exit if they
return false.  For example, it's clear that commands in an `if` or
`while` statement don't cause an error if they are false.

What is less obvious, however, is that negated commands and negated
pipelines also have no effect on `set -e`.  From POSIX 1003.1-2017 (on
`sh -e`):

    When this option is on, if a simple command fails for any of the
    reasons listed in Consequences of Shell Errors or returns an exit
    status value >0, and is not part of the compound list following a
    while, until, or if keyword, and is not a part of an AND or OR list,
    and is not a pipeline preceded by the ! reserved word, then the
    shell shall immediately exit.

As such, writing something like `! grep` will never fail.  Fortunately,
we can append `&& exit 1` instead of the `!` and that will work
correctly.

To make this work, run the following command to make the code properly
check the exit status of our commands:

  git grep -l '! [a-z]' t | \
    xargs ruby -pi -e '$_.gsub!(/^(\s+)! ([a-z].*)$/, "\\1\\2 && exit 1")'

Because such a command will still have a non-zero exit status, even if
it doesn't trigger `set -e`, add a `true` if this is the last statement
in a block, so that the test exits successfully and therefore passes.
@bk2204 bk2204 marked this pull request as ready for review February 23, 2023 13:38
@bk2204 bk2204 requested a review from a team as a code owner February 23, 2023 13:38
Copy link
Contributor

@chrisd8088 chrisd8088 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, and catches all the spots I'd noticed, plus some git ones too. Thank you!

@bk2204 bk2204 merged commit 91bac11 into git-lfs:main Feb 23, 2023
@bk2204 bk2204 deleted the negated-grep branch February 23, 2023 17:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Bare negated grep commands in tests do not catch errors
2 participants