huskies: merge 629_refactor_migrate_commanddispatch_and_commandcontext_to_services_bundle

This commit is contained in:
dave
2026-04-25 20:41:19 +00:00
parent 2a3f88fdcf
commit 14b158d0b2
27 changed files with 407 additions and 544 deletions
+38 -49
View File
@@ -41,7 +41,7 @@ pub(super) fn handle_loc(ctx: &CommandContext) -> Option<String> {
let args = ctx.args.trim();
if args.is_empty() {
return Some(loc_top_n(ctx.project_root, DEFAULT_TOP_N));
return Some(loc_top_n(ctx.effective_root(), DEFAULT_TOP_N));
}
let first_token = args.split_whitespace().next().unwrap_or("");
@@ -49,8 +49,8 @@ pub(super) fn handle_loc(ctx: &CommandContext) -> Option<String> {
Ok(0) => format!(
"Usage: `loc [N]` or `loc <filepath>` — show top N source files by line count (default {DEFAULT_TOP_N}), or line count for a specific file"
),
Ok(n) => loc_top_n(ctx.project_root, n),
Err(_) => loc_single_file(ctx.project_root, args),
Ok(n) => loc_top_n(ctx.effective_root(), n),
Err(_) => loc_single_file(ctx.effective_root(), args),
})
}
@@ -209,24 +209,13 @@ fn is_source_extension(ext: &str) -> bool {
#[cfg(test)]
mod tests {
use super::*;
use crate::agents::AgentPool;
use std::collections::HashSet;
use std::sync::{Arc, Mutex};
fn make_ctx<'a>(
agents: &'a Arc<AgentPool>,
ambient_rooms: &'a Arc<Mutex<HashSet<String>>>,
services: &'a crate::services::Services,
project_root: &'a std::path::Path,
args: &'a str,
) -> super::super::CommandContext<'a> {
super::super::CommandContext {
bot_name: "Timmy",
args,
project_root,
agents,
ambient_rooms,
room_id: "!test:example.com",
}
super::super::CommandContext::new_test(services, args, "!test:example.com", project_root)
}
#[test]
@@ -252,12 +241,12 @@ mod tests {
#[test]
fn loc_default_returns_top_10() {
let agents = Arc::new(AgentPool::new_test(3000));
let ambient_rooms = Arc::new(Mutex::new(HashSet::new()));
let repo_root = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
.parent()
.unwrap_or(std::path::Path::new("."));
let ctx = make_ctx(&agents, &ambient_rooms, repo_root, "");
let services =
crate::services::Services::new_test(repo_root.to_path_buf(), "Timmy".to_string());
let ctx = make_ctx(&services, repo_root, "");
let output = handle_loc(&ctx).unwrap();
assert!(
output.contains("Top"),
@@ -273,12 +262,12 @@ mod tests {
#[test]
fn loc_with_arg_5_returns_at_most_5() {
let agents = Arc::new(AgentPool::new_test(3000));
let ambient_rooms = Arc::new(Mutex::new(HashSet::new()));
let repo_root = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
.parent()
.unwrap_or(std::path::Path::new("."));
let ctx = make_ctx(&agents, &ambient_rooms, repo_root, "5");
let services =
crate::services::Services::new_test(repo_root.to_path_buf(), "Timmy".to_string());
let ctx = make_ctx(&services, repo_root, "5");
let output = handle_loc(&ctx).unwrap();
let count = output.lines().filter(|l| l.contains(". `")).count();
assert!(
@@ -289,12 +278,12 @@ mod tests {
#[test]
fn loc_with_arg_20_returns_at_most_20() {
let agents = Arc::new(AgentPool::new_test(3000));
let ambient_rooms = Arc::new(Mutex::new(HashSet::new()));
let repo_root = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
.parent()
.unwrap_or(std::path::Path::new("."));
let ctx = make_ctx(&agents, &ambient_rooms, repo_root, "20");
let services =
crate::services::Services::new_test(repo_root.to_path_buf(), "Timmy".to_string());
let ctx = make_ctx(&services, repo_root, "20");
let output = handle_loc(&ctx).unwrap();
let count = output.lines().filter(|l| l.contains(". `")).count();
assert!(
@@ -305,12 +294,12 @@ mod tests {
#[test]
fn loc_output_contains_rank_and_line_count() {
let agents = Arc::new(AgentPool::new_test(3000));
let ambient_rooms = Arc::new(Mutex::new(HashSet::new()));
let repo_root = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
.parent()
.unwrap_or(std::path::Path::new("."));
let ctx = make_ctx(&agents, &ambient_rooms, repo_root, "");
let services =
crate::services::Services::new_test(repo_root.to_path_buf(), "Timmy".to_string());
let ctx = make_ctx(&services, repo_root, "");
let output = handle_loc(&ctx).unwrap();
// Each entry should have "N. `path` — N lines"
assert!(
@@ -325,12 +314,12 @@ mod tests {
#[test]
fn loc_zero_arg_returns_usage() {
let agents = Arc::new(AgentPool::new_test(3000));
let ambient_rooms = Arc::new(Mutex::new(HashSet::new()));
let repo_root = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
.parent()
.unwrap_or(std::path::Path::new("."));
let ctx = make_ctx(&agents, &ambient_rooms, repo_root, "0");
let services =
crate::services::Services::new_test(repo_root.to_path_buf(), "Timmy".to_string());
let ctx = make_ctx(&services, repo_root, "0");
let output = handle_loc(&ctx).unwrap();
assert!(
output.contains("Usage"),
@@ -349,9 +338,9 @@ mod tests {
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(), "hello.rs");
let services =
crate::services::Services::new_test(dir.path().to_path_buf(), "Timmy".to_string());
let ctx = make_ctx(&services, dir.path(), "hello.rs");
let output = handle_loc(&ctx).unwrap();
assert!(
output.contains("42"),
@@ -366,9 +355,9 @@ mod tests {
#[test]
fn loc_filepath_nonexistent_returns_error() {
let dir = tempfile::tempdir().expect("tempdir");
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(), "does_not_exist.rs");
let services =
crate::services::Services::new_test(dir.path().to_path_buf(), "Timmy".to_string());
let ctx = make_ctx(&services, dir.path(), "does_not_exist.rs");
let output = handle_loc(&ctx).unwrap();
assert!(
output.contains("not found") || output.contains("Error"),
@@ -378,12 +367,12 @@ mod tests {
#[test]
fn loc_skips_worktrees_directory() {
let agents = Arc::new(AgentPool::new_test(3000));
let ambient_rooms = Arc::new(Mutex::new(HashSet::new()));
let repo_root = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
.parent()
.unwrap_or(std::path::Path::new("."));
let ctx = make_ctx(&agents, &ambient_rooms, repo_root, "");
let services =
crate::services::Services::new_test(repo_root.to_path_buf(), "Timmy".to_string());
let ctx = make_ctx(&services, repo_root, "");
let output = handle_loc(&ctx).unwrap();
assert!(
!output.contains(".huskies/worktrees"),
@@ -413,9 +402,9 @@ mod tests {
writeln!(f, "fn f{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 services =
crate::services::Services::new_test(dir.path().to_path_buf(), "Timmy".to_string());
let ctx = make_ctx(&services, dir.path(), "50");
let output = handle_loc(&ctx).unwrap();
assert!(
!output.contains("target/"),
@@ -447,9 +436,9 @@ mod tests {
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 services =
crate::services::Services::new_test(dir.path().to_path_buf(), "Timmy".to_string());
let ctx = make_ctx(&services, dir.path(), "50");
let output = handle_loc(&ctx).unwrap();
assert!(
!output.contains("package-lock.json"),
@@ -486,9 +475,9 @@ mod tests {
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 services =
crate::services::Services::new_test(dir.path().to_path_buf(), "Timmy".to_string());
let ctx = make_ctx(&services, dir.path(), "50");
let output = handle_loc(&ctx).unwrap();
assert!(
!output.contains("Cargo.lock"),