From 04205f36be0fe355c560f35a5c53d49c36ea724b Mon Sep 17 00:00:00 2001 From: Fabian Homborg Date: Wed, 21 Jun 2017 00:47:11 +0200 Subject: [PATCH] Copy local-exported variables When executing a function, local-exported (`set -lx`) variables previously were not accessible at all. This is weird e.g. in case of aliases, since ```fish set -lx PAGER cat git something # which will call $PAGER ``` would not work if `git` were a function, even if that ends up calling `command git`. Now, we copy these variables, so functions get a local-exported copy. ```fish function x echo $var set var wurst echo $var end set -lx var banana x # prints "banana" and "wurst" echo $var # prints "banana" ``` One weirdness here is that, if a variable is both local and global, the local-copy takes precedence: ```fish set -gx var banana set -lx var pineapple echo $var # prints "pineapple" x # from above, prints "pineapple" and "wurst" echo $var # still prints "pineapple" set -el var # deletes local version echo $var # "banana" again ``` I don't think there is any more consistent way to handle this - the local version is the one that is accessed first, so it should also be written to first. Global-exported variables are _not_ copied, instead they still offer full read-write access. --- src/env.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/env.cpp b/src/env.cpp index 2a4cf434a..a54f47e0e 100644 --- a/src/env.cpp +++ b/src/env.cpp @@ -179,6 +179,18 @@ struct var_stack_t { void var_stack_t::push(bool new_scope) { std::unique_ptr node(new env_node_t(new_scope)); + + // Copy local-exported variables + auto top_node = top.get(); + if (!(top_node == this->global_env)) { + for (auto& var : top_node->env) { + if (var.second.exportv) { + // This should copy var + node->env.insert(var); + } + } + } + node->next = std::move(this->top); this->top = std::move(node); if (new_scope && local_scope_exports(this->top.get())) {