From a6a30db4ce4ee1423a1e0e413dc2c6507b1d5ed2 Mon Sep 17 00:00:00 2001 From: parsonsmatt Date: Wed, 13 Dec 2023 08:56:23 -0700 Subject: [PATCH 1/5] CLI flag for disabling interrupts --- src/cli.rs | 6 ++++++ src/ghci/manager.rs | 29 ++++++++++++++++------------- src/ghci/mod.rs | 3 +++ 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/cli.rs b/src/cli.rs index 643fa598..139447df 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -51,6 +51,11 @@ pub struct Opts { /// Options to modify logging and error-handling behavior. #[command(flatten)] pub logging: LoggingOpts, + + /// By default, ghciwatch will interrupt reloads if a file changes. If you want ghciwatch to + /// avoid interrupting reloads, set this flag. + #[arg(long = "no-interrupt-reloads")] + pub no_interrupt_reloads: bool, } /// Options for watching files. @@ -105,6 +110,7 @@ pub struct WatchOpts { #[allow(rustdoc::bare_urls)] #[arg(long = "restart-glob")] pub restart_globs: Vec, + } impl WatchOpts { diff --git a/src/ghci/manager.rs b/src/ghci/manager.rs index c6aa5fc1..86689138 100644 --- a/src/ghci/manager.rs +++ b/src/ghci/manager.rs @@ -55,6 +55,7 @@ pub async fn run_ghci( // This function is pretty tricky! We need to handle shutdowns at each stage, and the process // is a little different each time, so the `select!`s can't be consolidated. + let no_interrupt_reloads = opts.no_interrupt_reloads; let mut ghci = Ghci::new(handle.clone(), opts) .await .wrap_err("Failed to start `ghci`")?; @@ -111,19 +112,21 @@ pub async fn run_ghci( } Some(new_event) = receiver.recv() => { tracing::debug!(?new_event, "Received ghci event from watcher while reloading"); - if should_interrupt(reload_receiver).await { - // Merge the events together so we don't lose progress. - // Then, the next iteration of the loop will pick up the `maybe_event` value - // and respond immediately. - event.merge(new_event); - maybe_event = Some(event); - - // Cancel the in-progress reload. This releases the `ghci` lock to prevent a deadlock. - task.abort(); - - // Send a SIGINT to interrupt the reload. - // NB: This may take a couple seconds to register. - ghci.lock().await.send_sigint().await?; + if !no_interrupt_reloads { + if should_interrupt(reload_receiver).await { + // Merge the events together so we don't lose progress. + // Then, the next iteration of the loop will pick up the `maybe_event` value + // and respond immediately. + event.merge(new_event); + maybe_event = Some(event); + + // Cancel the in-progress reload. This releases the `ghci` lock to prevent a deadlock. + task.abort(); + + // Send a SIGINT to interrupt the reload. + // NB: This may take a couple seconds to register. + ghci.lock().await.send_sigint().await?; + } } } ret = &mut task => { diff --git a/src/ghci/mod.rs b/src/ghci/mod.rs index 431f662e..9e37f274 100644 --- a/src/ghci/mod.rs +++ b/src/ghci/mod.rs @@ -96,6 +96,8 @@ pub struct GhciOpts { pub restart_globs: GlobMatcher, /// Reload the `ghci` session when paths matching these globs are changed. pub reload_globs: GlobMatcher, + /// Determines whether we should interrupt a reload in progress or not. + pub no_interrupt_reloads: bool, } impl GhciOpts { @@ -118,6 +120,7 @@ impl GhciOpts { hooks: opts.hooks.clone(), restart_globs: opts.watch.restart_globs()?, reload_globs: opts.watch.reload_globs()?, + no_interrupt_reloads: opts.no_interrupt_reloads, }) } } From c32a72e046e69d10073766d1757bc5ebdc112b85 Mon Sep 17 00:00:00 2001 From: parsonsmatt Date: Wed, 13 Dec 2023 09:00:02 -0700 Subject: [PATCH 2/5] resolve --- src/ghci/mod.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/ghci/mod.rs b/src/ghci/mod.rs index 9398314a..79901c0f 100644 --- a/src/ghci/mod.rs +++ b/src/ghci/mod.rs @@ -102,15 +102,12 @@ pub struct GhciOpts { pub restart_globs: GlobMatcher, /// Reload the `ghci` session when paths matching these globs are changed. pub reload_globs: GlobMatcher, -<<<<<<< HEAD /// Determines whether we should interrupt a reload in progress or not. pub no_interrupt_reloads: bool, -======= /// Where to write what `ghci` emits to `stdout`. Inherits parent's `stdout` by default. pub stdout_writer: GhciWriter, /// Where to write what `ghci` emits to `stderr`. Inherits parent's `stderr` by default. pub stderr_writer: GhciWriter, ->>>>>>> d2725f3ca1aa02230f2d118a7d164197ca7e9ffd } impl GhciOpts { @@ -133,12 +130,9 @@ impl GhciOpts { hooks: opts.hooks.clone(), restart_globs: opts.watch.restart_globs()?, reload_globs: opts.watch.reload_globs()?, -<<<<<<< HEAD no_interrupt_reloads: opts.no_interrupt_reloads, -======= stdout_writer: GhciWriter::stdout(), stderr_writer: GhciWriter::stderr(), ->>>>>>> d2725f3ca1aa02230f2d118a7d164197ca7e9ffd }) } } From 42bad4c822d72eccf268f2f1cc0ed1b9977f6d30 Mon Sep 17 00:00:00 2001 From: parsonsmatt Date: Wed, 13 Dec 2023 09:00:20 -0700 Subject: [PATCH 3/5] remove space --- src/cli.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cli.rs b/src/cli.rs index b9319d11..040584be 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -108,7 +108,6 @@ pub struct WatchOpts { #[allow(rustdoc::bare_urls)] #[arg(long = "restart-glob")] pub restart_globs: Vec, - } impl WatchOpts { From 15c20b308a399d0a29586023a22f164dd1a5895a Mon Sep 17 00:00:00 2001 From: parsonsmatt Date: Wed, 13 Dec 2023 09:18:09 -0700 Subject: [PATCH 4/5] ok clippy --- src/ghci/manager.rs | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/ghci/manager.rs b/src/ghci/manager.rs index 52d39e68..48ed72cd 100644 --- a/src/ghci/manager.rs +++ b/src/ghci/manager.rs @@ -114,21 +114,19 @@ pub async fn run_ghci( } Some(new_event) = receiver.recv() => { tracing::debug!(?new_event, "Received ghci event from watcher while reloading"); - if !no_interrupt_reloads { - if should_interrupt(reload_receiver).await { - // Merge the events together so we don't lose progress. - // Then, the next iteration of the loop will pick up the `maybe_event` value - // and respond immediately. - event.merge(new_event); - maybe_event = Some(event); - - // Cancel the in-progress reload. This releases the `ghci` lock to prevent a deadlock. - task.abort(); - - // Send a SIGINT to interrupt the reload. - // NB: This may take a couple seconds to register. - ghci.lock().await.send_sigint().await?; - } + if !no_interrupt_reloads && should_interrupt(reload_receiver).await { + // Merge the events together so we don't lose progress. + // Then, the next iteration of the loop will pick up the `maybe_event` value + // and respond immediately. + event.merge(new_event); + maybe_event = Some(event); + + // Cancel the in-progress reload. This releases the `ghci` lock to prevent a deadlock. + task.abort(); + + // Send a SIGINT to interrupt the reload. + // NB: This may take a couple seconds to register. + ghci.lock().await.send_sigint().await?; } } ret = &mut task => { From 1507ad37ba181a5b814a65949f181a8360d72a94 Mon Sep 17 00:00:00 2001 From: Rebecca Turner Date: Wed, 13 Dec 2023 10:50:16 -0800 Subject: [PATCH 5/5] CLI documentation --- src/cli.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/cli.rs b/src/cli.rs index 040584be..82fa8d31 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -50,9 +50,10 @@ pub struct Opts { #[command(flatten)] pub logging: LoggingOpts, - /// By default, ghciwatch will interrupt reloads if a file changes. If you want ghciwatch to - /// avoid interrupting reloads, set this flag. - #[arg(long = "no-interrupt-reloads")] + /// Don't interrupt reloads when files change. + /// + /// Depending on your workflow, `ghciwatch` may feel more responsive with this set. + #[arg(long)] pub no_interrupt_reloads: bool, }