Skip to content

Commit 344262c

Browse files
pmaxhoganclaude
andauthored
feat(core): filesystem timestamp-granularity probe with ctime fallback and per-directory gitignore cascade (#141)
Implements DESIGN s5.2 step 2 end-to-end plus the true per-directory gitignore cascade (both prior `TODO(M3)`s in the scanner/exclude modules). ## Timestamp-granularity probe + ctime fallback - On the first scan of a source, a write-stat probe measures the filesystem's effective mtime granularity (bounded by a ~2.2s budget so even 2s-resolution FAT32 resolves in one probe). The result is persisted per-source (migration `0009`); later scans reuse it. A probe I/O failure degrades to "fine" for that cycle only and re-probes next scan. - Change detection stays `(size, mtime_ns)` on fine filesystems (zero extra cost). On a coarse FS (granularity > 1s), a stat-matched file is re-hashed when its ctime/inode-birth post-dates the last scan boundary or its mtime falls within one granularity window of it - catching within-quantum in-place edits that a pure mtime compare misses. - Decision logic is pure (`granularity_is_coarse`, `coarse_fs_needs_rehash`) and unit-tested across the rule branches. ## Per-directory gitignore cascade - Replaces the flattened single-matcher approximation with directory-scoped cascading scopes: nested `.gitignore`/`.ignore` files apply at their own depth and deeper files override shallower ones, preserving negation/re-include semantics. - The repo-level `.git/info/exclude` and global-gitignore tiers are anchored at the source root per git semantics (second commit fixes the tier being scoped to `.git/info/`, which made its rules match nothing). Verified: 310 driven-core lib tests green, fmt clean, clippy `-D warnings` clean workspace-wide, `cargo check --workspace` clean, `.sqlx` regenerated for the migration. Refs #34 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01QZQVP2tUuTLh8oL31D8heC --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent 95fbd9a commit 344262c

34 files changed

Lines changed: 1165 additions & 181 deletions

.sqlx/query-68f85a137d75f3bb06d7c864a2b05aa0c6225d41c931595997629946b1d51d28.json

Lines changed: 0 additions & 12 deletions
This file was deleted.

.sqlx/query-86a9b9886667d72dfe7576dc54652d01d50da00987fdca31f12cdd37c79efcd8.json

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.sqlx/query-b38108b7bb9152533f8f85dcdfc45ec4d150f324ce9a22486a949a0fc062289a.json

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.sqlx/query-7ab8e9edaf83ed2697ef04c2249b7ff94afa9ecbcc80860482a5e6369f3a86df.json renamed to .sqlx/query-ca39a4f265b2a6b40b93de4111e6a2fde08a50c3d2d439ac18f3a1dac57ce103.json

Lines changed: 15 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.sqlx/query-ea24f36f62c84328655dbf258eb7422a1ac0bac4ea492559ec6229af2e94fe32.json renamed to .sqlx/query-f0e8817b58a17e8596b11d5b1781f648ee602223132db5d30b36a7b5a5967588.json

Lines changed: 15 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/driven-chaos/src/scenarios/concurrency.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ fn source_in(account: AccountId, root: &std::path::Path, folder_id: &str) -> Sou
147147
deep_verify_interval_secs: 604_800,
148148
last_full_scan_at: None,
149149
last_deep_verify_at: Some(0),
150+
mtime_granularity_ns: None,
150151
created_at: 0,
151152
}
152153
}

crates/driven-chaos/src/scenarios/drive_side.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ fn source_in(account: AccountId, root: &std::path::Path, folder_id: &str) -> Sou
103103
deep_verify_interval_secs: 604_800,
104104
last_full_scan_at: None,
105105
last_deep_verify_at: Some(0),
106+
mtime_granularity_ns: None,
106107
created_at: 0,
107108
}
108109
}

crates/driven-chaos/src/scenarios/file_size.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ fn source_in(account: AccountId, root: &Path, folder_id: &str) -> SourceRow {
151151
deep_verify_interval_secs: 604_800,
152152
last_full_scan_at: None,
153153
last_deep_verify_at: Some(0),
154+
mtime_granularity_ns: None,
154155
created_at: 0,
155156
}
156157
}

crates/driven-chaos/src/scenarios/filenames.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ fn source_row(account: driven_core::types::AccountId, root: &Path, folder_id: &s
249249
deep_verify_interval_secs: 604_800,
250250
last_full_scan_at: None,
251251
last_deep_verify_at: Some(0),
252+
mtime_granularity_ns: None,
252253
created_at: 0,
253254
}
254255
}

crates/driven-chaos/src/scenarios/mutation.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ fn source_in(account: driven_core::types::AccountId, root: &Path, folder_id: &st
197197
deep_verify_interval_secs: 604_800,
198198
last_full_scan_at: None,
199199
last_deep_verify_at: Some(0),
200+
mtime_granularity_ns: None,
200201
created_at: 0,
201202
}
202203
}

0 commit comments

Comments
 (0)