mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-28 22:03:12 +00:00
Factor some environment setting into set_scoped_internal
Breaks up a monolith function.
This commit is contained in:
parent
15a52d0f0d
commit
ee250aba82
3 changed files with 104 additions and 93 deletions
113
src/env.cpp
113
src/env.cpp
|
@ -796,59 +796,12 @@ static void env_set_internal_universal(const wcstring &key, wcstring_list_t val,
|
|||
}
|
||||
}
|
||||
|
||||
/// Set the value of the environment variable whose name matches key to val.
|
||||
///
|
||||
/// \param key The key
|
||||
/// \param val The value to set.
|
||||
/// \param var_mode The type of the variable. Can be any combination of ENV_GLOBAL, ENV_LOCAL,
|
||||
/// ENV_EXPORT and ENV_USER. If mode is ENV_DEFAULT, the current variable space is searched and the
|
||||
/// current mode is used. If no current variable with the same name is found, ENV_LOCAL is assumed.
|
||||
///
|
||||
/// Returns:
|
||||
///
|
||||
/// * ENV_OK on success.
|
||||
/// * ENV_PERM, can only be returned when setting as a user, e.g. ENV_USER is set. This means that
|
||||
/// the user tried to change a read-only variable.
|
||||
/// * 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.
|
||||
int env_stack_t::set_internal(const wcstring &key, env_mode_flags_t input_var_mode,
|
||||
void env_stack_t::set_scoped_internal(const wcstring &key, env_mode_flags_t 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();
|
||||
int done = 0;
|
||||
|
||||
if (val.size() == 1 && (key == L"PWD" || key == L"HOME")) {
|
||||
// Canonicalize our path; if it changes, recurse and try again.
|
||||
wcstring val_canonical = val.front();
|
||||
path_make_canonical(val_canonical);
|
||||
if (val.front() != val_canonical) {
|
||||
return set_internal(key, var_mode, {val_canonical});
|
||||
}
|
||||
}
|
||||
|
||||
if ((var_mode & ENV_LOCAL || var_mode & ENV_UNIVERSAL) &&
|
||||
(is_read_only(key) || is_electric(key))) {
|
||||
return ENV_SCOPE;
|
||||
}
|
||||
if ((var_mode & ENV_EXPORT) && is_electric(key)) {
|
||||
return ENV_SCOPE;
|
||||
}
|
||||
if ((var_mode & ENV_USER) && is_read_only(key)) {
|
||||
return ENV_PERM;
|
||||
}
|
||||
|
||||
if (key == L"umask") { // set new umask
|
||||
return set_umask(val);
|
||||
}
|
||||
|
||||
if (var_mode & ENV_UNIVERSAL) {
|
||||
if (uvars()) {
|
||||
env_set_internal_universal(key, std::move(val), var_mode, this);
|
||||
}
|
||||
} else {
|
||||
scoped_lock locker(env_lock);
|
||||
bool has_changed_old = vars_stack().has_changed_exported();
|
||||
bool done = false;
|
||||
|
||||
// Determine the node.
|
||||
bool has_changed_new = false;
|
||||
env_node_ref_t preexisting_node = get_node(key);
|
||||
|
@ -933,6 +886,64 @@ int env_stack_t::set_internal(const wcstring &key, env_mode_flags_t input_var_mo
|
|||
|
||||
if (has_changed_old || has_changed_new) vars_stack().mark_changed_exported();
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the value of the environment variable whose name matches key to val.
|
||||
///
|
||||
/// \param key The key
|
||||
/// \param val The value to set.
|
||||
/// \param var_mode The type of the variable. Can be any combination of ENV_GLOBAL, ENV_LOCAL,
|
||||
/// ENV_EXPORT and ENV_USER. If mode is ENV_DEFAULT, the current variable space is searched and the
|
||||
/// current mode is used. If no current variable with the same name is found, ENV_LOCAL is assumed.
|
||||
///
|
||||
/// Returns:
|
||||
///
|
||||
/// * ENV_OK on success.
|
||||
/// * ENV_PERM, can only be returned when setting as a user, e.g. ENV_USER is set. This means that
|
||||
/// the user tried to change a read-only variable.
|
||||
/// * 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.
|
||||
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;
|
||||
|
||||
if (val.size() == 1 && (key == L"PWD" || key == L"HOME")) {
|
||||
// Canonicalize our path; if it changes, recurse and try again.
|
||||
wcstring val_canonical = val.front();
|
||||
path_make_canonical(val_canonical);
|
||||
if (val.front() != val_canonical) {
|
||||
return set_internal(key, var_mode, {val_canonical});
|
||||
}
|
||||
}
|
||||
|
||||
// Yucky set of random checks.
|
||||
if ((var_mode & ENV_LOCAL || var_mode & ENV_UNIVERSAL) &&
|
||||
(is_read_only(key) || is_electric(key))) {
|
||||
return ENV_SCOPE;
|
||||
}
|
||||
if ((var_mode & ENV_EXPORT) && is_electric(key) && key != L"PWD") {
|
||||
return ENV_SCOPE;
|
||||
}
|
||||
if ((var_mode & ENV_USER) && is_read_only(key)) {
|
||||
return ENV_PERM;
|
||||
}
|
||||
|
||||
// Handle special case electric variables.
|
||||
if (key == L"umask") { // set new umask
|
||||
scoped_lock locker(env_lock);
|
||||
return set_umask(val);
|
||||
}
|
||||
|
||||
if (var_mode & ENV_UNIVERSAL) {
|
||||
// Set this as a universal variable.
|
||||
if (uvars()) {
|
||||
env_set_internal_universal(key, std::move(val), var_mode, this);
|
||||
}
|
||||
} else {
|
||||
// Unspecial variable, set it in the right scope.
|
||||
set_scoped_internal(key, var_mode, std::move(val));
|
||||
}
|
||||
|
||||
event_fire(event_t::variable(key, {L"VARIABLE", L"SET", key}));
|
||||
|
|
|
@ -240,6 +240,10 @@ class env_stack_t final : public env_scoped_t {
|
|||
~env_stack_t() override;
|
||||
env_stack_t(env_stack_t &&);
|
||||
|
||||
/// Given that we have determined that \p key is an unspecial key, set the variable in the right
|
||||
/// scope in the variable stack.
|
||||
void set_scoped_internal(const wcstring &key, env_mode_flags_t var_mode, wcstring_list_t val);
|
||||
|
||||
public:
|
||||
/// 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);
|
||||
|
@ -279,9 +283,6 @@ class env_stack_t final : public env_scoped_t {
|
|||
/// Update the termsize variable.
|
||||
void set_termsize();
|
||||
|
||||
/// Update the PWD variable directory.
|
||||
bool set_pwd();
|
||||
|
||||
/// Sets up argv as the given null terminated array of strings.
|
||||
void set_argv(const wchar_t *const *argv);
|
||||
|
||||
|
|
|
@ -402,13 +402,12 @@ int main(int argc, char **argv) {
|
|||
save_term_foreground_process_group();
|
||||
}
|
||||
|
||||
auto &globals = env_stack_t::globals();
|
||||
const struct config_paths_t paths = determine_config_directory_paths(argv[0]);
|
||||
env_init(&paths);
|
||||
// Set features early in case other initialization depends on them.
|
||||
// Start with the ones set in the environment, then those set on the command line (so the
|
||||
// command line takes precedence).
|
||||
if (auto features_var = globals.get(L"fish_features")) {
|
||||
if (auto features_var = env_stack_t::globals().get(L"fish_features")) {
|
||||
for (const wcstring &s : features_var->as_list()) {
|
||||
mutable_fish_features().set_from_string(s);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue