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

Fix incorrect handling of boolean flags for builtin commands #11492

Merged
merged 13 commits into from Jan 11, 2024

Conversation

NotLebedev
Copy link
Contributor

@NotLebedev NotLebedev commented Jan 6, 2024

Description

Possible fix of #11456
This PR fixes a bug where builtin commands did not respect the logic of dynamically passed boolean flags. The reason is has_flag method did not evaluate and take into consideration expression used with flag.

To address this issue a solution is proposed:

  1. has_flag method is moved to CallExt and new logic to evaluate expression and check if it is a boolean value is added
  2. has_flag_const method is added to CallExt which is a constant version of has_flag
  3. has_named method is added to Call which is basically the old logic of has_flag
  4. All usages of has_flag in code are updated, mostly to pass engine_state and stack to new has_flag. In run_const commands it is replaced with has_flag_const. And in a few select places: parser, to nuon and into string old logic via has_named is used.

User-Facing Changes

Explicit values of boolean flags are now respected in builtin commands.
Before:
image
After:
image

Another example:
Before:
image
After:
image

Tests + Formatting

Added test reproducing some variants of original issue.

@NotLebedev NotLebedev changed the title Has flag values Fix incorrect handling of boolean flags for builtin commands Jan 6, 2024
@NotLebedev NotLebedev marked this pull request as ready for review January 6, 2024 21:31
@kubouch
Copy link
Contributor

kubouch commented Jan 6, 2024

The fix seems good. Two points:

@kubouch
Copy link
Contributor

kubouch commented Jan 6, 2024

Also, since you essentially renamed the old has_flag() to has_named(), shouldn't has_named() be removed because it has a faulty logic? What is the reason for keeping it?

@NotLebedev
Copy link
Contributor Author

  1. Added test for some flags of ls command but I am not sure how to make a more general test (and if it is needed)
  2. Call is part of nu_protocol::ast and its methods don't know anything about nu_protocol::engine and dont call eval_expression method. The trait CallExt is a collection of methods that can evaluate arguments of call
  3. Actually the reason was me. I misunderstood what it did in parse_keyword.rs and though that the old logic was necessary there. But actually it should be the same, so I replaced all remaining usages of has_named (also some in commands) and deleted it.

Test sandbox does not have a OS-agnostic way of creating hidden files
which breaks `ls --all` test on windows
@kubouch
Copy link
Contributor

kubouch commented Jan 7, 2024

OK, the test looks good enough.

One thing that I also noticed is that the parser shouldn't depend on the engine. If you check, nu-engine is used only in one place in the parser and that case should be removed in some other PR. So, I think the has_flag_const() should be moved to Call in nu-protocol. This should be possible as you only need the StateWorkingSet, you don't need the engine's Stack.

@NotLebedev
Copy link
Contributor Author

If you check, nu-engine is used only in one place in the parser and that case should be removed in some other PR. So, I think the has_flag_const() should be moved to Call in nu-protocol. This should be possible as you only need the StateWorkingSet, you don't need the engine's Stack.

That's fair. I think get_flag_const should also be moved to Call for consistency. I will take a look at this and submit a PR

@kubouch
Copy link
Contributor

kubouch commented Jan 9, 2024

(retroactively added the label to merge after the dust settles around the new release)

OK, could you then make a new PR moving the xxx_const() from CallExt to Call and while at it, you could also remove nu-engine dependency from the parser altogether if you don't mind. The move from CallExt to Call can also be a part of this PR, that would make me feel better not adding CallExt import to the parser 😆.

@NotLebedev
Copy link
Contributor Author

Done. Moved all _const methods from CallExt to Call. Also moved an auxiliary method rest_iter_flattened that was used by const mehtods (and in general had no place being part of CallExt)

@kubouch
Copy link
Contributor

kubouch commented Jan 11, 2024

OK, thanks, let's try it out!

