mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-23 13:11:15 -03:00
Make LOCALEDIR relocatable as well
As explained inc3740b85be(config_paths: fix compiled-in locale dir, 2025-06-12), fish is "relocatable", i.e. "mv /usr/ /usr2/" will leave "/usr2/bin/fish" fully functional. There is one exception: for LOCALEDIR we always use the path determined at compile time. This seems wrong; let's use the same relocatable-logic as for other paths. Inspired bybf65b9e3a7(Change `gettext` paths to be relocatable (#11195), 2025-03-30).
This commit is contained in:
38
src/env/config_paths.rs
vendored
38
src/env/config_paths.rs
vendored
@@ -9,6 +9,7 @@
|
||||
const DATA_DIR_SUBDIR: &str = env!("DATADIR_SUBDIR");
|
||||
const SYSCONF_DIR: &str = env!("SYSCONFDIR");
|
||||
const BIN_DIR: &str = env!("BINDIR");
|
||||
const LOCALE_DIR: &str = env!("LOCALEDIR");
|
||||
|
||||
pub static CONFIG_PATHS: Lazy<ConfigPaths> = Lazy::new(|| {
|
||||
// Read the current executable and follow all symlinks to it.
|
||||
@@ -51,6 +52,7 @@ fn determine_config_directory_paths(argv0: impl AsRef<Path>) -> ConfigPaths {
|
||||
sysconf: manifest_dir.join("etc"),
|
||||
doc: manifest_dir.join("user_doc/html"),
|
||||
bin: Some(exec_path.parent().unwrap().to_owned()),
|
||||
locale: Some(manifest_dir.join("share/locale")),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,18 +60,21 @@ fn determine_config_directory_paths(argv0: impl AsRef<Path>) -> ConfigPaths {
|
||||
// The next check is that we are in a relocatable directory tree
|
||||
if exec_path.ends_with("bin/fish") {
|
||||
let base_path = exec_path.parent().unwrap().parent().unwrap();
|
||||
#[cfg(feature = "installable")]
|
||||
let data = base_path.join("share/fish/install");
|
||||
#[cfg(not(feature = "installable"))]
|
||||
let data = base_path.join("share/fish");
|
||||
let locale = Some(data.join("locale"));
|
||||
paths = ConfigPaths {
|
||||
// One obvious path is ~/.local (with fish in ~/.local/bin/).
|
||||
// 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.
|
||||
#[cfg(feature = "installable")]
|
||||
data: base_path.join("share/fish/install"),
|
||||
#[cfg(not(feature = "installable"))]
|
||||
data: base_path.join("share/fish"),
|
||||
data,
|
||||
sysconf: base_path.join("etc/fish"),
|
||||
doc: base_path.join("share/doc/fish"),
|
||||
bin: Some(base_path.join("bin")),
|
||||
locale,
|
||||
}
|
||||
} else if exec_path.ends_with("fish") {
|
||||
FLOG!(
|
||||
@@ -77,14 +82,18 @@ fn determine_config_directory_paths(argv0: impl AsRef<Path>) -> ConfigPaths {
|
||||
"'fish' not in a 'bin/', trying paths relative to source tree"
|
||||
);
|
||||
let base_path = exec_path.parent().unwrap();
|
||||
#[cfg(feature = "installable")]
|
||||
let data = base_path.join("share/install");
|
||||
#[cfg(not(feature = "installable"))]
|
||||
let data = base_path.join("share");
|
||||
let locale = Some(data.join("locale"));
|
||||
|
||||
paths = ConfigPaths {
|
||||
#[cfg(feature = "installable")]
|
||||
data: base_path.join("share/install"),
|
||||
#[cfg(not(feature = "installable"))]
|
||||
data: base_path.join("share"),
|
||||
data,
|
||||
sysconf: base_path.join("etc"),
|
||||
doc: base_path.join("user_doc/html"),
|
||||
bin: Some(base_path.to_path_buf()),
|
||||
locale,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,6 +128,11 @@ fn determine_config_directory_paths(argv0: impl AsRef<Path>) -> ConfigPaths {
|
||||
} else {
|
||||
Some(PathBuf::from(BIN_DIR))
|
||||
};
|
||||
let locale = if cfg!(feature = "installable") {
|
||||
None
|
||||
} else {
|
||||
Some(PathBuf::from(LOCALE_DIR))
|
||||
};
|
||||
|
||||
FLOG!(config, "Using compiled in paths:");
|
||||
paths = ConfigPaths {
|
||||
@@ -126,13 +140,14 @@ fn determine_config_directory_paths(argv0: impl AsRef<Path>) -> ConfigPaths {
|
||||
sysconf: Path::new(SYSCONF_DIR).join("fish"),
|
||||
doc: DOC_DIR.into(),
|
||||
bin,
|
||||
locale,
|
||||
}
|
||||
}
|
||||
|
||||
FLOGF!(
|
||||
config,
|
||||
"determine_config_directory_paths() results:\npaths.data: %ls\npaths.sysconf: \
|
||||
%ls\npaths.doc: %ls\npaths.bin: %ls",
|
||||
%ls\npaths.doc: %ls\npaths.bin: %ls\npaths.locale: %ls",
|
||||
paths.data.display().to_string(),
|
||||
paths.sysconf.display().to_string(),
|
||||
paths.doc.display().to_string(),
|
||||
@@ -141,6 +156,11 @@ fn determine_config_directory_paths(argv0: impl AsRef<Path>) -> ConfigPaths {
|
||||
.clone()
|
||||
.map(|x| x.display().to_string())
|
||||
.unwrap_or("|not found|".to_string()),
|
||||
paths
|
||||
.locale
|
||||
.clone()
|
||||
.map(|x| x.display().to_string())
|
||||
.unwrap_or("|not found|".to_string()),
|
||||
);
|
||||
|
||||
paths
|
||||
|
||||
9
src/env/var.rs
vendored
9
src/env/var.rs
vendored
@@ -50,10 +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 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: Option<PathBuf>, // e.g., /usr/local/share/locale
|
||||
}
|
||||
|
||||
/// A collection of status and pipestatus.
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::CString;
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use crate::common::{charptr2wcstring, truncate_at_nul, wcs2zstring, PACKAGE_NAME};
|
||||
#[cfg(test)]
|
||||
use crate::tests::prelude::*;
|
||||
use crate::wchar::prelude::*;
|
||||
use crate::{
|
||||
common::{charptr2wcstring, truncate_at_nul, wcs2zstring, PACKAGE_NAME},
|
||||
env::CONFIG_PATHS,
|
||||
};
|
||||
use errno::{errno, set_errno};
|
||||
use once_cell::sync::{Lazy, OnceCell};
|
||||
|
||||
@@ -47,8 +51,11 @@ 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();
|
||||
let localedir = CString::new(env!("LOCALEDIR")).unwrap();
|
||||
let localedir = CString::new(localepath.as_os_str().as_bytes()).unwrap();
|
||||
fish_bindtextdomain(&package_name, &localedir);
|
||||
fish_textdomain(&package_name);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user