On Fri, Oct 13, 2023 at 5:35 PM Chet Ramey <chet.ra...@case.edu> wrote: > This is what happens. First, you have to remember that variables supplied > as temporary assignments to builtins like eval and source persist for the > entire life of that builtin's execution, and appear in the environment of > child processes those builtins create (this is what the man page text > "added to the environment of the executed command" means for a builtin).
Yep, that part I'm extremely familiar with... > these temporary variables can shadow global variables. ...but I was not aware of that part in this context! That's what I was missing. > 6. inner.sh calls unset, which unsets the temporary variable (clone) and > `unshadows' the global variable (clone2) And that makes it very clear what's going on. Thank you for that walkthrough. > There is code in bash to make a unsetting a function's local copy of a > dynamically-scoped variable that shadows a global variable remain `unset' > instead of unshadowing the global, but I've never done that for source or > eval. It's not clear that would help in this case, either -- it depends > on what the rest of the code does and expects. I could see "helpful or not" going either way, honestly. In this specific case, there isn't really any "rest of the code" that's relevant to the variables being shadowed, etc, it's just the "[[ -v foo ]]" tests to see where along the cloning process we are. The only part I didn't include in the example was the code that does such tests to see if it's inside the cloned copy, and if it is, arranges to delete the temporary copy on exit. (The arbitrary top-level script might also be doing on-exit actions, so there's this whole thing of registering a chain of functions to be called by the single permitted EXIT trap. All of that is working, and is independent of the optional cloning, so I didn't want to litter up the example with distractions.) Activating the code you mention for source/eval might have helped for my particular use case, in that it would have saved me some debugging time that I would otherwise have spent... I dunno, probably drinking more coffee. But it would likely have introduced confusion for all the other users who were accustomed to the shadowing behavior, and caused them to spend even more time debugging and writing bug report emails. I agree probably not helpful to have that code for source/eval. :-) We'll either be writing a solid comment in the code explaining why that particular 'unset' has to be where it is, or we'll change to testing the values of those trigger variables instead of just "is it set or not" and using varying values to track where in the process it is ("clone" vs "clone2" in your example). Thank you again! -Ti