fix(os): find in-repo resources from release builds run in the workspace

Testing with a real user config showed that `target/release/ghostty` and
`target/production/ghostty` (also `cargo run --profile production`, which
the README recommends) silently ran without resources: the configured
theme was not applied, bash shell integration was disabled ("no resources
dir set") so tab titles, the prompt cursor and cwd inheritance for new
tabs/splits broke, and terminfo was missing.

Zig never hits this because `zig build` installs `zig-out/share/ghostty`
next to `zig-out/bin`, which the exe-relative sentinel search finds. Cargo
has no such tree; the Rust-specific fallback to `<workspace>/resources`
was limited to the dev profile. It now applies to every profile. It only
triggers when the exe lives inside the workspace it was built from, after
GHOSTTY_RESOURCES_DIR and the share/ sentinel search, so installed
binaries are unaffected.

Test Plan:
- cargo test -p ghostty-os (dev_fallback_finds_workspace_resources now
  covers release builds and env precedence)
- run target/production/ghostty with `theme = Catppuccin Mocha` and
  `shell-integration = bash`: theme applied, titles show the cwd
This commit is contained in:
ddidderr committed 2026-10-12 21:11:39 +02:00
1 parent 908d5b105a
commit 733df84eaf
2 files changed
+15 -11

No files matched your search

+12 -8
View File
@@ -143,12 +143,12 @@ fn resources_dir_impl(debug: bool, exe: Option<&Path>, env: Option<OsString>) ->
};
}
// Rust-specific: development builds run out of `<workspace>/target`, where
// there is no installed `share/` tree. Fall back to the in-repo
// `<workspace>/resources` directory (it carries the same sentinel,
// `terminfo/x/xterm-ghostty`, see scripts/gen-terminfo.sh) if the binary
// lives inside this workspace.
if debug && let Some(dir) = dev_resources_dir(exe_start) {
// Rust-specific: builds of any profile run out of `<workspace>/target`,
// where there is no `share/` tree (Zig installs one into `zig-out/share`
// next to `zig-out/bin`). Fall back to the in-repo `<workspace>/resources`
// directory (it carries the same sentinel, `terminfo/x/xterm-ghostty`, see
// scripts/gen-terminfo.sh) if the binary lives inside this workspace.
if let Some(dir) = dev_resources_dir(exe_start) {
return ResourcesDir {
app_path: Some(enc(&dir)),
host_path: None,
@@ -261,9 +261,13 @@ mod tests {
// Outside the workspace there is no fallback.
let r = resources_dir_impl(true, Some(Path::new("/nonexistent/bin/x")), None);
assert_eq!(r.app().map(EncodedOs::as_encoded), None);
// Release builds never use it.
// Release builds run from the workspace use it too...
let exe = workspace_root().join("target/production/ghostty");
let r = resources_dir_impl(false, Some(&exe), None);
assert_eq!(r.app().map(EncodedOs::as_encoded), None);
assert!(r.app().is_some_and(|d| d.ends_with_plain("/resources")));
// ...but GHOSTTY_RESOURCES_DIR still takes precedence there.
let r = resources_dir_impl(false, Some(&exe), Some("/env/res".into()));
assert_eq!(r.app_os().unwrap(), Path::new("/env/res"));
}
#[test]