Declare that two "not" keywords cancel each other out

"not not return 34" exits with 34, not 1.  This behavior is pretty
surprising but benign. I think it's very unlikely that anyone relies
on the opposite behavior, because using two "not" decorators in one
job is weird, and code that compares not's raw exit code is rare.

The behavior doesn't match our docs, but it's not worth changing the
docs because that would confuse newcomers. Add a test to cement the
behavior and a comment to explain this is intentional.

I considered adding the comment at
parse_execution_context_t::populate_not_process where this behavior
is implemented but the field defintion seems even better, because I
expect programmers to read that first.

Closes #8377
This commit is contained in:
Johannes Altmanninger 2021-12-28 16:38:53 +01:00
parent 4ceed7c482
commit 65b34a12c0
2 changed files with 11 additions and 0 deletions

View File

@ -403,6 +403,7 @@ class job_t : noncopyable_t {
bool notified_of_stop{false}; bool notified_of_stop{false};
/// Whether the exit status should be negated. This flag can only be set by the not builtin. /// Whether the exit status should be negated. This flag can only be set by the not builtin.
/// Two "not" prefixes on a single job cancel each other out.
bool negate{false}; bool negate{false};
/// This job is disowned, and should be removed from the active jobs list. /// This job is disowned, and should be removed from the active jobs list.

10
tests/checks/not.fish Normal file
View File

@ -0,0 +1,10 @@
#RUN: %fish %s
not true
echo $status
# CHECK: 1
# Two "not" prefixes on a single job cancel each other out.
not not sh -c 'exit 34'
echo $status
# CHECK: 34