fix(cli): kill beforeDevCommand if dev code returns an error (#3907)

This commit is contained in:
Lucas Fernandes Nogueira
2022-04-19 15:04:42 -07:00
committed by GitHub
parent f2a30d8bc5
commit 485c97438a
4 changed files with 92 additions and 51 deletions

View File

@@ -0,0 +1,6 @@
---
"cli.rs": patch
"cli.js": patch
---
Kill the `beforeDevCommand` and app processes if the dev command returns an error.

View File

@@ -23,9 +23,9 @@
svelte-hmr "^0.14.7"
"@tauri-apps/api@../../tooling/api/dist":
version "1.0.0-rc.1"
version "1.0.0-rc.2"
dependencies:
type-fest "2.12.0"
type-fest "2.12.1"
debug@^4.3.2:
version "4.3.3"
@@ -262,10 +262,10 @@ svelte@3.35.0:
resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.35.0.tgz#e0d0ba60c4852181c2b4fd851194be6fda493e65"
integrity sha512-gknlZkR2sXheu/X+B7dDImwANVvK1R0QGQLd8CNIfxxGPeXBmePnxfzb6fWwTQRsYQG7lYkZXvpXJvxvpsoB7g==
type-fest@2.12.0:
version "2.12.0"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.12.0.tgz#ce342f58cab9114912f54b493d60ab39c3fc82b6"
integrity sha512-Qe5GRT+n/4GoqCNGGVp5Snapg1Omq3V7irBJB3EaKsp7HWDo5Gv2d/67gfNyV+d5EXD+x/RF5l1h4yJ7qNkcGA==
type-fest@2.12.1:
version "2.12.1"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.12.1.tgz#d2be8f50bf5f8f0a5fd916d29bf3e98c17e960be"
integrity sha512-AiknQSEqKVGDDjtZqeKrUoTlcj7FKhupmnVUgz6KoOKtvMwRGE6hUNJ/nVear+h7fnUPO1q/htSkYKb1pyntkQ==
vite@^2.6.4:
version "2.6.14"

View File

@@ -6,8 +6,8 @@ use crate::{
helpers::{
app_paths::{app_dir, tauri_dir},
command_env,
config::{get as get_config, reload as reload_config, AppUrl, WindowUrl},
manifest::{get_workspace_members, rewrite_manifest, Manifest},
config::{get as get_config, reload as reload_config, AppUrl, ConfigHandle, WindowUrl},
manifest::{rewrite_manifest, Manifest},
Logger,
},
CommandExt, Result,
@@ -22,10 +22,12 @@ use shared_child::SharedChild;
use std::{
env::set_current_dir,
ffi::OsStr,
fs::FileType,
path::{Path, PathBuf},
process::{exit, Command},
sync::{
atomic::{AtomicBool, Ordering},
mpsc::{channel, Receiver},
mpsc::{channel, Receiver, Sender},
Arc, Mutex,
},
time::Duration,
@@ -63,6 +65,14 @@ pub struct Options {
}
pub fn command(options: Options) -> Result<()> {
let r = command_internal(options);
if r.is_err() {
kill_before_dev_process();
}
r
}
fn command_internal(options: Options) -> Result<()> {
let logger = Logger::new("tauri:dev");
let tauri_path = tauri_dir();
@@ -151,7 +161,7 @@ pub fn command(options: Options) -> Result<()> {
.or(runner_from_config)
.unwrap_or_else(|| "cargo".to_string());
let mut manifest = {
let manifest = {
let (tx, rx) = channel();
let mut watcher = watcher(tx, Duration::from_secs(1)).unwrap();
watcher.watch(tauri_path.join("Cargo.toml"), RecursiveMode::Recursive)?;
@@ -239,26 +249,78 @@ pub fn command(options: Options) -> Result<()> {
}
}
let mut process = start_app(
let process = start_app(
&options,
&runner,
&manifest,
&cargo_features,
child_wait_rx.clone(),
)?;
let shared_process = Arc::new(Mutex::new(process));
if let Err(e) = watch(
shared_process.clone(),
child_wait_tx,
child_wait_rx,
tauri_path,
merge_config,
config,
options,
runner,
manifest,
cargo_features,
) {
shared_process
.lock()
.unwrap()
.kill()
.with_context(|| "failed to kill app process")?;
Err(e)
} else {
Ok(())
}
}
fn lookup<F: FnMut(&OsStr, FileType, PathBuf)>(dir: &Path, mut f: F) {
let mut builder = ignore::WalkBuilder::new(dir);
builder.require_git(false).ignore(false).max_depth(Some(1));
for entry in builder.build().flatten() {
f(
entry.file_name(),
entry.file_type().unwrap(),
dir.join(entry.path()),
);
}
}
#[allow(clippy::too_many_arguments)]
fn watch(
process: Arc<Mutex<Arc<SharedChild>>>,
child_wait_tx: Sender<()>,
child_wait_rx: Arc<Mutex<Receiver<()>>>,
tauri_path: PathBuf,
merge_config: Option<String>,
config: ConfigHandle,
options: Options,
runner: String,
mut manifest: Manifest,
cargo_features: Vec<String>,
) -> Result<()> {
let (tx, rx) = channel();
let mut watcher = watcher(tx, Duration::from_secs(1)).unwrap();
watcher.watch(tauri_path.join("src"), RecursiveMode::Recursive)?;
watcher.watch(tauri_path.join("Cargo.toml"), RecursiveMode::Recursive)?;
watcher.watch(tauri_path.join("tauri.conf.json"), RecursiveMode::Recursive)?;
for member in get_workspace_members()? {
let workspace_path = tauri_path.join(member);
watcher.watch(workspace_path.join("src"), RecursiveMode::Recursive)?;
watcher.watch(workspace_path.join("Cargo.toml"), RecursiveMode::Recursive)?;
}
lookup(&tauri_path, |file_name, file_type, path| {
if file_name != "target" && file_name != "Cargo.lock" {
let _ = watcher.watch(
path,
if file_type.is_dir() {
RecursiveMode::Recursive
} else {
RecursiveMode::NonRecursive
},
);
}
});
loop {
if let Ok(event) = rx.recv() {
@@ -279,16 +341,15 @@ pub fn command(options: Options) -> Result<()> {
// which will trigger the watcher again
// So the app should only be started when a file other than tauri.conf.json is changed
let _ = child_wait_tx.send(());
process
.kill()
.with_context(|| "failed to kill app process")?;
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(_)) = process.try_wait() {
if let Ok(Some(_)) = p.try_wait() {
break;
}
}
process = start_app(
*p = start_app(
&options,
&runner,
&manifest,

View File

@@ -234,29 +234,3 @@ pub fn rewrite_manifest(config: ConfigHandle) -> crate::Result<Manifest> {
Err(e) => Err(e),
}
}
pub fn get_workspace_members() -> crate::Result<Vec<String>> {
let mut manifest = read_manifest(&tauri_dir().join("Cargo.toml"))?;
let workspace = manifest
.as_table_mut()
.entry("workspace")
.or_insert(Item::None)
.as_table_mut();
match workspace {
Some(workspace) => {
let members = workspace
.entry("members")
.or_insert(Item::None)
.as_array()
.expect("workspace members aren't an array");
Ok(
members
.iter()
.map(|v| v.as_str().unwrap().to_string())
.collect(),
)
}
None => Ok(vec![]),
}
}