diff --git a/CHANGELOG.rst b/CHANGELOG.rst index a0fc24ffa..9ba252fe2 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -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 ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/env_universal_common.cpp b/src/env_universal_common.cpp index 4278d18b9..87cbc6951 100644 --- a/src/env_universal_common.cpp +++ b/src/env_universal_common.cpp @@ -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"); } diff --git a/tests/checks/symlink-universal-variables.fish b/tests/checks/symlink-universal-variables.fish new file mode 100644 index 000000000..d15389741 --- /dev/null +++ b/tests/checks/symlink-universal-variables.fish @@ -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