mirror of
https://github.com/fish-shell/fish-shell
synced 2024-11-15 09:27:38 +00:00
Introduce env_stack_t
This will instance environment variable stacks.
This commit is contained in:
parent
391af6af0c
commit
8d7cae63ff
3 changed files with 170 additions and 53 deletions
142
src/env.cpp
142
src/env.cpp
|
@ -141,8 +141,6 @@ class env_node_t {
|
|||
|
||||
static std::mutex env_lock;
|
||||
|
||||
static bool local_scope_exports(const env_node_t *n);
|
||||
|
||||
// A class wrapping up a variable stack
|
||||
// Currently there is only one variable stack in fish,
|
||||
// but we can imagine having separate (linked) stacks
|
||||
|
@ -163,7 +161,7 @@ struct var_stack_t {
|
|||
void mark_changed_exported() { has_changed_exported = true; }
|
||||
void update_export_array_if_necessary();
|
||||
|
||||
var_stack_t() : top(new env_node_t(false)) { this->global_env = this->top.get(); }
|
||||
var_stack_t() : top(new env_node_t(false)), global_env(top.get()) {}
|
||||
|
||||
// Pushes a new node onto our stack
|
||||
// Optionally creates a new scope for the node
|
||||
|
@ -180,6 +178,10 @@ struct var_stack_t {
|
|||
// Returns the scope used for unspecified scopes. An unspecified scope is either the topmost
|
||||
// shadowing scope, or the global scope if none. This implements the default behavior of `set`.
|
||||
env_node_t *resolve_unspecified_scope();
|
||||
|
||||
private:
|
||||
bool local_scope_exports(const env_node_t *n) const;
|
||||
void get_exported(const env_node_t *n, var_table_t &h) const;
|
||||
};
|
||||
|
||||
void var_stack_t::push(bool new_scope) {
|
||||
|
@ -272,11 +274,12 @@ env_node_t *var_stack_t::resolve_unspecified_scope() {
|
|||
return node ? node : this->global_env;
|
||||
}
|
||||
|
||||
// Get the global variable stack
|
||||
static var_stack_t &vars_stack() {
|
||||
static var_stack_t global_stack;
|
||||
return global_stack;
|
||||
}
|
||||
env_stack_t::env_stack_t() : vars_(make_unique<var_stack_t>()) {}
|
||||
|
||||
// Get the variable stack
|
||||
var_stack_t &env_stack_t::vars_stack() { return *vars_; }
|
||||
|
||||
const var_stack_t &env_stack_t::vars_stack() const { return *vars_; }
|
||||
|
||||
/// Universal variables global instance. Initialized in env_init.
|
||||
static env_universal_t *s_universal_variables = NULL;
|
||||
|
@ -616,11 +619,11 @@ static void react_to_variable_change(const wchar_t *op, const wcstring &key) {
|
|||
|
||||
/// Universal variable callback function. This function makes sure the proper events are triggered
|
||||
/// when an event occurs.
|
||||
static void universal_callback(const callback_data_t &cb) {
|
||||
static void universal_callback(env_stack_t *stack, const callback_data_t &cb) {
|
||||
const wchar_t *op = cb.is_erase() ? L"ERASE" : L"SET";
|
||||
|
||||
react_to_variable_change(op, cb.key);
|
||||
vars_stack().mark_changed_exported();
|
||||
stack->mark_changed_exported();
|
||||
|
||||
event_t ev = event_t::variable_event(cb.key);
|
||||
ev.arguments.push_back(L"VARIABLE");
|
||||
|
@ -650,7 +653,7 @@ static void env_set_termsize() {
|
|||
}
|
||||
|
||||
/// Update the PWD variable directory from the result of getcwd().
|
||||
void env_set_pwd_from_getcwd() {
|
||||
void env_stack_t::set_pwd_from_getcwd() {
|
||||
wcstring cwd = wgetcwd();
|
||||
if (cwd.empty()) {
|
||||
debug(0,
|
||||
|
@ -662,7 +665,7 @@ void env_set_pwd_from_getcwd() {
|
|||
|
||||
/// Allow the user to override the limit on how much data the `read` command will process.
|
||||
/// This is primarily for testing but could be used by users in special situations.
|
||||
void env_set_read_limit() {
|
||||
void env_stack_t::set_read_limit() {
|
||||
auto read_byte_limit_var = env_get(L"fish_read_limit");
|
||||
if (!read_byte_limit_var.missing_or_empty()) {
|
||||
size_t limit = fish_wcstoull(read_byte_limit_var->as_string().c_str());
|
||||
|
@ -674,7 +677,9 @@ void env_set_read_limit() {
|
|||
}
|
||||
}
|
||||
|
||||
wcstring env_get_pwd_slash() {
|
||||
void env_stack_t::mark_changed_exported() { vars_stack().mark_changed_exported(); }
|
||||
|
||||
wcstring env_stack_t::get_pwd_slash() {
|
||||
// Return "/" if PWD is missing.
|
||||
// See https://github.com/fish-shell/fish-shell/issues/5080
|
||||
auto pwd_var = env_get(L"PWD");
|
||||
|
@ -716,13 +721,13 @@ void misc_init() {
|
|||
}
|
||||
}
|
||||
|
||||
static void env_universal_callbacks(const callback_data_list_t &callbacks) {
|
||||
static void env_universal_callbacks(env_stack_t *stack, const callback_data_list_t &callbacks) {
|
||||
for (const callback_data_t &cb : callbacks) {
|
||||
universal_callback(cb);
|
||||
universal_callback(stack, cb);
|
||||
}
|
||||
}
|
||||
|
||||
void env_universal_barrier() {
|
||||
void env_stack_t::universal_barrier() {
|
||||
ASSERT_IS_MAIN_THREAD();
|
||||
if (!uvars()) return;
|
||||
|
||||
|
@ -732,7 +737,7 @@ void env_universal_barrier() {
|
|||
universal_notifier_t::default_notifier().post_notification();
|
||||
}
|
||||
|
||||
env_universal_callbacks(callbacks);
|
||||
env_universal_callbacks(this, callbacks);
|
||||
}
|
||||
|
||||
static void handle_fish_term_change(const wcstring &op, const wcstring &var_name) {
|
||||
|
@ -976,7 +981,7 @@ void env_init(const struct config_paths_t *paths /* or NULL */) {
|
|||
// initialize the PWD variable if necessary
|
||||
// Note we may inherit a virtual PWD that doesn't match what getcwd would return; respect that.
|
||||
if (env_get(L"PWD").missing_or_empty()) {
|
||||
env_set_pwd_from_getcwd();
|
||||
env_stack_t::principal().set_pwd_from_getcwd();
|
||||
}
|
||||
env_set_termsize(); // initialize the terminal size variables
|
||||
env_set_read_limit(); // initialize the read_byte_limit
|
||||
|
@ -1000,7 +1005,7 @@ void env_init(const struct config_paths_t *paths /* or NULL */) {
|
|||
s_universal_variables = new env_universal_t(L"");
|
||||
callback_data_list_t callbacks;
|
||||
s_universal_variables->initialize(callbacks);
|
||||
env_universal_callbacks(callbacks);
|
||||
env_universal_callbacks(&env_stack_t::principal(), callbacks);
|
||||
|
||||
// Now that the global scope is fully initialized, add a toplevel local scope. This same local
|
||||
// scope will persist throughout the lifetime of the fish process, and it will ensure that `set
|
||||
|
@ -1010,7 +1015,7 @@ void env_init(const struct config_paths_t *paths /* or NULL */) {
|
|||
|
||||
/// Search all visible scopes in order for the specified key. Return the first scope in which it was
|
||||
/// found.
|
||||
static env_node_t *env_get_node(const wcstring &key) {
|
||||
env_node_t *env_stack_t::get_node(const wcstring &key) {
|
||||
env_node_t *env = vars_stack().top.get();
|
||||
while (env != NULL) {
|
||||
if (env->find_entry(key)) break;
|
||||
|
@ -1033,7 +1038,7 @@ static int set_umask(const wcstring_list_t &list_val) {
|
|||
|
||||
/// Set a universal variable, inheriting as applicable from the given old variable.
|
||||
static void env_set_internal_universal(const wcstring &key, wcstring_list_t val,
|
||||
env_mode_flags_t input_var_mode) {
|
||||
env_mode_flags_t input_var_mode, env_stack_t *stack) {
|
||||
ASSERT_IS_MAIN_THREAD();
|
||||
if (!uvars()) return;
|
||||
env_mode_flags_t var_mode = input_var_mode;
|
||||
|
@ -1068,7 +1073,7 @@ static void env_set_internal_universal(const wcstring &key, wcstring_list_t val,
|
|||
uvars()->set(key, new_var);
|
||||
env_universal_barrier();
|
||||
if (new_var.exports() || (oldvar && oldvar->exports())) {
|
||||
vars_stack().mark_changed_exported();
|
||||
stack->mark_changed_exported();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1088,8 +1093,7 @@ static void env_set_internal_universal(const wcstring &key, wcstring_list_t val,
|
|||
/// * ENV_SCOPE, the variable cannot be set in the given scope. This applies to readonly/electric
|
||||
/// variables set from the local or universal scopes, or set as exported.
|
||||
/// * ENV_INVALID, the variable value was invalid. This applies only to special variables.
|
||||
static int env_set_internal(const wcstring &key, env_mode_flags_t input_var_mode,
|
||||
wcstring_list_t val) {
|
||||
int env_stack_t::set_internal(const wcstring &key, env_mode_flags_t input_var_mode, wcstring_list_t val) {
|
||||
ASSERT_IS_MAIN_THREAD();
|
||||
env_mode_flags_t var_mode = input_var_mode;
|
||||
bool has_changed_old = vars_stack().has_changed_exported;
|
||||
|
@ -1100,7 +1104,7 @@ static int env_set_internal(const wcstring &key, env_mode_flags_t input_var_mode
|
|||
wcstring val_canonical = val.front();
|
||||
path_make_canonical(val_canonical);
|
||||
if (val.front() != val_canonical) {
|
||||
return env_set_internal(key, var_mode, {val_canonical});
|
||||
return set_internal(key, var_mode, {val_canonical});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1121,12 +1125,12 @@ static int env_set_internal(const wcstring &key, env_mode_flags_t input_var_mode
|
|||
|
||||
if (var_mode & ENV_UNIVERSAL) {
|
||||
if (uvars()) {
|
||||
env_set_internal_universal(key, std::move(val), var_mode);
|
||||
env_set_internal_universal(key, std::move(val), var_mode, this);
|
||||
}
|
||||
} else {
|
||||
// Determine the node.
|
||||
bool has_changed_new = false;
|
||||
env_node_t *preexisting_node = env_get_node(key);
|
||||
env_node_t *preexisting_node = get_node(key);
|
||||
maybe_t<env_var_t::env_var_flags_t> preexisting_flags{};
|
||||
if (preexisting_node != NULL) {
|
||||
var_table_t::const_iterator result = preexisting_node->env.find(key);
|
||||
|
@ -1157,7 +1161,7 @@ static int env_set_internal(const wcstring &key, env_mode_flags_t input_var_mode
|
|||
}
|
||||
if (uvars() && uvars()->get(key)) {
|
||||
// Modifying an existing universal variable.
|
||||
env_set_internal_universal(key, std::move(val), var_mode);
|
||||
env_set_internal_universal(key, std::move(val), var_mode, this);
|
||||
done = true;
|
||||
} else {
|
||||
// New variable with unspecified scope
|
||||
|
@ -1229,26 +1233,26 @@ static int env_set_internal(const wcstring &key, env_mode_flags_t input_var_mode
|
|||
}
|
||||
|
||||
/// Sets the variable with the specified name to the given values.
|
||||
int env_set(const wcstring &key, env_mode_flags_t mode, wcstring_list_t vals) {
|
||||
return env_set_internal(key, mode, std::move(vals));
|
||||
int env_stack_t::set(const wcstring &key, env_mode_flags_t mode, wcstring_list_t vals) {
|
||||
return set_internal(key, mode, std::move(vals));
|
||||
}
|
||||
|
||||
/// Sets the variable with the specified name to a single value.
|
||||
int env_set_one(const wcstring &key, env_mode_flags_t mode, wcstring val) {
|
||||
int env_stack_t::set_one(const wcstring &key, env_mode_flags_t mode, wcstring val) {
|
||||
wcstring_list_t vals;
|
||||
vals.push_back(std::move(val));
|
||||
return env_set_internal(key, mode, std::move(vals));
|
||||
return set_internal(key, mode, std::move(vals));
|
||||
}
|
||||
|
||||
/// Sets the variable with the specified name without any (i.e., zero) values.
|
||||
int env_set_empty(const wcstring &key, env_mode_flags_t mode) {
|
||||
return env_set_internal(key, mode, {});
|
||||
int env_stack_t::set_empty(const wcstring &key, env_mode_flags_t mode) {
|
||||
return set_internal(key, mode, {});
|
||||
}
|
||||
|
||||
/// Attempt to remove/free the specified key/value pair from the specified map.
|
||||
///
|
||||
/// \return zero if the variable was not found, non-zero otherwise
|
||||
static bool try_remove(env_node_t *n, const wchar_t *key, int var_mode) {
|
||||
bool env_stack_t::try_remove(env_node_t *n, const wchar_t *key, int var_mode) {
|
||||
if (n == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1256,7 +1260,7 @@ static bool try_remove(env_node_t *n, const wchar_t *key, int var_mode) {
|
|||
var_table_t::iterator result = n->env.find(key);
|
||||
if (result != n->env.end()) {
|
||||
if (result->second.exports()) {
|
||||
vars_stack().mark_changed_exported();
|
||||
mark_changed_exported();
|
||||
}
|
||||
n->env.erase(result);
|
||||
return true;
|
||||
|
@ -1272,7 +1276,7 @@ static bool try_remove(env_node_t *n, const wchar_t *key, int var_mode) {
|
|||
return try_remove(n->next.get(), key, var_mode);
|
||||
}
|
||||
|
||||
int env_remove(const wcstring &key, int var_mode) {
|
||||
int env_stack_t::remove(const wcstring &key, int var_mode) {
|
||||
ASSERT_IS_MAIN_THREAD();
|
||||
env_node_t *first_node;
|
||||
int erased = 0;
|
||||
|
@ -1345,7 +1349,7 @@ env_var_t::env_var_flags_t env_var_t::flags_for(const wchar_t *name) {
|
|||
return result;
|
||||
}
|
||||
|
||||
maybe_t<env_var_t> env_get(const wcstring &key, env_mode_flags_t mode) {
|
||||
maybe_t<env_var_t> env_stack_t::get(const wcstring &key, env_mode_flags_t mode) const {
|
||||
const bool has_scope = mode & (ENV_LOCAL | ENV_GLOBAL | ENV_UNIVERSAL);
|
||||
const bool search_local = !has_scope || (mode & ENV_LOCAL);
|
||||
const bool search_global = !has_scope || (mode & ENV_GLOBAL);
|
||||
|
@ -1383,7 +1387,7 @@ maybe_t<env_var_t> env_get(const wcstring &key, env_mode_flags_t mode) {
|
|||
|
||||
if (search_local || search_global) {
|
||||
scoped_lock locker(env_lock); // lock around a local region
|
||||
env_node_t *env = search_local ? vars_stack().top.get() : vars_stack().global_env;
|
||||
const env_node_t *env = search_local ? vars_stack().top.get() : vars_stack().global_env;
|
||||
|
||||
while (env != NULL) {
|
||||
if (env == vars_stack().global_env && !search_global) {
|
||||
|
@ -1422,11 +1426,46 @@ maybe_t<env_var_t> env_get(const wcstring &key, env_mode_flags_t mode) {
|
|||
return none();
|
||||
}
|
||||
|
||||
/// Legacy versions.
|
||||
maybe_t<env_var_t> env_get(const wcstring &key, env_mode_flags_t mode) {
|
||||
return env_stack_t::principal().get(key, mode);
|
||||
}
|
||||
|
||||
int env_set(const wcstring &key, env_mode_flags_t mode, wcstring_list_t vals) {
|
||||
return env_stack_t::principal().set(key, mode, std::move(vals));
|
||||
}
|
||||
|
||||
int env_set_one(const wcstring &key, env_mode_flags_t mode, wcstring val) {
|
||||
return env_stack_t::principal().set_one(key, mode, std::move(val));
|
||||
}
|
||||
|
||||
int env_set_empty(const wcstring &key, env_mode_flags_t mode) {
|
||||
return env_stack_t::principal().set_empty(key, mode);
|
||||
}
|
||||
|
||||
int env_remove(const wcstring &key, int mode) { return env_stack_t::principal().remove(key, mode); }
|
||||
|
||||
void env_push(bool new_scope) { env_stack_t::principal().push(new_scope); }
|
||||
|
||||
void env_pop() { env_stack_t::principal().pop(); }
|
||||
|
||||
void env_universal_barrier() { env_stack_t::principal().universal_barrier(); }
|
||||
|
||||
const char *const *env_export_arr() { return env_stack_t::principal().export_arr(); }
|
||||
|
||||
void env_set_argv(const wchar_t *const *argv) { return env_stack_t::principal().set_argv(argv); }
|
||||
|
||||
wcstring_list_t env_get_names(int flags) { return env_stack_t::principal().get_names(flags); }
|
||||
|
||||
wcstring env_get_pwd_slash() { return env_stack_t::principal().get_pwd_slash(); }
|
||||
|
||||
void env_set_read_limit() { return env_stack_t::principal().set_read_limit(); }
|
||||
|
||||
/// Returns true if the specified scope or any non-shadowed non-global subscopes contain an exported
|
||||
/// variable.
|
||||
static bool local_scope_exports(const env_node_t *n) {
|
||||
bool var_stack_t::local_scope_exports(const env_node_t *n) const {
|
||||
assert(n != NULL);
|
||||
if (n == vars_stack().global_env) return false;
|
||||
if (n == global_env) return false;
|
||||
|
||||
if (n->exportv) return true;
|
||||
|
||||
|
@ -1435,9 +1474,9 @@ static bool local_scope_exports(const env_node_t *n) {
|
|||
return local_scope_exports(n->next.get());
|
||||
}
|
||||
|
||||
void env_push(bool new_scope) { vars_stack().push(new_scope); }
|
||||
void env_stack_t::push(bool new_scope) { vars_stack().push(new_scope); }
|
||||
|
||||
void env_pop() { vars_stack().pop(); }
|
||||
void env_stack_t::pop() { vars_stack().pop(); }
|
||||
|
||||
/// Function used with to insert keys of one table into a set::set<wcstring>.
|
||||
static void add_key_to_string_set(const var_table_t &envs, std::set<wcstring> *str_set,
|
||||
|
@ -1453,7 +1492,7 @@ static void add_key_to_string_set(const var_table_t &envs, std::set<wcstring> *s
|
|||
}
|
||||
}
|
||||
|
||||
wcstring_list_t env_get_names(int flags) {
|
||||
wcstring_list_t env_stack_t::get_names(int flags) {
|
||||
scoped_lock locker(env_lock);
|
||||
|
||||
wcstring_list_t result;
|
||||
|
@ -1499,11 +1538,11 @@ wcstring_list_t env_get_names(int flags) {
|
|||
}
|
||||
|
||||
/// Get list of all exported variables.
|
||||
static void get_exported(const env_node_t *n, var_table_t &h) {
|
||||
void var_stack_t::get_exported(const env_node_t *n, var_table_t &h) const {
|
||||
if (!n) return;
|
||||
|
||||
if (n->new_scope) {
|
||||
get_exported(vars_stack().global_env, h);
|
||||
get_exported(global_env, h);
|
||||
} else {
|
||||
get_exported(n->next.get(), h);
|
||||
}
|
||||
|
@ -1569,14 +1608,14 @@ void var_stack_t::update_export_array_if_necessary() {
|
|||
has_changed_exported = false;
|
||||
}
|
||||
|
||||
const char *const *env_export_arr() {
|
||||
const char *const *env_stack_t::export_arr() {
|
||||
ASSERT_IS_MAIN_THREAD();
|
||||
ASSERT_IS_NOT_FORKED_CHILD();
|
||||
vars_stack().update_export_array_if_necessary();
|
||||
return vars_stack().export_array.get();
|
||||
}
|
||||
|
||||
void env_set_argv(const wchar_t *const *argv) {
|
||||
void env_stack_t::set_argv(const wchar_t *const *argv) {
|
||||
if (argv && *argv) {
|
||||
wcstring_list_t list;
|
||||
for (auto arg = argv; *arg; arg++) {
|
||||
|
@ -1591,6 +1630,13 @@ void env_set_argv(const wchar_t *const *argv) {
|
|||
|
||||
environment_t::~environment_t() = default;
|
||||
|
||||
env_stack_t::~env_stack_t() = default;
|
||||
|
||||
env_stack_t &env_stack_t::principal() {
|
||||
static env_stack_t s_principal;
|
||||
return s_principal;
|
||||
}
|
||||
|
||||
env_vars_snapshot_t::env_vars_snapshot_t(const wchar_t *const *keys) {
|
||||
ASSERT_IS_MAIN_THREAD();
|
||||
wcstring key;
|
||||
|
|
77
src/env.h
77
src/env.h
|
@ -182,15 +182,86 @@ void env_set_argv(const wchar_t *const *argv);
|
|||
/// Returns all variable names.
|
||||
wcstring_list_t env_get_names(int flags);
|
||||
|
||||
/// Update the PWD variable based on the result of getcwd.
|
||||
void env_set_pwd_from_getcwd();
|
||||
|
||||
/// Returns the PWD with a terminating slash.
|
||||
wcstring env_get_pwd_slash();
|
||||
|
||||
/// Update the read_byte_limit variable.
|
||||
void env_set_read_limit();
|
||||
|
||||
/// A environment stack of scopes. This is the main class that tracks fish variables.
|
||||
struct var_stack_t;
|
||||
class env_node_t;
|
||||
class env_stack_t : public environment_t {
|
||||
std::unique_ptr<var_stack_t> vars_;
|
||||
|
||||
int set_internal(const wcstring &key, env_mode_flags_t var_mode, wcstring_list_t val);
|
||||
|
||||
bool try_remove(env_node_t *n, const wchar_t *key, int var_mode);
|
||||
env_node_t *get_node(const wcstring &key);
|
||||
|
||||
var_stack_t &vars_stack();
|
||||
const var_stack_t &vars_stack() const;
|
||||
|
||||
env_stack_t();
|
||||
~env_stack_t() override;
|
||||
|
||||
public:
|
||||
/// Gets the variable with the specified name, or none() if it does not exist.
|
||||
maybe_t<env_var_t> get(const wcstring &key, env_mode_flags_t mode = ENV_DEFAULT) const override;
|
||||
|
||||
/// Sets the variable with the specified name to the given values.
|
||||
int set(const wcstring &key, env_mode_flags_t mode, wcstring_list_t vals);
|
||||
|
||||
/// Sets the variable with the specified name to a single value.
|
||||
int set_one(const wcstring &key, env_mode_flags_t mode, wcstring val);
|
||||
|
||||
/// Sets the variable with the specified name to no values.
|
||||
int set_empty(const wcstring &key, env_mode_flags_t mode);
|
||||
|
||||
/// Update the PWD variable based on the result of getcwd.
|
||||
void set_pwd_from_getcwd();
|
||||
|
||||
/// Remove environment variable.
|
||||
///
|
||||
/// \param key The name of the variable to remove
|
||||
/// \param mode should be ENV_USER if this is a remove request from the user, 0 otherwise. If
|
||||
/// this is a user request, read-only variables can not be removed. The mode may also specify
|
||||
/// the scope of the variable that should be erased.
|
||||
///
|
||||
/// \return zero if the variable existed, and non-zero if the variable did not exist
|
||||
int remove(const wcstring &key, int mode);
|
||||
|
||||
/// Push the variable stack. Used for implementing local variables for functions and for-loops.
|
||||
void push(bool new_scope);
|
||||
|
||||
/// Pop the variable stack. Used for implementing local variables for functions and for-loops.
|
||||
void pop();
|
||||
|
||||
/// Synchronizes all universal variable changes: writes everything out, reads stuff in.
|
||||
void universal_barrier();
|
||||
|
||||
/// Returns an array containing all exported variables in a format suitable for execv
|
||||
const char *const *export_arr();
|
||||
|
||||
/// Returns all variable names.
|
||||
wcstring_list_t get_names(int flags);
|
||||
|
||||
/// Sets up argv as the given null terminated array of strings.
|
||||
void set_argv(const wchar_t *const *argv);
|
||||
|
||||
/// Returns the PWD with a terminating slash.
|
||||
wcstring get_pwd_slash();
|
||||
|
||||
/// Update the read_byte_limit variable.
|
||||
void set_read_limit();
|
||||
|
||||
/// Mark that exported variables have changed.
|
||||
void mark_changed_exported();
|
||||
|
||||
// Compatibility hack; access the "environment stack" from back when there was just one.
|
||||
static env_stack_t &principal();
|
||||
};
|
||||
|
||||
class env_vars_snapshot_t : public environment_t {
|
||||
std::map<wcstring, env_var_t> vars;
|
||||
bool is_current() const;
|
||||
|
|
|
@ -174,7 +174,7 @@ static bool pushd(const char *path) {
|
|||
return false;
|
||||
}
|
||||
|
||||
env_set_pwd_from_getcwd();
|
||||
env_stack_t::principal().set_pwd_from_getcwd();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -184,7 +184,7 @@ static void popd() {
|
|||
err(L"chdir(\"%s\") from popd() failed: errno = %d", old_cwd.c_str(), errno);
|
||||
}
|
||||
pushed_dirs.pop_back();
|
||||
env_set_pwd_from_getcwd();
|
||||
env_stack_t::principal().set_pwd_from_getcwd();
|
||||
}
|
||||
|
||||
// The odd formulation of these macros is to avoid "multiple unary operator" warnings from oclint
|
||||
|
|
Loading…
Reference in a new issue