From e88b9bbc63d1f512a23e27d80415963ca9f3c2e1 Mon Sep 17 00:00:00 2001 From: dave Date: Fri, 27 Mar 2026 15:35:20 +0000 Subject: [PATCH] storkit: merge 414_story_loc_command_filters_out_known_huge_files --- server/src/chat/commands/loc.rs | 104 ++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/server/src/chat/commands/loc.rs b/server/src/chat/commands/loc.rs index 1f71eafd..0d9b5afa 100644 --- a/server/src/chat/commands/loc.rs +++ b/server/src/chat/commands/loc.rs @@ -20,6 +20,23 @@ const SKIP_DIRS: &[&str] = &[ /// Path components that indicate a worktree path that should be skipped. const SKIP_PATH_COMPONENTS: &[&str] = &[".storkit/worktrees"]; +/// Known-huge or machine-generated files that are excluded from the loc count +/// even when they have a recognised source extension (e.g. `.json`, `.yaml`). +/// Add entries here to extend the exclusion list. +const EXCLUDED_FILENAMES: &[&str] = &[ + "package-lock.json", + "yarn.lock", + "pnpm-lock.yaml", + "bun.lockb", + "Cargo.lock", + "composer.lock", + "Gemfile.lock", + "poetry.lock", + "go.sum", + "go.work.sum", + "flake.lock", +]; + pub(super) fn handle_loc(ctx: &CommandContext) -> Option { let top_n = if ctx.args.is_empty() { DEFAULT_TOP_N @@ -64,6 +81,11 @@ pub(super) fn handle_loc(ctx: &CommandContext) -> Option { return None; } let path = entry.path(); + // Skip known-huge or machine-generated files (lockfiles, etc.). + let filename = path.file_name().and_then(|f| f.to_str()).unwrap_or(""); + if EXCLUDED_FILENAMES.contains(&filename) { + return None; + } // Skip binary/generated files without a recognisable text extension. let ext = path.extension().and_then(|e| e.to_str()).unwrap_or(""); if !is_source_extension(ext) { @@ -264,6 +286,88 @@ mod tests { ); } + #[test] + fn loc_excludes_lockfiles_from_results() { + use std::io::Write as _; + let dir = tempfile::tempdir().expect("tempdir"); + // Write a package-lock.json with many lines — it must NOT appear in output. + let lockfile = dir.path().join("package-lock.json"); + { + let mut f = std::fs::File::create(&lockfile).unwrap(); + for _ in 0..500 { + writeln!(f, " \"line\": true,").unwrap(); + } + } + // Write a real source file so the output is non-empty. + let source = dir.path().join("main.rs"); + { + let mut f = std::fs::File::create(&source).unwrap(); + for i in 0..20 { + writeln!(f, "fn line_{i}() {{}}").unwrap(); + } + } + let agents = Arc::new(AgentPool::new_test(3000)); + let ambient_rooms = Arc::new(Mutex::new(HashSet::new())); + let ctx = make_ctx(&agents, &ambient_rooms, dir.path(), "50"); + let output = handle_loc(&ctx).unwrap(); + assert!( + !output.contains("package-lock.json"), + "package-lock.json must be excluded from loc output: {output}" + ); + assert!( + output.contains("main.rs"), + "main.rs should appear in loc output: {output}" + ); + } + + #[test] + fn loc_excludes_cargo_lock_from_results() { + use std::io::Write as _; + let dir = tempfile::tempdir().expect("tempdir"); + // Cargo.lock has no recognised source extension so it would be skipped + // anyway — but we still verify EXCLUDED_FILENAMES contains it. + assert!( + EXCLUDED_FILENAMES.contains(&"Cargo.lock"), + "EXCLUDED_FILENAMES must contain Cargo.lock" + ); + // Write a Cargo.lock with many lines and verify it is excluded. + let lockfile = dir.path().join("Cargo.lock"); + { + let mut f = std::fs::File::create(&lockfile).unwrap(); + for _ in 0..500 { + writeln!(f, "name = \"foo\"").unwrap(); + } + } + let source = dir.path().join("lib.rs"); + { + let mut f = std::fs::File::create(&source).unwrap(); + for i in 0..10 { + std::io::Write::write_all(&mut f, format!("fn f{i}() {{}}\n").as_bytes()).unwrap(); + } + } + let agents = Arc::new(AgentPool::new_test(3000)); + let ambient_rooms = Arc::new(Mutex::new(HashSet::new())); + let ctx = make_ctx(&agents, &ambient_rooms, dir.path(), "50"); + let output = handle_loc(&ctx).unwrap(); + assert!( + !output.contains("Cargo.lock"), + "Cargo.lock must be excluded from loc output: {output}" + ); + } + + #[test] + fn excluded_filenames_constant_is_defined() { + // The constant must contain the examples from the story. + assert!( + EXCLUDED_FILENAMES.contains(&"package-lock.json"), + "EXCLUDED_FILENAMES must contain package-lock.json" + ); + assert!( + EXCLUDED_FILENAMES.contains(&"Cargo.lock"), + "EXCLUDED_FILENAMES must contain Cargo.lock" + ); + } + #[test] fn loc_works_via_full_dispatch() { // Verifies the command is reachable through the same dispatch path used