huskies: merge 1013

This commit is contained in:
dave
2026-05-13 23:07:32 +00:00
parent 4e007bb770
commit 8754c790b9
2 changed files with 154 additions and 33 deletions
+64 -23
View File
@@ -5,8 +5,13 @@
//! Exits with code 1 and prints LLM-friendly directions when public items are
//! missing doc comments. Exits 0 (silently) when all changed files are fully
//! documented or when there are no relevant changes to check.
//!
//! The file set is derived from all worktree states: committed changes since
//! `base`, staged changes, unstaged changes, and untracked files. This ensures
//! the result is independent of git index state.
use source_map_gen::{CheckResult, check_files_ratcheted};
use std::collections::HashSet;
use std::path::{Path, PathBuf};
use std::process::Command;
@@ -17,29 +22,7 @@ fn main() {
let worktree_path = Path::new(&worktree);
let output = match Command::new("git")
.args(["diff", "--name-only", &format!("{base}...HEAD")])
.current_dir(worktree_path)
.output()
{
Ok(o) => o,
Err(e) => {
eprintln!("source-map-check: git diff failed: {e}");
std::process::exit(1);
}
};
if !output.status.success() {
// Base branch not found or other git error — skip the check gracefully.
return;
}
let changed: Vec<PathBuf> = String::from_utf8_lossy(&output.stdout)
.lines()
.filter(|l| !l.is_empty())
.map(|l| worktree_path.join(l))
.filter(|p| p.exists())
.collect();
let changed = collect_changed_files(worktree_path, &base);
if changed.is_empty() {
return;
@@ -64,6 +47,64 @@ fn main() {
}
}
/// Collect all files that differ from `base` in any git state: committed, staged,
/// unstaged, or untracked. Returns deduplicated absolute paths that exist on disk.
fn collect_changed_files(worktree_path: &Path, base: &str) -> Vec<PathBuf> {
let mut names: HashSet<String> = HashSet::new();
// Committed changes since base (three-dot diff handles divergent histories).
run_git_name_list(
worktree_path,
&["diff", "--name-only", &format!("{base}...HEAD")],
&mut names,
);
// Staged changes not yet committed.
run_git_name_list(
worktree_path,
&["diff", "--name-only", "--cached"],
&mut names,
);
// Unstaged changes to tracked files.
run_git_name_list(worktree_path, &["diff", "--name-only"], &mut names);
// Untracked files (new files not yet added to the index).
run_git_name_list(
worktree_path,
&["ls-files", "--others", "--exclude-standard"],
&mut names,
);
names
.into_iter()
.map(|l| worktree_path.join(l))
.filter(|p| p.exists())
.collect()
}
/// Run a git command and collect each non-empty output line into `out`.
///
/// Silently ignores git errors so a missing base branch or a fresh repo without
/// any commits does not abort the check.
fn run_git_name_list(worktree_path: &Path, args: &[&str], out: &mut HashSet<String>) {
let Ok(output) = Command::new("git")
.args(args)
.current_dir(worktree_path)
.output()
else {
return;
};
if !output.status.success() {
return;
}
for line in String::from_utf8_lossy(&output.stdout).lines() {
if !line.is_empty() {
out.insert(line.to_string());
}
}
}
/// Parse a flag value from an argument list (e.g. `--flag value`).
fn parse_arg(args: &[String], flag: &str) -> Option<String> {
args.windows(2).find(|w| w[0] == flag).map(|w| w[1].clone())