mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-26 10:43:47 +08:00
remove unset vars from the environment
Remove vars from the environment that are no longer set. Simplify the code by removing an unnecessary loop. Add some tests. Fixes #3124
This commit is contained in:
parent
cfe3fc301c
commit
0ca103686f
|
@ -321,8 +321,7 @@ static void print_variables(int include_values, int esc, bool shorten_ok, int sc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The set builtin. Creates, updates and erases environment variables and environemnt variable
|
/// The set builtin creates, updates, and erases (removes, deletes) variables.
|
||||||
/// arrays.
|
|
||||||
int builtin_set(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
|
int builtin_set(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
|
||||||
wgetopter_t w;
|
wgetopter_t w;
|
||||||
// Variables used for parsing the argument list.
|
// Variables used for parsing the argument list.
|
||||||
|
|
44
src/env.cpp
44
src/env.cpp
|
@ -174,16 +174,14 @@ static bool var_is_locale(const wcstring &key) {
|
||||||
static void handle_locale(const wchar_t *env_var_name) {
|
static void handle_locale(const wchar_t *env_var_name) {
|
||||||
debug(2, L"handle_locale() called in response to '%ls' changing", env_var_name);
|
debug(2, L"handle_locale() called in response to '%ls' changing", env_var_name);
|
||||||
const char *old_msg_locale = setlocale(LC_MESSAGES, NULL);
|
const char *old_msg_locale = setlocale(LC_MESSAGES, NULL);
|
||||||
|
const env_var_t val = env_get_string(env_var_name, ENV_EXPORT);
|
||||||
for (size_t i = 0; locale_variable[i]; i++) {
|
const std::string &value = wcs2string(val);
|
||||||
const wchar_t *key = locale_variable[i];
|
const std::string &name = wcs2string(env_var_name);
|
||||||
const env_var_t var = env_get_string(key);
|
debug(2, L"locale var %s='%s'", name.c_str(), value.c_str());
|
||||||
if (!var.empty()) {
|
if (val.empty()) {
|
||||||
const std::string &name = wcs2string(key);
|
unsetenv(name.c_str());
|
||||||
const std::string &value = wcs2string(var);
|
} else {
|
||||||
setenv(name.c_str(), value.c_str(), 1);
|
setenv(name.c_str(), value.c_str(), 1);
|
||||||
debug(3, L"locale var %s='%s'", name.c_str(), value.c_str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *locale = setlocale(LC_ALL, "");
|
char *locale = setlocale(LC_ALL, "");
|
||||||
|
@ -216,15 +214,14 @@ static bool var_is_curses(const wcstring &key) {
|
||||||
/// libraries.
|
/// libraries.
|
||||||
static void handle_curses(const wchar_t *env_var_name) {
|
static void handle_curses(const wchar_t *env_var_name) {
|
||||||
debug(2, L"handle_curses() called in response to '%ls' changing", env_var_name);
|
debug(2, L"handle_curses() called in response to '%ls' changing", env_var_name);
|
||||||
for (size_t i = 0; curses_variable[i]; i++) {
|
const env_var_t val = env_get_string(env_var_name, ENV_EXPORT);
|
||||||
const wchar_t *key = curses_variable[i];
|
const std::string &name = wcs2string(env_var_name);
|
||||||
const env_var_t var = env_get_string(key);
|
const std::string &value = wcs2string(val);
|
||||||
if (!var.empty()) {
|
debug(2, L"curses var %s='%s'", name.c_str(), value.c_str());
|
||||||
const std::string &name = wcs2string(key);
|
if (val.empty()) {
|
||||||
const std::string &value = wcs2string(var);
|
unsetenv(name.c_str());
|
||||||
setenv(name.c_str(), value.c_str(), 1);
|
} else {
|
||||||
debug(3, L"curses var %s='%s'", name.c_str(), value.c_str());
|
setenv(name.c_str(), value.c_str(), 1);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// TODO: Modify input_init() to allow calling it when the terminfo env vars are dynamically
|
// TODO: Modify input_init() to allow calling it when the terminfo env vars are dynamically
|
||||||
// changed. At the present time it can be called just once. Also, we should really only do this
|
// changed. At the present time it can be called just once. Also, we should really only do this
|
||||||
|
@ -318,11 +315,10 @@ static bool variable_is_colon_delimited_array(const wcstring &str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void env_init(const struct config_paths_t *paths /* or NULL */) {
|
void env_init(const struct config_paths_t *paths /* or NULL */) {
|
||||||
// env_read_only variables can not be altered directly by the user.
|
// These variables can not be altered directly by the user.
|
||||||
const wchar_t *const ro_keys[] = {
|
const wchar_t *const ro_keys[] = {
|
||||||
L"status", L"history", L"_", L"LINES", L"COLUMNS", L"PWD",
|
L"status", L"history", L"_", L"LINES", L"COLUMNS", L"PWD", L"FISH_VERSION",
|
||||||
// L"SHLVL", // will be inserted a bit lower down
|
// L"SHLVL" is readonly but will be inserted below after we increment it.
|
||||||
L"FISH_VERSION",
|
|
||||||
};
|
};
|
||||||
for (size_t i = 0; i < sizeof ro_keys / sizeof *ro_keys; i++) {
|
for (size_t i = 0; i < sizeof ro_keys / sizeof *ro_keys; i++) {
|
||||||
env_read_only.insert(ro_keys[i]);
|
env_read_only.insert(ro_keys[i]);
|
||||||
|
@ -339,7 +335,7 @@ void env_init(const struct config_paths_t *paths /* or NULL */) {
|
||||||
global_env = top;
|
global_env = top;
|
||||||
global = &top->env;
|
global = &top->env;
|
||||||
|
|
||||||
// Now the environemnt variable handling is set up, the next step is to insert valid data.
|
// Now the environment variable handling is set up, the next step is to insert valid data.
|
||||||
|
|
||||||
// Import environment variables. Walk backwards so that the first one out of any duplicates wins
|
// Import environment variables. Walk backwards so that the first one out of any duplicates wins
|
||||||
// (#2784).
|
// (#2784).
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
58c3bb58
|
|
||||||
58c3bc58
|
|
||||||
59fc59
|
|
||||||
543f54
|
|
|
@ -1,3 +1,27 @@
|
||||||
|
# Test behavior related to the locale.
|
||||||
|
|
||||||
|
# Verify that our UTF-8 locale produces the expected output.
|
||||||
|
echo -n A\u00FCA | xxd --plain
|
||||||
|
|
||||||
|
# Verify that exporting a change to the C locale produces the expected output.
|
||||||
|
# The output should include the literal byte \xFC rather than the UTF-8 sequence for \u00FC.
|
||||||
|
begin
|
||||||
|
set -lx LC_ALL C
|
||||||
|
echo -n B\u00FCB | xxd --plain
|
||||||
|
end
|
||||||
|
|
||||||
|
# Since the previous change was localized to a block it should no
|
||||||
|
# longer be in effect and we should be back to a UTF-8 locale.
|
||||||
|
echo -n C\u00FCC | xxd --plain
|
||||||
|
|
||||||
|
# Verify that setting a non-exported locale var doesn't affect the behavior.
|
||||||
|
# The output should include the UTF-8 sequence for \u00FC rather than that literal byte.
|
||||||
|
# Just like the previous test.
|
||||||
|
begin
|
||||||
|
set -l LC_ALL C
|
||||||
|
echo -n D\u00FCD | xxd --plain
|
||||||
|
end
|
||||||
|
|
||||||
# Verify that fish can pass through non-ASCII characters in the C/POSIX
|
# Verify that fish can pass through non-ASCII characters in the C/POSIX
|
||||||
# locale. This is to prevent regression of
|
# locale. This is to prevent regression of
|
||||||
# https://github.com/fish-shell/fish-shell/issues/2802.
|
# https://github.com/fish-shell/fish-shell/issues/2802.
|
||||||
|
@ -14,22 +38,24 @@
|
||||||
# echo output directly to the `xxd` program then via a fish instance. The
|
# echo output directly to the `xxd` program then via a fish instance. The
|
||||||
# output should be "58c3bb58" for the first statement and "58c3bc58" for the
|
# output should be "58c3bb58" for the first statement and "58c3bc58" for the
|
||||||
# second.
|
# second.
|
||||||
echo -n X\u00fbX | \
|
echo -n X\u00FBX | \
|
||||||
xxd --plain
|
xxd --plain
|
||||||
echo X\u00fcX | env LC_ALL=C ../test/root/bin/fish -c 'read foo; echo -n $foo' | \
|
echo X\u00FCX | env LC_ALL=C ../test/root/bin/fish -c 'read foo; echo -n $foo' | \
|
||||||
xxd --plain
|
xxd --plain
|
||||||
|
|
||||||
|
# The next tests deliberately spawn another fish instance to test inheritence of env vars.
|
||||||
|
|
||||||
# This test is subtle. Despite the presence of the \u00fc unicode char (a "u"
|
# This test is subtle. Despite the presence of the \u00fc unicode char (a "u"
|
||||||
# with an umlaut) the fact the locale is C/POSIX will cause the \xfc byte to
|
# with an umlaut) the fact the locale is C/POSIX will cause the \xfc byte to
|
||||||
# be emitted rather than the usual UTF-8 sequence \xc3\xbc. That's because the
|
# be emitted rather than the usual UTF-8 sequence \xc3\xbc. That's because the
|
||||||
# few single-byte unicode chars (that are not ASCII) are generally in the
|
# few single-byte unicode chars (that are not ASCII) are generally in the
|
||||||
# ISO-8859-1 char set which is encompased by the C locale. The output should
|
# ISO 8859-x char sets which are encompassed by the C locale. The output should
|
||||||
# be "59fc59".
|
# be "59fc59".
|
||||||
env LC_ALL=C ../test/root/bin/fish -c 'echo -n Y\u00fcY' | \
|
env LC_ALL=C ../test/root/bin/fish -c 'echo -n Y\u00FCY' | \
|
||||||
xxd --plain
|
xxd --plain
|
||||||
|
|
||||||
# The user can specify a wide unicode character (one requiring more than a
|
# The user can specify a wide unicode character (one requiring more than a
|
||||||
# single byte). In the C/POSIX locales we substitute a question-mark for the
|
# single byte). In the C/POSIX locales we substitute a question-mark for the
|
||||||
# unencodable wide char. The output should be "543f54".
|
# unencodable wide char. The output should be "543f54".
|
||||||
env LC_ALL=C ../test/root/bin/fish -c 'echo -n T\u01fdT' | \
|
env LC_ALL=C ../test/root/bin/fish -c 'echo -n T\u01FDT' | \
|
||||||
xxd --plain
|
xxd --plain
|
8
tests/locale.out
Normal file
8
tests/locale.out
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
41c3bc41
|
||||||
|
42fc42
|
||||||
|
43c3bc43
|
||||||
|
44c3bc44
|
||||||
|
58c3bb58
|
||||||
|
58c3bc58
|
||||||
|
59fc59
|
||||||
|
543f54
|
Loading…
Reference in New Issue
Block a user