fix(core): Incorrect resource_dir when app run from new style target/PLATFORM+ARCH/(debug|release) dir (#8852)

* Fix resource_dir when app run from new target/someting/(debug|release) dir

* Update core/tauri-utils/src/platform.rs

Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com>

* change file, update logic, add tests

* lint

* fix tests

---------

Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com>
Co-authored-by: Lucas Nogueira <lucas@tauri.app>
This commit is contained in:
Sam Willis 2024-02-18 18:10:21 +00:00 committed by GitHub
parent ed33b851c7
commit 28fb036ce4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 105 additions and 9 deletions

View File

@ -0,0 +1,5 @@
---
"tauri-utils": patch:enhance
---
Enhance resource directory resolution on development.

View File

@ -1095,7 +1095,14 @@
]
},
"windows": {
"description": "List of windows that uses this capability. Can be a glob pattern.",
"description": "List of windows that uses this capability. Can be a glob pattern.\n\nOn multiwebview windows, prefer [`Self::webviews`] for a fine grained access control.",
"type": "array",
"items": {
"type": "string"
}
},
"webviews": {
"description": "List of webviews that uses this capability. Can be a glob pattern.\n\nThis is only required when using on multiwebview contexts, by default all child webviews of a window that matches [`Self::windows`] are linked.",
"type": "array",
"items": {
"type": "string"

View File

@ -6,7 +6,7 @@
use std::{
fmt::Display,
path::{PathBuf, MAIN_SEPARATOR},
path::{Path, PathBuf, MAIN_SEPARATOR},
};
use serde::{Deserialize, Serialize};
@ -221,6 +221,28 @@ pub fn target_triple() -> crate::Result<String> {
Ok(format!("{arch}-{os}"))
}
#[cfg(not(test))]
fn is_cargo_output_directory(path: &Path) -> bool {
path.join(".cargo-lock").exists()
}
#[cfg(test)]
const CARGO_OUTPUT_DIRECTORIES: &[&str] = &["debug", "release", "custom-profile"];
#[cfg(test)]
fn is_cargo_output_directory(path: &Path) -> bool {
let last_component = path
.components()
.last()
.unwrap()
.as_os_str()
.to_str()
.unwrap();
CARGO_OUTPUT_DIRECTORIES
.iter()
.any(|dirname| &last_component == dirname)
}
/// Computes the resource directory of the current environment.
///
/// On Windows, it's the path to the executable.
@ -233,17 +255,32 @@ pub fn target_triple() -> crate::Result<String> {
/// `${exe_dir}/../lib/${exe_name}`.
///
/// On MacOS, it's `${exe_dir}../Resources` (inside .app).
#[allow(unused_variables)]
pub fn resource_dir(package_info: &PackageInfo, env: &Env) -> crate::Result<PathBuf> {
let exe = current_exe()?;
let exe_dir = exe.parent().expect("failed to get exe directory");
resource_dir_from(exe, package_info, env)
}
#[allow(unused_variables)]
fn resource_dir_from<P: AsRef<Path>>(
exe: P,
package_info: &PackageInfo,
env: &Env,
) -> crate::Result<PathBuf> {
let exe_dir = exe.as_ref().parent().expect("failed to get exe directory");
let curr_dir = exe_dir.display().to_string();
if curr_dir.ends_with(format!("{MAIN_SEPARATOR}target{MAIN_SEPARATOR}debug").as_str())
|| curr_dir.ends_with(format!("{MAIN_SEPARATOR}target{MAIN_SEPARATOR}release").as_str())
|| cfg!(target_os = "windows")
let parts: Vec<&str> = curr_dir.split(MAIN_SEPARATOR).collect();
let len = parts.len();
// Check if running from the Cargo output directory, which means it's an executable in a development machine
// We check if the binary is inside a `target` folder which can be either `target/$profile` or `target/$triple/$profile`
// and see if there's a .cargo-lock file along the executable
// This ensures the check is safer so it doesn't affect apps in production
// Windows also includes the resources in the executable folder so we check that too
if cfg!(target_os = "windows")
|| ((len >= 2 && parts[len - 2] == "target") || (len >= 3 && parts[len - 3] == "target"))
&& is_cargo_output_directory(exe_dir)
{
// running from the out dir or windows
return Ok(exe_dir.to_path_buf());
}
@ -306,3 +343,43 @@ mod build {
}
}
}
#[cfg(test)]
mod tests {
use std::path::PathBuf;
use crate::{Env, PackageInfo};
#[test]
fn resolve_resource_dir() {
let package_info = PackageInfo {
name: "MyApp".into(),
version: "1.0.0".parse().unwrap(),
authors: "",
description: "",
crate_name: "",
};
let env = Env::default();
let path = PathBuf::from("/path/to/target/aarch64-apple-darwin/debug/app");
let resource_dir = super::resource_dir_from(&path, &package_info, &env).unwrap();
assert_eq!(resource_dir, path.parent().unwrap());
let path = PathBuf::from("/path/to/target/custom-profile/app");
let resource_dir = super::resource_dir_from(&path, &package_info, &env).unwrap();
assert_eq!(resource_dir, path.parent().unwrap());
let path = PathBuf::from("/path/to/target/release/app");
let resource_dir = super::resource_dir_from(&path, &package_info, &env).unwrap();
assert_eq!(resource_dir, path.parent().unwrap());
let path = PathBuf::from("/path/to/target/unknown-profile/app");
let resource_dir = super::resource_dir_from(&path, &package_info, &env);
#[cfg(target_os = "macos")]
assert!(resource_dir.is_err());
#[cfg(target_os = "linux")]
assert_eq!(resource_dir.unwrap(), PathBuf::from("/usr/lib/my-app"));
#[cfg(windows)]
assert_eq!(resource_dir.unwrap(), path.parent().unwrap());
}
}

View File

@ -1095,7 +1095,14 @@
]
},
"windows": {
"description": "List of windows that uses this capability. Can be a glob pattern.",
"description": "List of windows that uses this capability. Can be a glob pattern.\n\nOn multiwebview windows, prefer [`Self::webviews`] for a fine grained access control.",
"type": "array",
"items": {
"type": "string"
}
},
"webviews": {
"description": "List of webviews that uses this capability. Can be a glob pattern.\n\nThis is only required when using on multiwebview contexts, by default all child webviews of a window that matches [`Self::windows`] are linked.",
"type": "array",
"items": {
"type": "string"