From 0d5e8b35c6c1bf7cf7c9f4f2e8301dbf4d3d6d3e Mon Sep 17 00:00:00 2001
From: Ilya Grigoriev <ilyagr@users.noreply.github.com>
Date: Sat, 30 Mar 2024 22:47:07 -0700
Subject: [PATCH] New `jj debug watchman status` command

This command checks not only whether Watchman works, but also whether
it's enabled in the config. Also, the output is easier to understand
than that of the other `jj debug watchman` commands.

It would be nice if `jj debug watchman` called `jj debug watchman
status`, but it's not trivial in `clap` to have a default subcommand.
---
 CHANGELOG.md              |  3 +++
 cli/src/commands/debug.rs | 27 +++++++++++++++++++++++++++
 docs/config.md            |  3 ++-
 lib/src/fsmonitor.rs      |  2 +-
 4 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a703a6dfe2..61780beddc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -40,6 +40,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
   evaluates to true if the operation was a snapshot created by a non-mutating
   command (e.g. `jj log`).
 
+* You can check whether Watchman fsmonitor is enabled or installed with the new
+  `jj debug watchman status` command.
+
 ### Fixed bugs
 
 * Revsets now support `\`-escapes in string literal.
diff --git a/cli/src/commands/debug.rs b/cli/src/commands/debug.rs
index 1b22cc96de..624e5e772d 100644
--- a/cli/src/commands/debug.rs
+++ b/cli/src/commands/debug.rs
@@ -118,6 +118,8 @@ pub struct DebugTreeArgs {
 
 #[derive(Subcommand, Clone, Debug)]
 pub enum DebugWatchmanSubcommand {
+    /// Check whether `watchman` is enabled and whether it's correctly installed
+    Status,
     QueryClock,
     QueryChangedFiles,
     ResetClock,
@@ -367,6 +369,31 @@ fn cmd_debug_watchman(
     let mut workspace_command = command.workspace_helper(ui)?;
     let repo = workspace_command.repo().clone();
     match subcommand {
+        DebugWatchmanSubcommand::Status => {
+            // TODO(ilyagr): It would be nice to add colors here
+            match command.settings().fsmonitor_kind()? {
+                jj_lib::fsmonitor::FsmonitorKind::Watchman => {
+                    writeln!(ui.stdout(), "Watchman is enabled via `core.fsmonitor`.")?
+                }
+                jj_lib::fsmonitor::FsmonitorKind::None => writeln!(
+                    ui.stdout(),
+                    "Watchman is disabled. Set `core.fsmonitor=\"watchman\"` to \
+                     enable.\nAttempting to contact the `watchman` CLI regardless..."
+                )?,
+                other_fsmonitor => {
+                    return Err(user_error(format!(
+                        "This command does not support the currently enabled filesystem monitor: \
+                         {other_fsmonitor:?}."
+                    )))
+                }
+            };
+            let wc = check_local_disk_wc(workspace_command.working_copy().as_any())?;
+            let _ = wc.query_watchman()?;
+            writeln!(
+                ui.stdout(),
+                "The watchman server seems to be installed and working correctly."
+            )?;
+        }
         DebugWatchmanSubcommand::QueryClock => {
             let wc = check_local_disk_wc(workspace_command.working_copy().as_any())?;
             let (clock, _changed_files) = wc.query_watchman()?;
diff --git a/docs/config.md b/docs/config.md
index 633da13f59..7b9597b499 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -727,7 +727,8 @@ To configure the Watchman filesystem monitor, set
 `core.fsmonitor = "watchman"`. Ensure that you have [installed the Watchman
 executable on your system](https://facebook.github.io/watchman/docs/install).
 
-Debugging commands are available under `jj debug watchman`.
+You can check whether Watchman is enabled and whether it is installed correctly
+using `jj debug watchman status`.
 
 ## Ways to specify `jj` config: details
 
diff --git a/lib/src/fsmonitor.rs b/lib/src/fsmonitor.rs
index 4385345990..21351340ef 100644
--- a/lib/src/fsmonitor.rs
+++ b/lib/src/fsmonitor.rs
@@ -24,7 +24,7 @@ use std::path::PathBuf;
 use std::str::FromStr;
 
 /// The recognized kinds of filesystem monitors.
-#[derive(Eq, PartialEq)]
+#[derive(Eq, PartialEq, Clone, Debug)]
 pub enum FsmonitorKind {
     /// The Watchman filesystem monitor (<https://facebook.github.io/watchman/>).
     Watchman,