Skip to content

Commit 70ce427

Browse files
alecthomasclaude
andauthored
fix: case-insensitive trailer dedup and always add Ai-assisted (#25)
## Summary - Fix case-sensitive `Co-authored-by:` trailer check that missed variants like `Co-Authored-By:` - When the co-author email is already present, still add `Ai-assisted: true` if missing - Add test for case-insensitive trailer matching and assertions for `Ai-assisted` in existing dedup tests ## Test plan - [x] `cargo test` — all 21 tests pass - [x] `cargo clippy -- -D warnings` — clean 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent f8c4839 commit 70ce427

File tree

2 files changed

+63
-16
lines changed

2 files changed

+63
-16
lines changed

src/git.rs

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,36 +23,50 @@ pub fn append_trailers(commit_msg_file: &PathBuf, agent: &Agent, debug: bool) ->
2323
let content = fs::read_to_string(commit_msg_file)?;
2424

2525
let addr = Agent::extract_email_addr(agent.email);
26-
if content.contains("Co-authored-by:") && content.contains(addr) {
26+
let content_lower = content.to_lowercase();
27+
let has_co_author = content_lower.contains("co-authored-by:") && content_lower.contains(&addr.to_lowercase());
28+
let has_ai_assisted = content_lower.contains("ai-assisted: true");
29+
30+
if has_co_author && has_ai_assisted {
2731
if debug {
2832
eprintln!("\n=== Git Command ===");
2933
eprintln!("Trailers already present, skipping git interpret-trailers");
3034
}
3135
return Ok(());
3236
}
3337

34-
let co_authored = format!("Co-authored-by: {}", agent.email);
38+
let mut cmd = std::process::Command::new("git");
39+
cmd.arg("interpret-trailers").arg("--in-place");
3540

36-
if debug {
41+
if !has_co_author {
42+
let co_authored = format!("Co-authored-by: {}", agent.email);
43+
if debug {
44+
eprintln!("\n=== Git Command ===");
45+
eprintln!(
46+
"git interpret-trailers --in-place --trailer \"{}\" --if-exists addIfDifferent --trailer \"Ai-assisted: true\" \"{}\"",
47+
co_authored,
48+
commit_msg_file.display()
49+
);
50+
}
51+
cmd.arg("--trailer")
52+
.arg(&co_authored)
53+
.arg("--if-exists")
54+
.arg("addIfDifferent");
55+
} else if debug {
3756
eprintln!("\n=== Git Command ===");
3857
eprintln!(
39-
"git interpret-trailers --in-place --trailer \"{}\" --if-exists addIfDifferent --trailer \"Ai-assisted: true\" \"{}\"",
40-
co_authored,
58+
"git interpret-trailers --in-place --trailer \"Ai-assisted: true\" \"{}\"",
4159
commit_msg_file.display()
4260
);
4361
}
4462

45-
let output = std::process::Command::new("git")
46-
.arg("interpret-trailers")
47-
.arg("--in-place")
48-
.arg("--trailer")
49-
.arg(&co_authored)
50-
.arg("--if-exists")
51-
.arg("addIfDifferent")
52-
.arg("--trailer")
53-
.arg("Ai-assisted: true")
54-
.arg(commit_msg_file)
55-
.output()?;
63+
if !has_ai_assisted {
64+
cmd.arg("--trailer").arg("Ai-assisted: true");
65+
}
66+
67+
cmd.arg(commit_msg_file);
68+
69+
let output = cmd.output()?;
5670

5771
if !output.status.success() {
5872
return Err(std::io::Error::other(format!(

src/main.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,34 @@ mod tests {
258258
let agent = Agent::find_by_name("claude").unwrap();
259259
append_trailers(&file.path().to_path_buf(), agent, false).unwrap();
260260

261+
let content = fs::read_to_string(file.path()).unwrap();
262+
let co_author_count = content.matches("noreply@anthropic.com").count();
263+
assert_eq!(
264+
co_author_count, 1,
265+
"Should not add duplicate trailer for same email address, found {} occurrences",
266+
co_author_count
267+
);
268+
assert!(
269+
content.contains("Ai-assisted: true"),
270+
"Should still add Ai-assisted trailer even when co-authored-by already exists"
271+
);
272+
}
273+
274+
#[test]
275+
fn test_append_trailers_skips_existing_email_different_case() {
276+
// The "Co-Authored-By" key can have varying capitalisation
277+
let mut file = NamedTempFile::new().unwrap();
278+
writeln!(file, "Initial commit").unwrap();
279+
writeln!(file).unwrap();
280+
writeln!(
281+
file,
282+
"Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>"
283+
)
284+
.unwrap();
285+
286+
let agent = Agent::find_by_name("claude").unwrap();
287+
append_trailers(&file.path().to_path_buf(), agent, false).unwrap();
288+
261289
let content = fs::read_to_string(file.path()).unwrap();
262290
// Should NOT have added a second Co-authored-by for noreply@anthropic.com
263291
let co_author_count = content.matches("noreply@anthropic.com").count();
@@ -266,6 +294,11 @@ mod tests {
266294
"Should not add duplicate trailer for same email address, found {} occurrences",
267295
co_author_count
268296
);
297+
// But SHOULD have added Ai-assisted
298+
assert!(
299+
content.contains("Ai-assisted: true"),
300+
"Should still add Ai-assisted trailer even when co-authored-by already exists"
301+
);
269302
}
270303

271304
#[test]

0 commit comments

Comments
 (0)