Fix set -U when fish_variables is a symlink

Previously, `set -U` would overwrite the symlink with a
regular file.

Fixes https://github.com/fish-shell/fish-shell/issues/7466
This commit is contained in:
Ilya Grigoriev 2021-02-17 16:44:07 -08:00 committed by ridiculousfish
parent e7d5a40252
commit 622f2868e1
3 changed files with 28 additions and 2 deletions

View File

@ -275,6 +275,7 @@ Interactive improvements
- Just like new ``fish_indent``, the interactive reader will indent continuation lines that follow a line ending in a backslash, ``|``, ``&&`` or ``||`` (:issue:`7694`).
- Commands with a trailing escaped space are saved in history correctly (:issue:`7661`).
- ``fish_prompt`` no longer mangles Unicode characters in the private-use range U+F600-U+F700. (:issue:`7723`).
- ``set -U`` now behaves correctly when ``fish_variables`` is a symbolic link instead of overwriting it with a regular file (:issue:`7466`)
New or improved bindings
^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -739,9 +739,16 @@ bool env_universal_t::save(const wcstring &directory, const wcstring &vars_path)
}
if (success) {
wcstring real_path;
if (auto maybe_real_path = wrealpath(vars_path)) {
real_path = *maybe_real_path;
} else {
real_path = vars_path;
}
// Ensure we maintain ownership and permissions (#2176).
struct stat sbuf;
if (wstat(vars_path, &sbuf) >= 0) {
if (wstat(real_path, &sbuf) >= 0) {
if (fchown(private_fd.fd(), sbuf.st_uid, sbuf.st_gid) == -1)
FLOGF(uvar_file, L"universal log fchown() failed");
if (fchmod(private_fd.fd(), sbuf.st_mode) == -1)
@ -765,7 +772,7 @@ bool env_universal_t::save(const wcstring &directory, const wcstring &vars_path)
#endif
// Apply new file.
success = this->move_new_vars_file_into_place(private_file_path, vars_path);
success = this->move_new_vars_file_into_place(private_file_path, real_path);
if (!success) FLOGF(uvar_file, L"universal log move_new_vars_file_into_place() failed");
}

View File

@ -0,0 +1,18 @@
#RUN: %fish -C 'set -g fish %fish' %s
begin
set -gx XDG_CONFIG_HOME (mktemp -d)
mkdir -p $XDG_CONFIG_HOME/fish
set -l target_file $XDG_CONFIG_HOME/fish/target_fish_variables
set -l fish_variables $XDG_CONFIG_HOME/fish/fish_variables
echo > $target_file
ln -sf $target_file $fish_variables
$fish -c 'set -U variable value'
if test -L $fish_variables
echo fish_variables is still a symlink
else
echo fish_variables has been overwritten
end
# CHECK: fish_variables is still a symlink
end