@kubouch kubouch merged commit 1867bb1 into nushell:main Jan 11, 2024
19 checks passed
@kubouch kubouch added the pr:bugfix This PR fixes some bug label Jan 11, 2024
@kubouch kubouch added this to the v0.90.0 milestone Jan 18, 2024
fdncred pushed a commit that referenced this pull request Jan 22, 2024
# Description
#11492 fixed flags for builtin commands but I missed that plugins don't
use the same `has_flag` that builtins do. This PR addresses this.

Unfortunately this means that return value of `has_flag` needs to change
from `bool` to `Result<bool, ShellError>` to produce an error when
explicit value is not a boolean (just like in case of `has_flag` for
builtin commands. It is not possible to check this in
`EvaluatedCall::try_from_call` because

# User-Facing Changes
Passing explicit values to flags of plugin commands (like `--flag=true`
`--flag=false`) should work now.
BREAKING: changed return value of `EvaluatedCall::has_flag` method from
`bool` to `Result<bool, ShellError>`

# Tests + Formatting
Added tests and updated documentation and examples
@kik4444
Copy link
Contributor

kik4444 commented Feb 5, 2024

Hi, @NotLebedev, it seems that b90fe82 introduced a regression. When I build the latest nushell:main branch and try to run something like touch -r deps build I get an error

Error: nu::shell::cant_convert

  × Can't convert to bool.
   ╭─[entry #3:1:1]
 1 │ touch -r deps build
   ·          ──┬─
   ·            ╰── can't convert string to bool
   ╰────

On commits prior to that there's no issues. Could you check what went wrong?

dmatos2012 pushed a commit to dmatos2012/nushell that referenced this pull request Feb 20, 2024
…#11492)

# Description
Possible fix of nushell#11456
This PR fixes a bug where builtin commands did not respect the logic of
dynamically passed boolean flags. The reason is
[has_flag](https://github.com/nushell/nushell/blob/6f59abaf4310487f7a6319437be6ec61abcbc3b9/crates/nu-protocol/src/ast/call.rs#L204C5-L212C6)
method did not evaluate and take into consideration expression used with
flag.

To address this issue a solution is proposed:
1. `has_flag` method is moved to `CallExt` and new logic to evaluate
expression and check if it is a boolean value is added
2. `has_flag_const` method is added to `CallExt` which is a constant
version of `has_flag`
3. `has_named` method is added to `Call` which is basically the old
logic of `has_flag`
4. All usages of `has_flag` in code are updated, mostly to pass
`engine_state` and `stack` to new `has_flag`. In `run_const` commands it
is replaced with `has_flag_const`. And in a few select places: parser,
`to nuon` and `into string` old logic via `has_named` is used.

# User-Facing Changes
Explicit values of boolean flags are now respected in builtin commands.
Before:

![image](https://github.com/nushell/nushell/assets/17511668/f9fbabb2-3cfd-43f9-ba9e-ece76d80043c)
After:

![image](https://github.com/nushell/nushell/assets/17511668/21867596-2075-437f-9c85-45563ac70083)

Another example:
Before:

![image](https://github.com/nushell/nushell/assets/17511668/efdbc5ca-5227-45a4-ac5b-532cdc2bbf5f)
After:

![image](https://github.com/nushell/nushell/assets/17511668/2907d5c5-aa93-404d-af1c-21cdc3d44646)


# Tests + Formatting
Added test reproducing some variants of original issue.
dmatos2012 pushed a commit to dmatos2012/nushell that referenced this pull request Feb 20, 2024
# Description
nushell#11492 fixed flags for builtin commands but I missed that plugins don't
use the same `has_flag` that builtins do. This PR addresses this.

Unfortunately this means that return value of `has_flag` needs to change
from `bool` to `Result<bool, ShellError>` to produce an error when
explicit value is not a boolean (just like in case of `has_flag` for
builtin commands. It is not possible to check this in
`EvaluatedCall::try_from_call` because

# User-Facing Changes
Passing explicit values to flags of plugin commands (like `--flag=true`
`--flag=false`) should work now.
BREAKING: changed return value of `EvaluatedCall::has_flag` method from
`bool` to `Result<bool, ShellError>`

# Tests + Formatting
Added tests and updated documentation and examples
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants