|
@@ -8,7 +8,7 @@ use std::{
|
|
|
fs::{File, FileType},
|
|
|
io::{Read, Write},
|
|
|
path::{Path, PathBuf},
|
|
|
- process::ExitStatus,
|
|
|
+ process::{Command, ExitStatus},
|
|
|
str::FromStr,
|
|
|
sync::{
|
|
|
mpsc::{channel, sync_channel},
|
|
@@ -20,7 +20,6 @@ use std::{
|
|
|
use anyhow::Context;
|
|
|
#[cfg(target_os = "linux")]
|
|
|
use heck::ToKebabCase;
|
|
|
-use log::warn;
|
|
|
use log::{debug, info};
|
|
|
use notify::{watcher, DebouncedEvent, RecursiveMode, Watcher};
|
|
|
use serde::Deserialize;
|
|
@@ -35,8 +34,10 @@ use crate::helpers::{
|
|
|
config::{reload as reload_config, wix_settings, Config},
|
|
|
};
|
|
|
|
|
|
+mod cargo_config;
|
|
|
mod desktop;
|
|
|
mod manifest;
|
|
|
+use cargo_config::Config as CargoConfig;
|
|
|
use manifest::{rewrite_manifest, Manifest};
|
|
|
|
|
|
#[derive(Debug, Default, Clone)]
|
|
@@ -305,7 +306,7 @@ impl Rust {
|
|
|
let process = Arc::new(Mutex::new(child));
|
|
|
let (tx, rx) = channel();
|
|
|
let tauri_path = tauri_dir();
|
|
|
- let workspace_path = get_workspace_dir(&tauri_path);
|
|
|
+ let workspace_path = get_workspace_dir()?;
|
|
|
|
|
|
let watch_folders = if tauri_path == workspace_path {
|
|
|
vec![tauri_path]
|
|
@@ -439,22 +440,12 @@ impl CargoSettings {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-#[derive(Deserialize)]
|
|
|
-struct CargoBuildConfig {
|
|
|
- #[serde(rename = "target-dir")]
|
|
|
- target_dir: Option<String>,
|
|
|
-}
|
|
|
-
|
|
|
-#[derive(Deserialize)]
|
|
|
-struct CargoConfig {
|
|
|
- build: Option<CargoBuildConfig>,
|
|
|
-}
|
|
|
-
|
|
|
pub struct RustAppSettings {
|
|
|
manifest: Manifest,
|
|
|
cargo_settings: CargoSettings,
|
|
|
cargo_package_settings: CargoPackageSettings,
|
|
|
package_settings: PackageSettings,
|
|
|
+ cargo_config: CargoConfig,
|
|
|
}
|
|
|
|
|
|
impl AppSettings for RustAppSettings {
|
|
@@ -642,11 +633,14 @@ impl RustAppSettings {
|
|
|
default_run: cargo_package_settings.default_run.clone(),
|
|
|
};
|
|
|
|
|
|
+ let cargo_config = CargoConfig::load(&tauri_dir())?;
|
|
|
+
|
|
|
Ok(Self {
|
|
|
manifest,
|
|
|
cargo_settings,
|
|
|
cargo_package_settings,
|
|
|
package_settings,
|
|
|
+ cargo_config,
|
|
|
})
|
|
|
}
|
|
|
|
|
@@ -655,100 +649,60 @@ impl RustAppSettings {
|
|
|
}
|
|
|
|
|
|
pub fn out_dir(&self, target: Option<String>, debug: bool) -> crate::Result<PathBuf> {
|
|
|
- let tauri_dir = tauri_dir();
|
|
|
- let workspace_dir = get_workspace_dir(&tauri_dir);
|
|
|
- get_target_dir(&workspace_dir, target, !debug)
|
|
|
+ get_target_dir(
|
|
|
+ target
|
|
|
+ .as_deref()
|
|
|
+ .or_else(|| self.cargo_config.build().target()),
|
|
|
+ !debug,
|
|
|
+ )
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-/// This function determines where 'target' dir is and suffixes it with 'release' or 'debug'
|
|
|
+#[derive(Deserialize)]
|
|
|
+struct CargoMetadata {
|
|
|
+ target_directory: PathBuf,
|
|
|
+ workspace_root: PathBuf,
|
|
|
+}
|
|
|
+
|
|
|
+fn get_cargo_metadata() -> crate::Result<CargoMetadata> {
|
|
|
+ let output = Command::new("cargo")
|
|
|
+ .args(["metadata", "--no-deps", "--format-version", "1"])
|
|
|
+ .current_dir(tauri_dir())
|
|
|
+ .output()?;
|
|
|
+
|
|
|
+ if !output.status.success() {
|
|
|
+ return Err(anyhow::anyhow!(
|
|
|
+ "cargo metadata command exited with a non zero exit code: {}",
|
|
|
+ String::from_utf8(output.stderr)?
|
|
|
+ ));
|
|
|
+ }
|
|
|
+
|
|
|
+ Ok(serde_json::from_slice(&output.stdout)?)
|
|
|
+}
|
|
|
+
|
|
|
+/// This function determines the 'target' directory and suffixes it with 'release' or 'debug'
|
|
|
/// to determine where the compiled binary will be located.
|
|
|
-fn get_target_dir(
|
|
|
- project_root_dir: &Path,
|
|
|
- target: Option<String>,
|
|
|
- is_release: bool,
|
|
|
-) -> crate::Result<PathBuf> {
|
|
|
- let mut path: PathBuf = match std::env::var_os("CARGO_TARGET_DIR") {
|
|
|
- Some(target_dir) => target_dir.into(),
|
|
|
- None => {
|
|
|
- let mut root_dir = project_root_dir.to_path_buf();
|
|
|
- let target_path: Option<PathBuf> = loop {
|
|
|
- // cargo reads configs under .cargo/config.toml or .cargo/config
|
|
|
- let mut cargo_config_path = root_dir.join(".cargo/config");
|
|
|
- if !cargo_config_path.exists() {
|
|
|
- cargo_config_path = root_dir.join(".cargo/config.toml");
|
|
|
- }
|
|
|
- // if the path exists, parse it
|
|
|
- if cargo_config_path.exists() {
|
|
|
- let mut config_str = String::new();
|
|
|
- let mut config_file = File::open(&cargo_config_path)
|
|
|
- .with_context(|| format!("failed to open {:?}", cargo_config_path))?;
|
|
|
- config_file
|
|
|
- .read_to_string(&mut config_str)
|
|
|
- .with_context(|| "failed to read cargo config file")?;
|
|
|
- let config: CargoConfig =
|
|
|
- toml::from_str(&config_str).with_context(|| "failed to parse cargo config file")?;
|
|
|
- if let Some(build) = config.build {
|
|
|
- if let Some(target_dir) = build.target_dir {
|
|
|
- break Some(target_dir.into());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- if !root_dir.pop() {
|
|
|
- break None;
|
|
|
- }
|
|
|
- };
|
|
|
- target_path.unwrap_or_else(|| project_root_dir.join("target"))
|
|
|
- }
|
|
|
- };
|
|
|
+fn get_target_dir(target: Option<&str>, is_release: bool) -> crate::Result<PathBuf> {
|
|
|
+ let mut path = get_cargo_metadata()
|
|
|
+ .with_context(|| "failed to get cargo metadata")?
|
|
|
+ .target_directory;
|
|
|
|
|
|
- if let Some(ref triple) = target {
|
|
|
+ if let Some(triple) = target {
|
|
|
path.push(triple);
|
|
|
}
|
|
|
+
|
|
|
path.push(if is_release { "release" } else { "debug" });
|
|
|
+
|
|
|
Ok(path)
|
|
|
}
|
|
|
|
|
|
-/// Walks up the file system, looking for a Cargo.toml file
|
|
|
-/// If one is found before reaching the root, then the current_dir's package belongs to that parent workspace if it's listed on [workspace.members].
|
|
|
-///
|
|
|
-/// If this package is part of a workspace, returns the path to the workspace directory
|
|
|
-/// Otherwise returns the current directory.
|
|
|
-pub fn get_workspace_dir(current_dir: &Path) -> PathBuf {
|
|
|
- let mut dir = current_dir.to_path_buf();
|
|
|
- let project_path = dir.clone();
|
|
|
-
|
|
|
- while dir.pop() {
|
|
|
- if dir.join("Cargo.toml").exists() {
|
|
|
- match CargoSettings::load(&dir) {
|
|
|
- Ok(cargo_settings) => {
|
|
|
- if let Some(workspace_settings) = cargo_settings.workspace {
|
|
|
- if let Some(members) = workspace_settings.members {
|
|
|
- if members.iter().any(|member| {
|
|
|
- glob::glob(&dir.join(member).to_string_lossy())
|
|
|
- .unwrap()
|
|
|
- .any(|p| p.unwrap() == project_path)
|
|
|
- }) {
|
|
|
- return dir;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- Err(e) => {
|
|
|
- warn!(
|
|
|
- "Found `{}`, which may define a parent workspace, but \
|
|
|
- failed to parse it. If this is indeed a parent workspace, undefined behavior may occur: \
|
|
|
- \n {:#}",
|
|
|
- dir.display(),
|
|
|
- e
|
|
|
- );
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Nothing found walking up the file system, return the starting directory
|
|
|
- current_dir.to_path_buf()
|
|
|
+/// Executes `cargo metadata` to get the workspace directory.
|
|
|
+pub fn get_workspace_dir() -> crate::Result<PathBuf> {
|
|
|
+ Ok(
|
|
|
+ get_cargo_metadata()
|
|
|
+ .with_context(|| "failed to get cargo metadata")?
|
|
|
+ .workspace_root,
|
|
|
+ )
|
|
|
}
|
|
|
|
|
|
#[allow(unused_variables)]
|