bigbrother 0.4.0

Git-aware file tracker (list & watch) for async Rust apps
Documentation
# Big Borther

`bigbrother` crate is an async Git-aware file tracker for Rust that watches a working directory and reports files that are currently trackable by ignore rules.

- High-level API.
- Git-aware file watching.
- `.gitignore` and `.ignore` support across hierarchy, including parent directories.
- Global Git ignore support (`core.excludesFile`).
- Per-file transitions when ignore rules change.
- Async API via [`tokio`]https://crates.io/crates/tokio channel.
-
- Optional source-only mode (`source-filter` feature) that only tracks source files based on [`tokei`]https://crates.io/crates/tokei language definitions.

It combines:

- [`notify`]https://crates.io/crates/notify for filesystem watching.
- [`ignore`]https://crates.io/crates/ignore for fast parallel file discovery.
- [`ignore-files`]https://crates.io/crates/ignore-files for discovering and compiling ignore files (`.gitignore`, `.ignore`, global git excludes).
- Optional [`tokei`]https://crates.io/crates/tokei support for source-only filtering


## Installation

To add `bigbrother` to your project, install it with `cargo add`:

```bash
cargo add bigbrother
```

To enable source-only filtering (`only_source` option), use the source-filter feature:

```bash
cargo add bigbrother --features source-filter
```

## How it works

Here's a high-level overview of how Big Brother works:

- Resolves cwd and (if present) containing git repo root.
- If cwd is inside a repo, watches the repo root to catch parent ignore changes.
- Builds ignore state from local + global ignore sources.
- Performs an initial parallel scan, then emits InitialTracked events.
- Processes live filesystem events (`Created`, `Changed`, `Removed`, `Moved`) for tracked files.
- On ignore-file updates, rescans and diffs tracked state to emit `Tracked`/`Untracked`.

## Usage

Basic usage:

```rs
use bigbrother::{
    FileTracker, TrackEvent, TrackEventError, TrackEventFile, TrackEventFileMove, WatchOptions,
};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let (tracker, mut rx) = FileTracker::start(".").await?;

    while let Some(event) = rx.recv().await {
        match event {
            TrackEvent::InitialTracked(TrackEventFile { path }) => println!("initial: {}", path.display()),
            TrackEvent::Tracked(TrackEventFile { path }) => println!("tracked: {}", path.display()),
            TrackEvent::Untracked(TrackEventFile { path }) => println!("untracked: {}", path.display()),
            TrackEvent::Created(TrackEventFile { path }) => println!("created: {}", path.display()),
            TrackEvent::Changed(TrackEventFile { path }) => println!("changed: {}", path.display()),
            TrackEvent::Removed(TrackEventFile { path }) => println!("removed: {}", path.display()),
            TrackEvent::Moved(TrackEventFileMove { from, to }) => {
                println!("moved: {} -> {}", from.display(), to.display())
            }
            TrackEvent::Error(TrackEventError { message }) => eprintln!("error: {message}"),
        }
    }

    tracker.stop().await?;

    Ok(())
}
```

If you only care about source files, enable the `source-filter` feature and set the `only_source` option:

```rs
use bigbrother::{FileTracker, WatchOptions};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let options = WatchOptions {
        only_source: true,
        ..WatchOptions::default()
    };
    let (tracker, mut rx) = FileTracker::start_with_options(".", options).await?;

    // ...

    Ok(())
}
```


## Changelog

See [the changelog](./CHANGELOG.md).

## License

[MIT © Sasha Koss](https://koss.nocorp.me/mit/)