Files
branchgraph/tests/diff.rs
Jean-Gabriel Gill-Couture e03a92c570 Remove dead code, merge duplicated logic, match docs to the code
- Drop fields and functions nothing reads: job and proc tips, fetch time,
  PR url/author (and their GraphQL fields), spine summaries, diff::commit,
  unread data attributes, unused CSS and tokens.
- One home each for state wording (naming main as the repo does), lane
  lookup, unseen, outdated, main's tip, the stop wait and the token header.
- Narrow visibility; rename render::View to Filter; queue ranking moves
  to the CLI, its only user.
- Token test covers every route; shared checkout snapshot in the fixture.
- Client: errors outside Run/Send are toasts, history only after a good
  load, a drag stays in one file, the agent marker is a ring.
- design.md, the skill and AGENTS.md describe what is built.
2026-10-09 12:24:24 -04:00

122 lines
4.0 KiB
Rust

mod fixture;
use branchgraph::diff::{self, Kind};
use fixture::{commit, git};
fn as_git(lines: &[diff::Line]) -> Vec<String> {
lines
.iter()
.map(|l| match l.kind {
Kind::Hunk => l.text.clone(),
Kind::Context => format!(" {}", l.text),
Kind::Added => format!("+{}", l.text),
Kind::Removed => format!("-{}", l.text),
})
.collect()
}
/// The hunk lines of `git show`, with the function context after `@@` cut.
fn git_show(d: &std::path::Path, rev: &str) -> Vec<String> {
git(d, &["show", "--format=", "-U3", rev])
.lines()
.skip_while(|l| !l.starts_with("@@"))
.map(|l| match l.strip_prefix("@@") {
Some(rest) => format!("@@{} @@", rest.split(" @@").next().unwrap()),
None => l.to_owned(),
})
.collect()
}
#[test]
fn hunks_match_git_show() {
let dir = tempfile::tempdir().unwrap();
let d = dir.path();
git(d, &["init", "-q"]);
let before: String = (1..=40).map(|i| format!("line {i}\n")).collect();
commit(d, "a.txt", &before, "base");
let after = before
.replace("line 2\n", "line two\n")
.replace("line 6\n", "")
.replace("line 30\n", "line 30\nnew\n");
commit(d, "a.txt", &after, "edit");
commit(d, "b.txt", "added\n", "add b");
let repo = gix::open(d).unwrap();
let id = |rev: &str| gix::ObjectId::from_hex(git(d, &["rev-parse", rev]).as_bytes()).unwrap();
let edit = diff::range(&repo, id("HEAD~2"), id("HEAD~1")).unwrap();
assert_eq!(edit.files.len(), 1);
let f = &edit.files[0];
assert_eq!((f.path.as_str(), f.stat), ("a.txt", Some((2, 2))));
assert_eq!(as_git(f.patch.as_ref().unwrap()), git_show(d, "HEAD~1"));
let add = diff::range(&repo, id("HEAD~1"), id("HEAD")).unwrap();
assert_eq!(
as_git(add.files[0].patch.as_ref().unwrap()),
git_show(d, "HEAD")
);
}
#[test]
fn diff_stops_at_the_cap() {
let dir = tempfile::tempdir().unwrap();
let d = dir.path();
git(d, &["init", "-q"]);
commit(d, "seed", "x\n", "seed");
let big: String = (0..diff::CAP / 20)
.map(|i| format!("generated line {i:06}\n"))
.collect();
std::fs::write(d.join("small.txt"), "small\n").unwrap();
commit(d, "big.txt", &big, "big");
let repo = gix::open(d).unwrap();
let id = |rev: &str| gix::ObjectId::from_hex(git(d, &["rev-parse", rev]).as_bytes()).unwrap();
let out = diff::range(&repo, id("HEAD~1"), id("HEAD")).unwrap();
assert!(out.truncated);
let got: Vec<_> = out
.files
.iter()
.map(|f| (f.path.as_str(), f.stat, f.patch.is_some()))
.collect();
let lines = (diff::CAP / 20) as u32;
assert_eq!(
got,
[
("big.txt", Some((lines, 0)), false),
("small.txt", None, false)
],
"the file that crosses the cap keeps its counts; later files are listed only"
);
}
#[test]
fn range_gives_every_file_and_one_large_file_loads_alone() {
let dir = tempfile::tempdir().unwrap();
let d = dir.path();
git(d, &["init", "-q"]);
commit(d, "seed", "x\n", "seed");
let base = git(d, &["rev-parse", "HEAD"]);
for i in 0..5 {
std::fs::write(d.join(format!("f{i}.txt")), format!("line {i}\n")).unwrap();
}
let big: String = (0..diff::CAP / 20)
.map(|i| format!("generated line {i:06}\n"))
.collect();
commit(d, "zz_big.txt", &big, "many files");
let repo = gix::open(d).unwrap();
let id = |h: &str| gix::ObjectId::from_hex(h.as_bytes()).unwrap();
let (from, to) = (id(&base), id(&git(d, &["rev-parse", "HEAD"])));
let all = diff::range(&repo, from, to).unwrap();
let small: Vec<bool> = all
.files
.iter()
.filter(|f| f.path.starts_with('f'))
.map(|f| f.patch.is_some())
.collect();
assert_eq!(small, [true; 5], "every small file comes with its lines");
let alone = diff::file(&repo, from, to, "zz_big.txt").unwrap().unwrap();
assert!(alone.patch.is_some(), "asked for by name, it loads");
}