Skip to content

Commit 485c974

Browse files
authored
fix(cli): kill beforeDevCommand if dev code returns an error (#3907)
1 parent f2a30d8 commit 485c974

File tree

4 files changed

+92
-51
lines changed

4 files changed

+92
-51
lines changed

.changes/cli-handle-dev-err.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"cli.rs": patch
3+
"cli.js": patch
4+
---
5+
6+
Kill the `beforeDevCommand` and app processes if the dev command returns an error.

examples/api/yarn.lock

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@
2323
svelte-hmr "^0.14.7"
2424

2525
"@tauri-apps/api@../../tooling/api/dist":
26-
version "1.0.0-rc.1"
26+
version "1.0.0-rc.2"
2727
dependencies:
28-
type-fest "2.12.0"
28+
type-fest "2.12.1"
2929

3030
debug@^4.3.2:
3131
version "4.3.3"
@@ -262,10 +262,10 @@ svelte@3.35.0:
262262
resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.35.0.tgz#e0d0ba60c4852181c2b4fd851194be6fda493e65"
263263
integrity sha512-gknlZkR2sXheu/X+B7dDImwANVvK1R0QGQLd8CNIfxxGPeXBmePnxfzb6fWwTQRsYQG7lYkZXvpXJvxvpsoB7g==
264264

265-
type-fest@2.12.0:
266-
version "2.12.0"
267-
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.12.0.tgz#ce342f58cab9114912f54b493d60ab39c3fc82b6"
268-
integrity sha512-Qe5GRT+n/4GoqCNGGVp5Snapg1Omq3V7irBJB3EaKsp7HWDo5Gv2d/67gfNyV+d5EXD+x/RF5l1h4yJ7qNkcGA==
265+
type-fest@2.12.1:
266+
version "2.12.1"
267+
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.12.1.tgz#d2be8f50bf5f8f0a5fd916d29bf3e98c17e960be"
268+
integrity sha512-AiknQSEqKVGDDjtZqeKrUoTlcj7FKhupmnVUgz6KoOKtvMwRGE6hUNJ/nVear+h7fnUPO1q/htSkYKb1pyntkQ==
269269

270270
vite@^2.6.4:
271271
version "2.6.14"

tooling/cli/src/dev.rs

Lines changed: 80 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use crate::{
66
helpers::{
77
app_paths::{app_dir, tauri_dir},
88
command_env,
9-
config::{get as get_config, reload as reload_config, AppUrl, WindowUrl},
10-
manifest::{get_workspace_members, rewrite_manifest, Manifest},
9+
config::{get as get_config, reload as reload_config, AppUrl, ConfigHandle, WindowUrl},
10+
manifest::{rewrite_manifest, Manifest},
1111
Logger,
1212
},
1313
CommandExt, Result,
@@ -22,10 +22,12 @@ use shared_child::SharedChild;
2222
use std::{
2323
env::set_current_dir,
2424
ffi::OsStr,
25+
fs::FileType,
26+
path::{Path, PathBuf},
2527
process::{exit, Command},
2628
sync::{
2729
atomic::{AtomicBool, Ordering},
28-
mpsc::{channel, Receiver},
30+
mpsc::{channel, Receiver, Sender},
2931
Arc, Mutex,
3032
},
3133
time::Duration,
@@ -63,6 +65,14 @@ pub struct Options {
6365
}
6466

6567
pub fn command(options: Options) -> Result<()> {
68+
let r = command_internal(options);
69+
if r.is_err() {
70+
kill_before_dev_process();
71+
}
72+
r
73+
}
74+
75+
fn command_internal(options: Options) -> Result<()> {
6676
let logger = Logger::new("tauri:dev");
6777

6878
let tauri_path = tauri_dir();
@@ -151,7 +161,7 @@ pub fn command(options: Options) -> Result<()> {
151161
.or(runner_from_config)
152162
.unwrap_or_else(|| "cargo".to_string());
153163

154-
let mut manifest = {
164+
let manifest = {
155165
let (tx, rx) = channel();
156166
let mut watcher = watcher(tx, Duration::from_secs(1)).unwrap();
157167
watcher.watch(tauri_path.join("Cargo.toml"), RecursiveMode::Recursive)?;
@@ -239,26 +249,78 @@ pub fn command(options: Options) -> Result<()> {
239249
}
240250
}
241251

242-
let mut process = start_app(
252+
let process = start_app(
243253
&options,
244254
&runner,
245255
&manifest,
246256
&cargo_features,
247257
child_wait_rx.clone(),
248258
)?;
259+
let shared_process = Arc::new(Mutex::new(process));
260+
if let Err(e) = watch(
261+
shared_process.clone(),
262+
child_wait_tx,
263+
child_wait_rx,
264+
tauri_path,
265+
merge_config,
266+
config,
267+
options,
268+
runner,
269+
manifest,
270+
cargo_features,
271+
) {
272+
shared_process
273+
.lock()
274+
.unwrap()
275+
.kill()
276+
.with_context(|| "failed to kill app process")?;
277+
Err(e)
278+
} else {
279+
Ok(())
280+
}
281+
}
282+
283+
fn lookup<F: FnMut(&OsStr, FileType, PathBuf)>(dir: &Path, mut f: F) {
284+
let mut builder = ignore::WalkBuilder::new(dir);
285+
builder.require_git(false).ignore(false).max_depth(Some(1));
249286

287+
for entry in builder.build().flatten() {
288+
f(
289+
entry.file_name(),
290+
entry.file_type().unwrap(),
291+
dir.join(entry.path()),
292+
);
293+
}
294+
}
295+
296+
#[allow(clippy::too_many_arguments)]
297+
fn watch(
298+
process: Arc<Mutex<Arc<SharedChild>>>,
299+
child_wait_tx: Sender<()>,
300+
child_wait_rx: Arc<Mutex<Receiver<()>>>,
301+
tauri_path: PathBuf,
302+
merge_config: Option<String>,
303+
config: ConfigHandle,
304+
options: Options,
305+
runner: String,
306+
mut manifest: Manifest,
307+
cargo_features: Vec<String>,
308+
) -> Result<()> {
250309
let (tx, rx) = channel();
251310

252311
let mut watcher = watcher(tx, Duration::from_secs(1)).unwrap();
253-
watcher.watch(tauri_path.join("src"), RecursiveMode::Recursive)?;
254-
watcher.watch(tauri_path.join("Cargo.toml"), RecursiveMode::Recursive)?;
255-
watcher.watch(tauri_path.join("tauri.conf.json"), RecursiveMode::Recursive)?;
256-
257-
for member in get_workspace_members()? {
258-
let workspace_path = tauri_path.join(member);
259-
watcher.watch(workspace_path.join("src"), RecursiveMode::Recursive)?;
260-
watcher.watch(workspace_path.join("Cargo.toml"), RecursiveMode::Recursive)?;
261-
}
312+
lookup(&tauri_path, |file_name, file_type, path| {
313+
if file_name != "target" && file_name != "Cargo.lock" {
314+
let _ = watcher.watch(
315+
path,
316+
if file_type.is_dir() {
317+
RecursiveMode::Recursive
318+
} else {
319+
RecursiveMode::NonRecursive
320+
},
321+
);
322+
}
323+
});
262324

263325
loop {
264326
if let Ok(event) = rx.recv() {
@@ -279,16 +341,15 @@ pub fn command(options: Options) -> Result<()> {
279341
// which will trigger the watcher again
280342
// So the app should only be started when a file other than tauri.conf.json is changed
281343
let _ = child_wait_tx.send(());
282-
process
283-
.kill()
284-
.with_context(|| "failed to kill app process")?;
344+
let mut p = process.lock().unwrap();
345+
p.kill().with_context(|| "failed to kill app process")?;
285346
// wait for the process to exit
286347
loop {
287-
if let Ok(Some(_)) = process.try_wait() {
348+
if let Ok(Some(_)) = p.try_wait() {
288349
break;
289350
}
290351
}
291-
process = start_app(
352+
*p = start_app(
292353
&options,
293354
&runner,
294355
&manifest,

tooling/cli/src/helpers/manifest.rs

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -234,29 +234,3 @@ pub fn rewrite_manifest(config: ConfigHandle) -> crate::Result<Manifest> {
234234
Err(e) => Err(e),
235235
}
236236
}
237-
238-
pub fn get_workspace_members() -> crate::Result<Vec<String>> {
239-
let mut manifest = read_manifest(&tauri_dir().join("Cargo.toml"))?;
240-
let workspace = manifest
241-
.as_table_mut()
242-
.entry("workspace")
243-
.or_insert(Item::None)
244-
.as_table_mut();
245-
246-
match workspace {
247-
Some(workspace) => {
248-
let members = workspace
249-
.entry("members")
250-
.or_insert(Item::None)
251-
.as_array()
252-
.expect("workspace members aren't an array");
253-
Ok(
254-
members
255-
.iter()
256-
.map(|v| v.as_str().unwrap().to_string())
257-
.collect(),
258-
)
259-
}
260-
None => Ok(vec![]),
261-
}
262-
}

0 commit comments

Comments
 (0)