Explorar el Código

fix(cli): dev watcher infinite loop on mobile (#9017)

Lucas Fernandes Nogueira hace 1 año
padre
commit
d7d03c7197

+ 6 - 0
.changes/mobile-watcher.md

@@ -0,0 +1,6 @@
+---
+"@tauri-apps/cli": patch:bug
+"tauri-cli": patch:bug
+---
+
+Fixes dev watcher on mobile dev.

+ 0 - 1
tooling/cli/src/interface/mod.rs

@@ -21,7 +21,6 @@ pub trait DevProcess {
   fn try_wait(&self) -> std::io::Result<Option<ExitStatus>>;
   fn wait(&self) -> std::io::Result<ExitStatus>;
   fn manually_killed_process(&self) -> bool;
-  fn is_building_app(&self) -> bool;
 }
 
 pub trait AppSettings {

+ 25 - 29
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;
-                }
+            }
+
+            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)?;
             }
+            *p = run(self)?;
           }
         }
       }

+ 0 - 4
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<F: Fn(Option<i32>, ExitReason) + Send + Sync + 'static>(

+ 30 - 25
tooling/cli/src/interface/rust/manifest.rs

@@ -84,7 +84,7 @@ fn get_enabled_features(list: &HashMap<String, Vec<String>>, feature: &str) -> V
   f
 }
 
-pub fn read_manifest(manifest_path: &Path) -> crate::Result<Document> {
+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<Document> {
     .parse::<Document>()
     .with_context(|| "failed to parse Cargo.toml")?;
 
-  Ok(manifest)
+  Ok((manifest, manifest_str))
 }
 
 pub fn toml_array(features: &HashSet<String>) -> Array {
@@ -265,9 +265,9 @@ fn inject_features(
   Ok(persist)
 }
 
-pub fn rewrite_manifest(config: &Config) -> crate::Result<Manifest> {
+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<Manifest> {
     .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,
+    ))
   }
 }
 

+ 1 - 1
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 =

+ 7 - 6
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<Option<ExitStatus>> {
@@ -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)]