Skip to content

Commit e8cdc22

Browse files
authored
Close remaining rewatch build.lock gaps (#8410)
* Close remaining rewatch build.lock gaps * CHANGELOG
1 parent 992c1a5 commit e8cdc22

3 files changed

Lines changed: 58 additions & 50 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
- Fix duplicated comments in `for`..`of` formatter. https://github.com/rescript-lang/rescript/pull/8395
2727
- Fix issue where warning 56 would blow up with `dict{}` patterns. https://github.com/rescript-lang/rescript/pull/8403
2828
- Acquire rewatch build lock before initialization. https://github.com/rescript-lang/rescript/pull/8409
29+
- Close remaining rewatch build.lock gaps. https://github.com/rescript-lang/rescript/pull/8410
2930
- Rewatch: treat transitive workspace dependencies as local packages in monorepo roots. https://github.com/rescript-lang/rescript/pull/8411
3031

3132
#### :memo: Documentation

rewatch/src/build.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ impl fmt::Display for IncrementalBuildError {
281281
}
282282
}
283283

284-
fn with_build_lock<T>(path: &Path, f: impl FnOnce() -> T) -> T {
284+
pub fn with_build_lock<T>(path: &Path, f: impl FnOnce() -> T) -> T {
285285
let build_folder = path.to_string_lossy().to_string();
286286
let _lock = get_lock_or_exit(LockKind::Build, &build_folder);
287287
let result = f();
@@ -316,7 +316,7 @@ pub fn incremental_build(
316316
// `build` needs to lock before initialization because initialization mutates previous
317317
// build artifacts. Keep the compile body separate so it can run under that wider lock.
318318
#[instrument(name = "build.incremental.unlocked", skip_all, fields(module_count = build_state.modules.len()))]
319-
fn incremental_build_without_lock(
319+
pub fn incremental_build_without_lock(
320320
build_state: &mut BuildCommandState,
321321
default_timing: Option<Duration>,
322322
initial_build: bool,

rewatch/src/watcher.rs

Lines changed: 55 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ async fn async_watch(
256256
if show_progress {
257257
println!("\nExiting...");
258258
}
259-
clean::cleanup_after_build(&build_state);
259+
build::with_build_lock(path, || clean::cleanup_after_build(&build_state));
260260
break Ok(());
261261
}
262262
let mut events: Vec<Event> = vec![];
@@ -281,7 +281,7 @@ async fn async_watch(
281281
if show_progress {
282282
println!("\nExiting... (lockfile removed)");
283283
}
284-
clean::cleanup_after_build(&build_state);
284+
build::with_build_lock(path, || clean::cleanup_after_build(&build_state));
285285
return Ok(());
286286
}
287287

@@ -468,38 +468,44 @@ async fn async_watch(
468468
}
469469

470470
let timing_total = Instant::now();
471-
let mut next_build_state = build::initialize_build(
472-
None,
473-
filter,
474-
show_progress,
475-
path,
476-
plain_output,
477-
build_state.get_warn_error_override(),
478-
prod,
479-
features.clone(),
480-
)
481-
.expect("Could not initialize build");
482-
483-
// Full rebuilds can be triggered by editor atomic saves that surface as rename events.
484-
// Preserve warning state for unchanged modules so their warnings are re-emitted after the
485-
// fresh build state replaces the previous one.
486-
carry_forward_compile_warnings(&build_state, &mut next_build_state);
487-
build_state = next_build_state;
488-
489-
// Re-register watches based on the new build state
490-
unregister_watches(watcher, &current_watch_paths);
491-
current_watch_paths = compute_watch_paths(&build_state, path);
492-
register_watches(watcher, &current_watch_paths);
493-
494-
let result = build::incremental_build(
495-
&mut build_state,
496-
None,
497-
initial_build,
498-
show_progress,
499-
false,
500-
create_sourcedirs,
501-
plain_output,
502-
);
471+
// Reinitialization runs cleanup for previous build artifacts, so full rebuilds need
472+
// the same build lock boundary as regular `rescript build`.
473+
let result = build::with_build_lock(path, || {
474+
let mut next_build_state = build::initialize_build(
475+
None,
476+
filter,
477+
show_progress,
478+
path,
479+
plain_output,
480+
build_state.get_warn_error_override(),
481+
prod,
482+
features.clone(),
483+
)
484+
.expect("Could not initialize build");
485+
486+
// Full rebuilds can be triggered by editor atomic saves that surface as rename events.
487+
// Preserve warning state for unchanged modules so their warnings are re-emitted after the
488+
// fresh build state replaces the previous one.
489+
carry_forward_compile_warnings(&build_state, &mut next_build_state);
490+
build_state = next_build_state;
491+
492+
// Re-register watches based on the new build state
493+
unregister_watches(watcher, &current_watch_paths);
494+
current_watch_paths = compute_watch_paths(&build_state, path);
495+
register_watches(watcher, &current_watch_paths);
496+
497+
let result = build::incremental_build_without_lock(
498+
&mut build_state,
499+
None,
500+
initial_build,
501+
show_progress,
502+
false,
503+
create_sourcedirs,
504+
plain_output,
505+
);
506+
build::write_build_ninja(&build_state);
507+
result
508+
});
503509
match result {
504510
Ok(result) => {
505511
if let Some(a) = after_build.clone() {
@@ -528,8 +534,6 @@ async fn async_watch(
528534
}
529535
}
530536
}
531-
532-
build::write_build_ninja(&build_state);
533537
needs_compile_type = CompileType::None;
534538
initial_build = false;
535539
}
@@ -565,18 +569,21 @@ pub fn start(
565569

566570
let path = Path::new(folder);
567571

568-
// Do an initial build to discover packages and source folders
569-
let build_state: BuildCommandState = build::initialize_build(
570-
None,
571-
filter,
572-
show_progress,
573-
path,
574-
plain_output,
575-
warn_error.clone(),
576-
prod,
577-
features.clone(),
578-
)
579-
.with_context(|| "Could not initialize build")?;
572+
// Do an initial build to discover packages and source folders. Initialization can clean
573+
// previous build artifacts, so it has to be serialized with other build operations.
574+
let build_state: BuildCommandState = build::with_build_lock(path, || {
575+
build::initialize_build(
576+
None,
577+
filter,
578+
show_progress,
579+
path,
580+
plain_output,
581+
warn_error.clone(),
582+
prod,
583+
features.clone(),
584+
)
585+
.with_context(|| "Could not initialize build")
586+
})?;
580587

581588
// Compute and register targeted watches based on source folders
582589
let current_watch_paths = compute_watch_paths(&build_state, path);

0 commit comments

Comments
 (0)