Skip to content

fix: add fixes for localvar_inherit #891

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

Merged
merged 10 commits into from
Mar 5, 2023

Conversation

akinomyoga
Copy link
Collaborator

I think this is not the complete list of the places that need a fix for localvar_inherit, but this pending branch starts to conflict with others frequently. I'm not planning to soon scan through all the codebase, so I decided to submit it as is now.

Copy link
Owner

@scop scop left a comment

Choose a reason for hiding this comment

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

Looks good in a way to me, but to be honest, having to add one line per such case along with a comment why it's done feels worse than if we'd instead initialize to the empty string on define and test with [[ $foo ]].

What do you think?

@akinomyoga
Copy link
Collaborator Author

akinomyoga commented Feb 23, 2023

I'm just afraid that it might break functions that would like to distinguish an empty value ''and the unset state. I can carefully check one by one if each function wants to distinguish an empty value and the unset state or not. Let me see...

@akinomyoga akinomyoga marked this pull request as draft February 23, 2023 17:46
@akinomyoga akinomyoga force-pushed the localvar_inherit branch 2 times, most recently from 16e21bf to 3ba87cf Compare February 24, 2023 04:42
@akinomyoga
Copy link
Collaborator Author

akinomyoga commented Feb 24, 2023

I've checked each of the codes that use local var; ...; [[ -v var ]]. In checking them, I found threefour suspicious places so first fixed them (b1ffcfb, 91e29fb, a13d1f1, a03809b). Then, I rewrote the codes in 7a4dcfe and 29007b5.

@akinomyoga akinomyoga marked this pull request as ready for review February 24, 2023 04:48
@akinomyoga akinomyoga force-pushed the localvar_inherit branch 2 times, most recently from cce6850 to 29007b5 Compare February 24, 2023 06:27
Copy link
Owner

@scop scop left a comment

Choose a reason for hiding this comment

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

Nice, looks better to me now.

A couple of points about the $has_ variables (no need to block this one for that, we can look into addressing them in followup PR's if we like). Leaving up to you to decide if we postpone them or do some of it here.

  1. I suppose many of the cases where a $has_* was introduced here are because of bugs in existing implementations that fail to consider the empty string appropriately. Would be good to clean those up.

  2. We have some precedent in _split_longopt and $split (and some other cases I think) in making vars used for booleans to have true or false values which can be tested by executing instead of doing the variable emptiness check (i.e. testing e.g. if $foo; ... instead of if [[ $foo ]]; .... I think that reads cleaner, we might want to have a look at doing that for the cases remaining if/after we weed out the cases where the separate boolean is not required in the first place.

shellcheck requires us putting '' or "" on the right-hand sides of
variable assignments unless `=' is at the end of line.  In the current
codebase, there are variations on var='' and var="", where most
instances are latter.  In this commit, I rewrite all var='' to match
the majority var="".
In commit d0a0eb5, [[ ! $mode ]] in completions/cvs is converted to
[[ ! -v mode ]].  However, the code two lines above, mode="", which
intended to turn [[ ! $mode ]] true, became not working by this
change.  This commit tries to fix it.
In the original code, the existence of $1 was not checked after
performing `shift`.  This would cause an error when `set -o nounset`
is set.  This commit adds a check.
The function `_gtar` calls `__tar_try_mode`, and `__tar_try_mode`
checks the state of the previous-scope `basic_tar`.  However,
`__tar_try_mode` called from `_gtar` references the state of the
global scope because `_gtar` does not declare `basic_tar`.  We need to
declare `basic_tar` local to `_gtar` the same as done in
`__posix_tar`.
@akinomyoga akinomyoga force-pushed the localvar_inherit branch 2 times, most recently from 4eb79b8 to cfe3487 Compare February 26, 2023 02:01
When the assigned values are ensured to be non-empty strings, [[ -v
var ]] is converted to [[ $var ]].  Otherwise, another local variable
`has_var={false,true}` is added to manage the assigned state, and [[
-v var ]] is converted to "$has_var".  I here did not consider whether
the empty value of $var actually makes a sense or not.
@akinomyoga
Copy link
Collaborator Author

akinomyoga commented Feb 26, 2023

  1. I suppose many of the cases where a $has_* was introduced here are because of bugs in existing implementations that fail to consider the empty string appropriately. Would be good to clean those up.

Currently, I do not have a good idea of how to handle these cases, so I think I'd postpone the resolution of these cases.

The remaining $has_* are all related to empty arguments stored in words, which originally come from COMP_WORDS. We usually don't have an empty element in COMP_WORDS (e.g., the empty argument '' or "" is usually stored in COMP_WORDS literally as '' or ""), but COMP_WORDS can still contain empty elements in some cases (e.g., cmd arg [TAB]). Having an empty element in words itself is not a bug because the empty element is coming from the user content, and we cannot output error or warning messages in the middle of completions when we find the empty element.


2. We have some precedent in _split_longopt and $split (and some other cases I think)

These are the other cases (excluding $split):

./bash_completion:823:    if $deduplicate; then
./completions/export:55:            if ! $remove && [[ $action != function ]]; then
./completions/find:74:    if ! $exprfound && [[ $cur != [-\(\),\!]* ]]; then
./completions/fio:121:                        if $in_values; then
./completions/jarsigner:43:    if ! $jar; then
./completions/lzip:38:    if $decompress; then
./completions/pack200:56:    if ! $pack; then
./completions/pack200:68:    elif ! $jar; then
./completions/pytest:115:            if $in_class && [[ $line =~ ^[[:space:]]+(async[[:space:]]+)?def[[:space:]]+(test_[A-Za-z0-9_]+) ]]; then
./completions/route:23:        $found || COMPREPLY+=("$opt")
./completions/ssh:490:    if $dirsonly; then
./completions/timeout:11:            if $found; then
./completions/unpack200:36:    if ! $pack; then
./completions/unpack200:44:    elif ! $jar; then

Another approach seems to prepare a variable that has a value 0 or 1, and test it with ((var == 0)), etc.

./completions/mcrypt:56:                decrypt=1
./completions/postcat:22:        [[ $idx == -q ]] && qfile=1 && break
./completions/svcadm:32:        exact_mode=1
./completions/tar:174:        old_opt_progress=1
./completions/tar:179:        old_opt_used=1
./completions/tar:204:    first_arg=1
./completions/wodim:72:            track_mode=1

The other boolean flags have been assigning a non-empty value and testing it with [[ -v $var ]], which were now converted to [[ $var ]]. This is the approach that I used for these new has_* variables.

./bash_completion:1909:            4) ipv4=1 ;;
./bash_completion:1910:            6) ipv6=1 ;;
./completions/tar:694:    basic_tar=yes
./completions/upgradepkg:20:        [[ ${COMPREPLY-} ]] || nofiles=1

@akinomyoga
Copy link
Collaborator Author

akinomyoga commented Feb 26, 2023

I have switched has_xxx to use true / false and "$has_xxx" / ! "$has_xxx" (cfe3487b..ace9cd66). I kept other existing cases.

@akinomyoga akinomyoga merged commit ba95f05 into scop:master Mar 5, 2023
@akinomyoga akinomyoga deleted the localvar_inherit branch March 5, 2023 11:48
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.

2 participants