diff --git a/.changes/mobile-watcher.md b/.changes/mobile-watcher.md new file mode 100644 index 000000000..2402e4f8f --- /dev/null +++ b/.changes/mobile-watcher.md @@ -0,0 +1,6 @@ +--- +"@tauri-apps/cli": patch:bug +"tauri-cli": patch:bug +--- + +Fixes dev watcher on mobile dev. diff --git a/tooling/cli/src/interface/mod.rs b/tooling/cli/src/interface/mod.rs index 215caf219..6b7292da1 100644 --- a/tooling/cli/src/interface/mod.rs +++ b/tooling/cli/src/interface/mod.rs @@ -21,7 +21,6 @@ pub trait DevProcess { fn try_wait(&self) -> std::io::Result>; fn wait(&self) -> std::io::Result; fn manually_killed_process(&self) -> bool; - fn is_building_app(&self) -> bool; } pub trait AppSettings { diff --git a/tooling/cli/src/interface/rust.rs b/tooling/cli/src/interface/rust.rs index dd3984f72..1abe870f0 100644 --- a/tooling/cli/src/interface/rust.rs +++ b/tooling/cli/src/interface/rust.rs @@ -121,7 +121,7 @@ impl Interface for Rust { watcher .watcher() .watch(&tauri_dir().join("Cargo.toml"), RecursiveMode::Recursive)?; - let manifest = rewrite_manifest(config)?; + let (manifest, _modified) = rewrite_manifest(config)?; let now = Instant::now(); let timeout = Duration::from_secs(2); loop { @@ -535,38 +535,34 @@ impl Rust { if !ignore_matcher.is_ignore(&event_path, event_path.is_dir()) { if is_configuration_file(self.app_settings.target, &event_path) { - match reload_config(config.as_ref()) { - Ok(config) => { - info!("Tauri configuration changed. Rewriting manifest..."); - *self.app_settings.manifest.lock().unwrap() = - rewrite_manifest(config.lock().unwrap().as_ref().unwrap())? - } - Err(err) => { - let p = process.lock().unwrap(); - if p.is_building_app() { - p.kill().with_context(|| "failed to kill app process")?; - } - error!("{}", err); + if let Ok(config) = reload_config(config.as_ref()) { + let (manifest, modified) = + rewrite_manifest(config.lock().unwrap().as_ref().unwrap())?; + if modified { + *self.app_settings.manifest.lock().unwrap() = manifest; + // no need to run the watcher logic, the manifest was modified + // and it will trigger the watcher again + continue; } } - } else { - info!( - "File {} changed. Rebuilding application...", - display_path(event_path.strip_prefix(app_path).unwrap_or(&event_path)) - ); - // When tauri.conf.json is changed, rewrite_manifest will be called - // which will trigger the watcher again - // So the app should only be started when a file other than tauri.conf.json is changed - let mut p = process.lock().unwrap(); - p.kill().with_context(|| "failed to kill app process")?; - // wait for the process to exit - loop { - if let Ok(Some(_)) = p.try_wait() { - break; - } - } - *p = run(self)?; } + + log::info!( + "File {} changed. Rebuilding application...", + display_path(event_path.strip_prefix(app_path).unwrap_or(&event_path)) + ); + + let mut p = process.lock().unwrap(); + p.kill().with_context(|| "failed to kill app process")?; + + // wait for the process to exit + // note that on mobile, kill() already waits for the process to exit (duct implementation) + loop { + if !matches!(p.try_wait(), Ok(None)) { + break; + } + } + *p = run(self)?; } } } diff --git a/tooling/cli/src/interface/rust/desktop.rs b/tooling/cli/src/interface/rust/desktop.rs index 6e308136d..b260ae45f 100644 --- a/tooling/cli/src/interface/rust/desktop.rs +++ b/tooling/cli/src/interface/rust/desktop.rs @@ -62,10 +62,6 @@ impl DevProcess for DevChild { fn manually_killed_process(&self) -> bool { self.manually_killed_app.load(Ordering::Relaxed) } - - fn is_building_app(&self) -> bool { - self.app_child.lock().unwrap().is_none() - } } pub fn run_dev, ExitReason) + Send + Sync + 'static>( diff --git a/tooling/cli/src/interface/rust/manifest.rs b/tooling/cli/src/interface/rust/manifest.rs index e196679d9..8a975b30b 100644 --- a/tooling/cli/src/interface/rust/manifest.rs +++ b/tooling/cli/src/interface/rust/manifest.rs @@ -84,7 +84,7 @@ fn get_enabled_features(list: &HashMap>, feature: &str) -> V f } -pub fn read_manifest(manifest_path: &Path) -> crate::Result { +pub fn read_manifest(manifest_path: &Path) -> crate::Result<(Document, String)> { let mut manifest_str = String::new(); let mut manifest_file = File::open(manifest_path) @@ -95,7 +95,7 @@ pub fn read_manifest(manifest_path: &Path) -> crate::Result { .parse::() .with_context(|| "failed to parse Cargo.toml")?; - Ok(manifest) + Ok((manifest, manifest_str)) } pub fn toml_array(features: &HashSet) -> Array { @@ -265,9 +265,9 @@ fn inject_features( Ok(persist) } -pub fn rewrite_manifest(config: &Config) -> crate::Result { +pub fn rewrite_manifest(config: &Config) -> crate::Result<(Manifest, bool)> { let manifest_path = tauri_dir().join("Cargo.toml"); - let mut manifest = read_manifest(&manifest_path)?; + let (mut manifest, original_manifest_str) = read_manifest(&manifest_path)?; let mut dependencies = Vec::new(); @@ -303,31 +303,36 @@ pub fn rewrite_manifest(config: &Config) -> crate::Result { .unwrap() .features; - if persist { + let new_manifest_str = manifest + .to_string() + // apply some formatting fixes + .replace(r#"" ,features =["#, r#"", features = ["#) + .replace(r#"" , features"#, r#"", features"#) + .replace("]}", "] }") + .replace("={", "= {") + .replace("=[", "= [") + .replace(r#"",""#, r#"", ""#); + + if persist && original_manifest_str != new_manifest_str { let mut manifest_file = File::create(&manifest_path).with_context(|| "failed to open Cargo.toml for rewrite")?; - manifest_file.write_all( - manifest - .to_string() - // apply some formatting fixes - .replace(r#"" ,features =["#, r#"", features = ["#) - .replace(r#"" , features"#, r#"", features"#) - .replace("]}", "] }") - .replace("={", "= {") - .replace("=[", "= [") - .replace(r#"",""#, r#"", ""#) - .as_bytes(), - )?; + manifest_file.write_all(new_manifest_str.as_bytes())?; manifest_file.flush()?; - Ok(Manifest { - inner: manifest, - tauri_features, - }) + Ok(( + Manifest { + inner: manifest, + tauri_features, + }, + true, + )) } else { - Ok(Manifest { - inner: manifest, - tauri_features, - }) + Ok(( + Manifest { + inner: manifest, + tauri_features, + }, + false, + )) } } diff --git a/tooling/cli/src/migrate/manifest.rs b/tooling/cli/src/migrate/manifest.rs index f2071f4dd..83ccc0250 100644 --- a/tooling/cli/src/migrate/manifest.rs +++ b/tooling/cli/src/migrate/manifest.rs @@ -15,7 +15,7 @@ const CRATE_TYPES: [&str; 3] = ["lib", "staticlib", "cdylib"]; pub fn migrate(tauri_dir: &Path) -> Result<()> { let manifest_path = tauri_dir.join("Cargo.toml"); - let mut manifest = read_manifest(&manifest_path)?; + let (mut manifest, _) = read_manifest(&manifest_path)?; migrate_manifest(&mut manifest)?; let mut manifest_file = diff --git a/tooling/cli/src/mobile/mod.rs b/tooling/cli/src/mobile/mod.rs index 02012538c..f728899e4 100644 --- a/tooling/cli/src/mobile/mod.rs +++ b/tooling/cli/src/mobile/mod.rs @@ -69,9 +69,14 @@ impl DevChild { impl DevProcess for DevChild { fn kill(&self) -> std::io::Result<()> { - self.child.kill()?; self.manually_killed_process.store(true, Ordering::Relaxed); - Ok(()) + match self.child.kill() { + Ok(_) => Ok(()), + Err(e) => { + self.manually_killed_process.store(false, Ordering::Relaxed); + Err(e) + } + } } fn try_wait(&self) -> std::io::Result> { @@ -85,10 +90,6 @@ impl DevProcess for DevChild { fn manually_killed_process(&self) -> bool { self.manually_killed_process.load(Ordering::Relaxed) } - - fn is_building_app(&self) -> bool { - false - } } #[derive(PartialEq, Eq, Copy, Clone)]