Skip to content

Commit

Permalink
feat(Turborepo): file hash watching (#7855)
Browse files Browse the repository at this point in the history
### Description

 - Implements basic file hash watching. Does not yet handle `inputs`, although some of the infrastructure is there for them
 - Updates some `Display` and `Debug` implementations on various glob wrappers to be less noisy

### Testing Instructions

The hash watching process has a couple of tests for scenarios like files changing and switching git branches, which triggers a change in package layout.

Closes TURBO-2721
  • Loading branch information
Greg Soltis authored Apr 16, 2024
1 parent fb83e8f commit 10eab3d
Show file tree
Hide file tree
Showing 10 changed files with 1,052 additions and 10 deletions.
29 changes: 29 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions crates/turborepo-filewatch/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@ workspace = true

[dependencies]
futures = { version = "0.3.26" }
itertools = { workspace = true }
nibble_vec = "0.1.0"
notify = { workspace = true }
radix_trie = "0.2.1"
thiserror = "1.0.38"
tokio = { workspace = true, features = ["full", "time"] }
tracing = "0.1.37"
tracing-test = "0.2.4"
turbopath = { workspace = true }
turborepo-repository = { version = "0.1.0", path = "../turborepo-repository" }
turborepo-scm = { workspace = true }
walkdir = "2.3.3"
wax = { workspace = true }

Expand All @@ -32,6 +36,7 @@ version = "1.0.4"
version = "0.2.4"

[dev-dependencies]
git2 = { version = "0.16.1", default-features = false }
tempfile = { workspace = true }
tokio-scoped = "0.2.0"

Expand Down
4 changes: 4 additions & 0 deletions crates/turborepo-filewatch/src/cookies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,10 @@ impl<T, U: CookieReady + Clone> CookiedOptionalWatch<T, U> {
self.value.wait_for(|f| f.is_some()).await?;
Ok(SomeRef(self.value.borrow()))
}

pub(crate) fn watch(&self) -> watch::Receiver<Option<T>> {

Check warning on line 495 in crates/turborepo-filewatch/src/cookies.rs

View workflow job for this annotation

GitHub Actions / JS Native Package Tests (ubuntu, self-hosted, linux, x64, metal)

method `watch` is never used

Check warning on line 495 in crates/turborepo-filewatch/src/cookies.rs

View workflow job for this annotation

GitHub Actions / Turborepo rust check

method `watch` is never used

Check warning on line 495 in crates/turborepo-filewatch/src/cookies.rs

View workflow job for this annotation

GitHub Actions / Build Turborepo (ubuntu, self-hosted, linux, x64, metal)

method `watch` is never used

Check warning on line 495 in crates/turborepo-filewatch/src/cookies.rs

View workflow job for this annotation

GitHub Actions / JS Native Package Tests (macos, macos-latest)

method `watch` is never used

Check warning on line 495 in crates/turborepo-filewatch/src/cookies.rs

View workflow job for this annotation

GitHub Actions / Turborepo rust clippy

method `watch` is never used

Check warning on line 495 in crates/turborepo-filewatch/src/cookies.rs

View workflow job for this annotation

GitHub Actions / Build Turborepo (macos, macos-latest)

method `watch` is never used

Check warning on line 495 in crates/turborepo-filewatch/src/cookies.rs

View workflow job for this annotation

GitHub Actions / Turborepo Rust testing on ubuntu

method `watch` is never used

Check warning on line 495 in crates/turborepo-filewatch/src/cookies.rs

View workflow job for this annotation

GitHub Actions / Build Turborepo (windows, windows-latest)

method `watch` is never used

Check warning on line 495 in crates/turborepo-filewatch/src/cookies.rs

View workflow job for this annotation

GitHub Actions / Benchmark TTFT (ubuntu, ubuntu-latest)

method `watch` is never used

Check warning on line 495 in crates/turborepo-filewatch/src/cookies.rs

View workflow job for this annotation

GitHub Actions / Turborepo Integration (ubuntu-latest)

method `watch` is never used

Check warning on line 495 in crates/turborepo-filewatch/src/cookies.rs

View workflow job for this annotation

GitHub Actions / Turborepo Integration (macos-latest)

method `watch` is never used

Check warning on line 495 in crates/turborepo-filewatch/src/cookies.rs

View workflow job for this annotation

GitHub Actions / Turborepo Integration (windows-latest)

method `watch` is never used

Check warning on line 495 in crates/turborepo-filewatch/src/cookies.rs

View workflow job for this annotation

GitHub Actions / Benchmark TTFT (macos, macos-latest)

method `watch` is never used

Check warning on line 495 in crates/turborepo-filewatch/src/cookies.rs

View workflow job for this annotation

GitHub Actions / Turborepo Rust testing on macos

method `watch` is never used

Check warning on line 495 in crates/turborepo-filewatch/src/cookies.rs

View workflow job for this annotation

GitHub Actions / Benchmark TTFT (windows, windows-latest)

method `watch` is never used

Check warning on line 495 in crates/turborepo-filewatch/src/cookies.rs

View workflow job for this annotation

GitHub Actions / Benchmark turbo run

method `watch` is never used

Check warning on line 495 in crates/turborepo-filewatch/src/cookies.rs

View workflow job for this annotation

GitHub Actions / Turborepo Rust testing on windows

method `watch` is never used

Check warning on line 495 in crates/turborepo-filewatch/src/cookies.rs

View workflow job for this annotation

GitHub Actions / Benchmark on generic

method `watch` is never used

Check warning on line 495 in crates/turborepo-filewatch/src/cookies.rs

View workflow job for this annotation

GitHub Actions / Benchmark on generic

method `watch` is never used
self.value.clone()
}
}

