Define __fish_{data,help}_dir again on standalone builds

As mentioned in a previous commit ("Don't special-case __fish_data_dir
in standalone builds"), we want to enable embed-data by default.
To reduce the amount of breakage, we'll keep installing files,
and keep defining those variables at least for some time.

We have no use for $__fish_data_dir apart from helping plugins and
improving upgrade experience, but we still use $__fish_help_dir;
so this will allow installed "standalone" builds to use local docs
via our "help" function.
This commit is contained in:
Johannes Altmanninger
2025-10-26 23:08:22 +01:00
parent da5a57890a
commit e0a2fa35cc
5 changed files with 82 additions and 79 deletions

View File

@@ -178,11 +178,16 @@ fn setup_paths() {
#[cfg(windows)]
use unix_path::{Path, PathBuf};
fn overridable_path(env_var_name: &str, f: impl FnOnce(Option<String>) -> PathBuf) -> PathBuf {
fn overridable_path(
env_var_name: &str,
f: impl FnOnce(Option<String>) -> Option<PathBuf>,
) -> Option<PathBuf> {
rsconf::rebuild_if_env_changed(env_var_name);
let path = f(env_var(env_var_name));
rsconf::set_env_value(env_var_name, path.to_str().unwrap());
path
let maybe_path = f(env_var(env_var_name));
if let Some(path) = maybe_path.as_ref() {
rsconf::set_env_value(env_var_name, path.to_str().unwrap());
}
maybe_path
}
fn join_if_relative(parent_if_relative: &Path, path: String) -> PathBuf {
@@ -195,11 +200,14 @@ fn join_if_relative(parent_if_relative: &Path, path: String) -> PathBuf {
}
let prefix = overridable_path("PREFIX", |env_prefix| {
PathBuf::from(env_prefix.unwrap_or("/usr/local".to_string()))
});
Some(PathBuf::from(
env_prefix.unwrap_or("/usr/local".to_string()),
))
})
.unwrap();
overridable_path("SYSCONFDIR", |env_sysconfdir| {
join_if_relative(
Some(join_if_relative(
&prefix,
env_sysconfdir.unwrap_or(
// Embedded builds use "/etc," not "$PREFIX/etc".
@@ -210,21 +218,30 @@ fn join_if_relative(parent_if_relative: &Path, path: String) -> PathBuf {
}
.to_string(),
),
)
))
});
#[cfg(not(feature = "embed-data"))]
{
let datadir = overridable_path("DATADIR", |env_datadir| {
join_if_relative(&prefix, env_datadir.unwrap_or("share/".to_string()))
});
overridable_path("BINDIR", |env_bindir| {
join_if_relative(&prefix, env_bindir.unwrap_or("bin/".to_string()))
});
overridable_path("DOCDIR", |env_docdir| {
join_if_relative(&datadir, env_docdir.unwrap_or("doc/fish".to_string()))
});
}
let default_ok = !cfg!(feature = "embed-data");
let datadir = overridable_path("DATADIR", |env_datadir| {
let default = default_ok.then_some("share/".to_string());
env_datadir
.or(default)
.map(|p| join_if_relative(&prefix, p))
});
overridable_path("BINDIR", |env_bindir| {
let default = default_ok.then_some("bin/".to_string());
env_bindir.or(default).map(|p| join_if_relative(&prefix, p))
});
overridable_path("DOCDIR", |env_docdir| {
let default = default_ok.then_some("doc/fish".to_string());
env_docdir.or(default).map(|p| {
join_if_relative(
&datadir
.expect("Setting DOCDIR without setting DATADIR is not currently supported"),
p,
)
})
});
}
fn get_version(src_dir: &Path) -> String {

View File

@@ -177,7 +177,7 @@ fn read_init(parser: &Parser, paths: &ConfigPaths) {
eprintf!("%s", msg);
}
} else {
let datapath = bytes2wcstring(paths.data.as_os_str().as_bytes());
let datapath = bytes2wcstring(paths.data.as_ref().unwrap().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

@@ -11,15 +11,14 @@
pub struct ConfigPaths {
pub sysconf: PathBuf, // e.g., /usr/local/etc
pub bin: Option<PathBuf>, // e.g., /usr/local/bin
#[cfg(not(feature = "embed-data"))]
pub data: PathBuf, // e.g., /usr/local/share
#[cfg(not(feature = "embed-data"))]
pub doc: PathBuf, // e.g., /usr/local/share/doc/fish
/// Always present if "embed-data" is disabled.
pub data: Option<PathBuf>, // e.g., /usr/local/share
/// Always present if "embed-data" is disabled.
pub doc: Option<PathBuf>, // e.g., /usr/local/share/doc/fish
}
const SYSCONF_DIR: &str = env!("SYSCONFDIR");
#[cfg(not(feature = "embed-data"))]
const DOC_DIR: &str = env!("DOCDIR");
const DOC_DIR: Option<&str> = option_env!("DOCDIR");
/// The kind of directory structure we assume.
/// Each variants is passed the executable path's parent, if available.
@@ -121,28 +120,29 @@ pub fn new() -> Self {
"paths.sysconf: %s",
paths.sysconf.display().to_string()
);
FLOGF!(
config,
"paths.bin: %s",
paths
.bin
.as_ref()
.map(|x| x.display().to_string())
.unwrap_or("|not found|".to_string()),
);
#[cfg(not(feature = "embed-data"))]
FLOGF!(config, "paths.data: %s", paths.data.display().to_string());
#[cfg(not(feature = "embed-data"))]
FLOGF!(config, "paths.doc: %s", paths.doc.display().to_string());
macro_rules! log_optional_path {
($field:ident) => {
FLOGF!(
config,
"paths.%s: %s",
stringify!($field),
paths
.$field
.as_ref()
.map(|x| x.display().to_string())
.unwrap_or("|not found|".to_string()),
);
};
}
log_optional_path!(bin);
log_optional_path!(data);
log_optional_path!(doc);
paths
}
fn from_layout(exec_path: DirectoryLayout) -> Self {
let workspace_root = workspace_root();
#[cfg(feature = "embed-data")]
FLOG!(config, "embed-data feature is active, ignoring data paths");
use DirectoryLayout::*;
match exec_path {
RelocatableTree(exec_path_parent) => {
@@ -150,16 +150,13 @@ fn from_layout(exec_path: DirectoryLayout) -> Self {
Self {
sysconf: prefix.join("etc/fish"),
bin: Some(exec_path_parent.to_owned()),
#[cfg(not(feature = "embed-data"))]
data: prefix.join("share/fish"),
// The docs dir may not exist; in that case fall back to the compiled in path.
#[cfg(not(feature = "embed-data"))]
data: Some(prefix.join("share/fish")),
doc: {
let doc = prefix.join("share/doc/fish");
if doc.exists() {
doc
Some(doc)
} else {
PathBuf::from(DOC_DIR)
DOC_DIR.map(PathBuf::from)
}
},
}
@@ -167,22 +164,16 @@ fn from_layout(exec_path: DirectoryLayout) -> Self {
BuildDirectory(exec_path_parent) => Self {
sysconf: workspace_root.join("etc"),
bin: Some(exec_path_parent.to_owned()),
#[cfg(not(feature = "embed-data"))]
data: workspace_root.join("share"),
#[cfg(not(feature = "embed-data"))]
doc: workspace_root.join("user_doc/html"),
data: Some(workspace_root.join("share")),
doc: Some(workspace_root.join("user_doc/html")),
},
#[allow(unused_variables)]
DefaultLayout(exec_path_parent) => Self {
sysconf: PathBuf::from(SYSCONF_DIR).join("fish"),
#[cfg(feature = "embed-data")]
bin: exec_path_parent,
#[cfg(not(feature = "embed-data"))]
bin: Some(PathBuf::from(env!("BINDIR"))),
#[cfg(not(feature = "embed-data"))]
data: PathBuf::from(env!("DATADIR")).join("fish"),
#[cfg(not(feature = "embed-data"))]
doc: DOC_DIR.into(),
bin: option_env!("BINDIR")
.map(PathBuf::from)
.or(exec_path_parent),
data: option_env!("DATADIR").map(|p| PathBuf::from(p).join("fish")),
doc: DOC_DIR.map(PathBuf::from),
},
}
}

View File

@@ -646,23 +646,14 @@ pub fn env_init(paths: Option<&ConfigPaths>, do_uvars: bool, default_paths: bool
set_path(FISH_SYSCONFDIR_VAR, Some(&paths.sysconf));
set_path(FISH_BIN_DIR, paths.bin.as_ref());
#[cfg(feature = "embed-data")]
vars.set_empty(FISH_DATADIR_VAR, EnvMode::GLOBAL);
#[cfg(not(feature = "embed-data"))]
{
let datadir = &paths.data;
set_path(FISH_DATADIR_VAR, Some(datadir));
if default_paths {
let mut scstr = datadir.clone();
scstr.push("functions");
set_path(L!("fish_function_path"), Some(&scstr));
}
let datadir = paths.data.as_ref();
set_path(FISH_DATADIR_VAR, datadir);
if !cfg!(feature = "embed-data") && default_paths {
let mut scstr = datadir.unwrap().clone();
scstr.push("functions");
set_path(L!("fish_function_path"), Some(&scstr));
}
#[cfg(feature = "embed-data")]
vars.set_empty(FISH_HELPDIR_VAR, EnvMode::GLOBAL);
#[cfg(not(feature = "embed-data"))]
set_path(FISH_HELPDIR_VAR, Some(&paths.doc));
set_path(FISH_HELPDIR_VAR, paths.doc.as_ref());
}
let user_config_dir = path_get_config();

View File

@@ -4,11 +4,15 @@
# CHECKERR: config: executable path: {{.*}}/fish
# CHECKERR: config: Running out of build directory, using paths relative to $CARGO_MANIFEST_DIR ({{.*}})
# CHECKERR: config: embed-data feature is active, ignoring data paths
# NOTE: When our executable is located outside the workspace, this is "/etc".
# CHECKERR: config: paths.sysconf: {{.+}}/etc
# CHECKERR: config: paths.bin: {{.*}}
# NOTE: When our executable is located outside the build directory, these are different.
# CHECKERR: config: paths.data: {{.*}}/share
# CHECKERR: config: paths.doc: {{.*}}/user_doc/html
# CHECKERR: config: sourcing {{.+}}/etc/config.fish
# CHECKERR: config: not sourcing {{.*}}/xdg_config_home/fish/config.fish (not readable or does not exist)