Skip to content

Commit

Permalink
interp: allow unsetting global vars from inside a function again
Browse files Browse the repository at this point in the history
In dc2e11e "unset" of a global var inside a function was broken,
as the special handling of "export" or "readonly" in function scope
introduced in that commit also incorrectly captured "unset",
calling "parent.Set" with the previous value.

Tweak the logic so that "unset" is handled like it did before,
which fixes the regression.

Fixes #806
  • Loading branch information
dtrudg authored and mvdan committed Feb 2, 2022
1 parent de81db6 commit 113ed66
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 4 deletions.
4 changes: 4 additions & 0 deletions interp/interp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2381,6 +2381,10 @@ set +o pipefail
"x=after\nbefore\n",
},

// unset global from inside function
{"f() { unset foo; echo $foo; }; foo=bar; f", "\n"},
{"f() { unset foo; }; foo=bar; f; echo $foo", "\n"},

// name references
{"declare -n foo=bar; bar=etc; [[ -R foo ]]", ""},
{"declare -n foo=bar; bar=etc; [ -R foo ]", ""},
Expand Down
12 changes: 8 additions & 4 deletions interp/vars.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,21 @@ func (o *overlayEnviron) Get(name string) expand.Variable {
}

func (o *overlayEnviron) Set(name string, vr expand.Variable) error {
// "foo=bar" in a function updates the global scope, unless the variable
// has been declared as local.
// Manipulation of a global var inside a function
if o.funcScope && !vr.Local && !o.values[name].Local {
// "foo=bar" on a global var in a function updates the global scope
if vr.IsSet() {
return o.parent.(expand.WriteEnviron).Set(name, vr)
}
// "foo=bar" followed by "export foo" or "readonly foo"
if !vr.IsSet() {
if vr.Exported || vr.ReadOnly {
prev := o.Get(name)
prev.Exported = prev.Exported || vr.Exported
prev.ReadOnly = prev.ReadOnly || vr.ReadOnly
vr = prev
return o.parent.(expand.WriteEnviron).Set(name, vr)
}
return o.parent.(expand.WriteEnviron).Set(name, vr)
// "unset" is handled below
}

prev := o.Get(name)
Expand Down

0 comments on commit 113ed66

Please sign in to comment.