Skip to content

Commit

Permalink
feat: Add command line option to pick filesystem scan method
Browse files Browse the repository at this point in the history
  • Loading branch information
Dmitry Bogatov committed Mar 22, 2024
1 parent 34ddc73 commit c5f8a2a
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 10 deletions.
20 changes: 10 additions & 10 deletions src/command/format.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::command::FSScan;
use crate::engine::run_treefmt;
use anyhow::anyhow;
use directories::ProjectDirs;
Expand All @@ -18,6 +19,7 @@ pub async fn format_cmd(
fail_on_change: bool,
allow_missing_formatter: bool,
selected_formatters: &Option<Vec<String>>,
fs_scan: &FSScan,
) -> anyhow::Result<()> {
let proj_dirs = match ProjectDirs::from("com", "NumTide", "treefmt") {
Some(x) => x,
Expand Down Expand Up @@ -52,23 +54,21 @@ pub async fn format_cmd(
paths
);

let client = match Connector::new().connect().await {
Err(e) => {
warn!(
"watchman is not available (err = {:?}), falling back on stat(2)",
e
);
None
}
Ok(c) => {
let client = match fs_scan {
FSScan::Stat => None,
FSScan::Watchman => {
// This is important. Subprocess wastes ~20ms.
if !std::env::var("WATCHMAN_SOCK").is_ok() {
warn!(
"Environment variable `WATCHMAN_SOCK' is not set, falling back on subprocess"
);
};
Some(c)
match Connector::new().connect().await {
Err(e) => return Err(anyhow!("watchman is not available (err = {:?})", e)),
Ok(c) => Some(c),
}
}
FSScan::Auto => Connector::new().connect().await.ok(),
};

// Finally run the main formatter logic from the engine.
Expand Down
42 changes: 42 additions & 0 deletions src/command/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,43 @@ use std::{
path::{Path, PathBuf},
};

/// Enumeration specifying filesystem scan method for modified files.
#[derive(Debug, Clone)]
pub enum FSScan {
/// Recursive walking the filesystem using getdents(2) and statx(2) system calls.
///
/// Scales linearly with total count of files in the repository.
Stat,

/// Query list of modified files from external watchman(1) process.
///
/// Watchman uses inotify(2), so this method scales linearly with count of files in
/// the repository that were actually modified.
///
/// It is user responsibility to get watchman(1) process up and running and preferable
/// set "WATCHMAN_SOCK" environment variable. One way to set that environment variable
/// is to put following snippet into ~/.bashrc:
///
/// export WATCHMAN_SOCK=$(watchman get-sockname | jq .sockname -r)
Watchman,

/// Try to use watchman(1), and silently fall back on stat should it fail.
Auto,
}

impl std::str::FromStr for FSScan {
type Err = String;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"stat" => Ok(Self::Stat),
"watchman" => Ok(Self::Watchman),
"auto" => Ok(Self::Auto),
_ => Err(format!("Unknown file-system scan method: {s}")),
}
}
}

/// ✨ format all your language!
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
Expand Down Expand Up @@ -84,6 +121,10 @@ pub struct Cli {
/// Select formatters name to apply. Defaults to all formatters.
#[arg(short, long)]
pub formatters: Option<Vec<String>>,

/// Select filesystem scan method (stat, watchman, auto).
#[arg(long, default_value = "auto")]
pub fs_scan: FSScan,
}

fn current_dir() -> anyhow::Result<PathBuf> {
Expand Down Expand Up @@ -173,6 +214,7 @@ pub fn run_cli(cli: &Cli) -> anyhow::Result<()> {
cli.fail_on_change,
cli.allow_missing_formatter,
&cli.formatters,
&cli.fs_scan,
)?
}
}
Expand Down

0 comments on commit c5f8a2a

Please sign in to comment.