Set $__fish_data_dir to empty for embed-data builds

These builds do not use it, and setting it makes it possible to use
stale files.

So instead, we set it to empty. All uses I could find are either fine
with that (`set fish_function_path $__fish_data_dir/functions` - which
would also just be empty, which means it reads the embedded
functions),

or would break even if the variable was set but the directory was
empty (`source $__fish_data_dir/completions/git.fish`).
This commit is contained in:
Fabian Boehm
2025-04-01 18:31:15 +02:00
parent 329cd7d429
commit b815fff292
6 changed files with 47 additions and 38 deletions

View File

@@ -35,7 +35,7 @@ end
set -l __extra_completionsdir
set -l __extra_functionsdir
set -l __extra_confdir
if test -f $__fish_data_dir/__fish_build_paths.fish
if path is -f -- $__fish_data_dir/__fish_build_paths.fish
source $__fish_data_dir/__fish_build_paths.fish
end

View File

@@ -186,7 +186,14 @@ fn read_init(parser: &Parser, paths: &ConfigPaths) {
}
#[cfg(not(feature = "embed-data"))]
{
let datapath = str2wcstring(paths.data.as_os_str().as_bytes());
let datapath = str2wcstring(
paths
.data
.clone()
.expect("Non-embed build not having a data path. That's a bug")
.as_os_str()
.as_bytes(),
);
if !source_config_in_directory(parser, &datapath) {
// If we cannot read share/config.fish, our internal configuration,
// something is wrong.

View File

@@ -52,11 +52,11 @@ fn determine_config_directory_paths(argv0: impl AsRef<Path>) -> ConfigPaths {
);
done = true;
paths = ConfigPaths {
data: manifest_dir.join("share"),
data: Some(manifest_dir.join("share")),
sysconf: manifest_dir.join("etc"),
doc: manifest_dir.join("user_doc/html"),
bin: Some(exec_path.parent().unwrap().to_owned()),
locale: manifest_dir.join("share/locale"),
locale: Some(manifest_dir.join("share/locale")),
}
}
@@ -73,11 +73,11 @@ fn determine_config_directory_paths(argv0: impl AsRef<Path>) -> ConfigPaths {
// If we picked ~/.local/share/fish as our data path,
// we would install there and erase history.
// So let's isolate us a bit more.
data: data_dir.clone(),
data: Some(data_dir.clone()),
sysconf: base_path.join("etc/fish"),
doc: base_path.join("share/doc/fish"),
bin: Some(base_path.join("bin")),
locale: data_dir.join("locale"),
locale: Some(data_dir.join("locale")),
}
} else if exec_path.ends_with("fish") {
FLOG!(
@@ -90,15 +90,15 @@ fn determine_config_directory_paths(argv0: impl AsRef<Path>) -> ConfigPaths {
#[cfg(not(feature = "embed-data"))]
let data_dir = base_path.join("share");
paths = ConfigPaths {
data: data_dir.clone(),
data: Some(data_dir.clone()),
sysconf: base_path.join("etc"),
doc: base_path.join("user_doc/html"),
bin: Some(base_path.to_path_buf()),
locale: data_dir.join("locale"),
locale: Some(data_dir.join("locale")),
}
}
if paths.data.exists() && paths.sysconf.exists() {
if paths.data.clone().is_some_and(|x| x.exists()) && paths.sysconf.exists() {
// The docs dir may not exist; in that case fall back to the compiled in path.
if !paths.doc.exists() {
paths.doc = PathBuf::from(DOC_DIR);
@@ -111,18 +111,9 @@ fn determine_config_directory_paths(argv0: impl AsRef<Path>) -> ConfigPaths {
if !done {
// Fall back to what got compiled in.
let data = if cfg!(feature = "embed-data") {
let Some(home) = crate::env::get_home() else {
FLOG!(
error,
"Cannot find home directory and will refuse to read configuration.\n",
"Consider installing into a directory tree with `fish --install=PATH`."
);
return paths;
};
PathBuf::from(home).join(DATA_DIR).join(DATA_DIR_SUBDIR)
None
} else {
PathBuf::from(DATA_DIR).join(DATA_DIR_SUBDIR)
Some(PathBuf::from(DATA_DIR).join(DATA_DIR_SUBDIR))
};
let bin = if cfg!(feature = "embed-data") {
exec_path.parent().map(|x| x.to_path_buf())
@@ -136,7 +127,7 @@ fn determine_config_directory_paths(argv0: impl AsRef<Path>) -> ConfigPaths {
sysconf: PathBuf::from(SYSCONF_DIR).join("fish"),
doc: DOC_DIR.into(),
bin,
locale: data.join("share"),
locale: data.map(|x| x.join("share")),
}
}
@@ -144,7 +135,11 @@ fn determine_config_directory_paths(argv0: impl AsRef<Path>) -> ConfigPaths {
config,
"determine_config_directory_paths() results:\npaths.data: %ls\npaths.sysconf: \
%ls\npaths.doc: %ls\npaths.bin: %ls",
paths.data.display().to_string(),
paths
.data
.clone()
.map(|x| x.display().to_string())
.unwrap_or("|not found|".to_string()),
paths.sysconf.display().to_string(),
paths.doc.display().to_string(),
paths

View File

@@ -635,9 +635,21 @@ pub fn env_init(paths: Option<&ConfigPaths>, do_uvars: bool, default_paths: bool
setup_user(vars);
if let Some(paths) = paths {
let datadir = str2wcstring(paths.data.as_os_str().as_bytes());
if let Some(ddir) = &paths.data {
let datadir = str2wcstring(ddir.as_os_str().as_bytes());
vars.set_one(FISH_DATADIR_VAR, EnvMode::GLOBAL, datadir.clone());
if default_paths {
let mut scstr = datadir;
// This is generated by PathBuf.join() everywhere currently
assert!(!scstr.ends_with("/"));
scstr.push_str("/functions");
vars.set_one(L!("fish_function_path"), EnvMode::GLOBAL, scstr);
}
} else {
vars.set_empty(FISH_DATADIR_VAR, EnvMode::GLOBAL);
}
vars.set_one(FISH_DATADIR_VAR, EnvMode::GLOBAL, datadir.clone());
vars.set_one(
FISH_SYSCONFDIR_VAR,
EnvMode::GLOBAL,
@@ -662,14 +674,6 @@ pub fn env_init(paths: Option<&ConfigPaths>, do_uvars: bool, default_paths: bool
} else {
vars.set_empty(FISH_BIN_DIR, EnvMode::GLOBAL);
};
if default_paths {
let mut scstr = datadir;
// This is generated by PathBuf.join() everywhere currently
assert!(!scstr.ends_with("/"));
scstr.push_str("/functions");
vars.set_one(L!("fish_function_path"), EnvMode::GLOBAL, scstr);
}
}
let user_config_dir = path_get_config();

10
src/env/var.rs vendored
View File

@@ -50,11 +50,11 @@ fn from(val: EnvMode) -> Self {
/// env_init.
#[derive(Default)]
pub struct ConfigPaths {
pub data: PathBuf, // e.g., /usr/local/share
pub sysconf: PathBuf, // e.g., /usr/local/etc
pub doc: PathBuf, // e.g., /usr/local/share/doc/fish
pub bin: Option<PathBuf>, // e.g., /usr/local/bin
pub locale: PathBuf, // e.g., /usr/local/share/locale
pub data: Option<PathBuf>, // e.g., /usr/local/share
pub sysconf: PathBuf, // e.g., /usr/local/etc
pub doc: PathBuf, // e.g., /usr/local/share/doc/fish
pub bin: Option<PathBuf>, // e.g., /usr/local/bin
pub locale: Option<PathBuf>, // e.g., /usr/local/share/locale
}
/// A collection of status and pipestatus.

View File

@@ -48,10 +48,13 @@ pub fn fish_textdomain(_domainname: &CStr) -> *mut c_char {
// Really init wgettext.
fn wgettext_really_init() {
let Some(ref localepath) = CONFIG_PATHS.locale else {
return;
};
let package_name = CString::new(PACKAGE_NAME).unwrap();
// This contains `datadir`; which when replaced to make the binary relocatable,
// causes null bytes at the end of the string.
let localedir = CString::new(CONFIG_PATHS.locale.display().to_string()).unwrap();
let localedir = CString::new(localepath.display().to_string()).unwrap();
fish_bindtextdomain(&package_name, &localedir);
fish_textdomain(&package_name);
}