pub struct CookieRegister(watch::Sender<usize>, AbsoluteSystemPathBuf);
Expand Down
52 changes: 48 additions & 4 deletions crates/turborepo-filewatch/src/globwatcher.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::{
collections::{HashMap, HashSet},
collections::{BTreeSet, HashMap, HashSet},
fmt::Display,
future::IntoFuture,
str::FromStr,
Expand All @@ -20,10 +20,19 @@ use crate::{

type Hash = String;

#[derive(Clone)]
pub struct GlobSet {
include: HashMap<String, wax::Glob<'static>>,
exclude: Any<'static>,
exclude_raw: Vec<String>,
exclude_raw: BTreeSet<String>,
}

impl GlobSet {
pub fn as_inputs(&self) -> Vec<String> {
let mut inputs: Vec<String> = self.include.keys().cloned().collect();
inputs.extend(self.exclude_raw.iter().cloned());
inputs
}
}

impl std::fmt::Debug for GlobSet {
Expand All @@ -35,6 +44,22 @@ impl std::fmt::Debug for GlobSet {
}
}

impl PartialEq for GlobSet {
fn eq(&self, other: &Self) -> bool {
self.include.keys().collect::<HashSet<_>>() == other.include.keys().collect::<HashSet<_>>()
&& self.exclude_raw == other.exclude_raw
}
}

impl Eq for GlobSet {}

impl std::hash::Hash for GlobSet {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.include.keys().collect::<BTreeSet<_>>().hash(state);
self.exclude_raw.hash(state);
}
}

#[derive(Debug, Error)]
pub struct GlobError {
// Boxed to minimize error size
Expand Down Expand Up @@ -63,7 +88,8 @@ impl GlobSet {
raw_excludes: Vec<String>,
) -> Result<Self, GlobError> {
let include = raw_includes
.into_iter()
.iter()
.cloned()
.map(|raw_glob| {
let glob = compile_glob(&raw_glob)?;
Ok((raw_glob, glob))
Expand All @@ -86,9 +112,27 @@ impl GlobSet {
Ok(Self {
include,
exclude,
exclude_raw: raw_excludes,
exclude_raw: BTreeSet::from_iter(raw_excludes),
})
}

// delegates to from_raw, but filters the globs into inclusions and exclusions
// first
pub fn from_raw_unfiltered(raw: Vec<String>) -> Result<Self, GlobError> {
let (includes, excludes): (Vec<_>, Vec<_>) = {
let mut includes = vec![];
let mut excludes = vec![];
for pattern in raw {
if let Some(exclude) = pattern.strip_prefix('!') {
excludes.push(exclude.to_string());
} else {
includes.push(pattern);
}
}
(includes, excludes)
};
Self::from_raw(includes, excludes)
}
}

#[derive(Debug, Error)]
Expand Down
Loading

0 comments on commit 10eab3d

Please sign in to comment.