Skip to content
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions src/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,35 @@ pub async fn generate_commit_message(
eprintln!("警告: 解析 issues 参数失败: {}", e);
}
}
} else if amend {
// 在 amend 模式下且未提供新的 issues 参数时,从原提交中保留 issue 引用(Fixes:/PMS:)
if let Some(ref orig_msg) = original_message {
let orig_commit = CommitMessage::parse(orig_msg);
let issue_marks: Vec<String> = orig_commit.marks.iter()
.filter(|mark| {
let mark_lower = mark.to_lowercase();
mark_lower.starts_with("fixes:") || mark_lower.starts_with("pms:")
Comment thread
zccrs marked this conversation as resolved.
Outdated
})
.cloned()
.collect();
// 只添加新内容中尚未包含的标记
let marks_to_add: Vec<String> = issue_marks.into_iter()
.filter(|mark| {
let mark_key = mark.split(':').next().unwrap_or("").trim().to_lowercase();
!content.lines().any(|line| {
line.trim().split(':').next()
.map_or(false, |k| k.trim().to_lowercase() == mark_key)
})
})
.collect();
if !marks_to_add.is_empty() {
if !content.ends_with('\n') {
content.push('\n');
}
content.push('\n');
content.push_str(&marks_to_add.join("\n"));
}
}
}

// 在 amend 模式下,如果原提交有 Change-Id,保留它
Expand Down Expand Up @@ -1154,4 +1183,80 @@ mod tests {
// Change-Id 应该在最后
assert!(result.ends_with("Change-Id: I1234567890abcdef1234567890abcdef12345678"));
}

// 测试 amend 模式下从原提交消息中提取 issue 引用标记
#[test]
fn test_extract_issue_marks_from_original_commit() {
let original = "fix: some bug\n\nDescription here\n\nFixes: #123\nPMS: BUG-456\nChange-Id: Iabc123\n";
let orig_commit = CommitMessage::parse(original);
let issue_marks: Vec<String> = orig_commit.marks.iter()
.filter(|mark| {
let mark_lower = mark.to_lowercase();
mark_lower.starts_with("fixes:") || mark_lower.starts_with("pms:")
})
.cloned()
.collect();
assert_eq!(issue_marks.len(), 2);
assert!(issue_marks.contains(&"Fixes: #123".to_string()));
assert!(issue_marks.contains(&"PMS: BUG-456".to_string()));
// Change-Id 不应被提取为 issue 标记
assert!(!issue_marks.iter().any(|m| m.starts_with("Change-Id:")));
}

// 测试 amend 时新内容已包含 issue 引用时不重复添加
#[test]
fn test_amend_no_duplicate_issue_marks() {
let original = "fix: some bug\n\nFixes: #123\n";
let orig_commit = CommitMessage::parse(original);
let issue_marks: Vec<String> = orig_commit.marks.iter()
.filter(|mark| {
let mark_lower = mark.to_lowercase();
mark_lower.starts_with("fixes:") || mark_lower.starts_with("pms:")
})
.cloned()
.collect();

// 新内容已包含 Fixes:
let new_content = "fix: improved bug fix\n\nBetter description\n\nFixes: #123";
let marks_to_add: Vec<String> = issue_marks.into_iter()
.filter(|mark| {
let mark_key = mark.split(':').next().unwrap_or("").trim().to_lowercase();
!new_content.lines().any(|line| {
line.trim().split(':').next()
.map_or(false, |k| k.trim().to_lowercase() == mark_key)
})
})
.collect();
// 不应重复添加
assert!(marks_to_add.is_empty());
}

// 测试 amend 时新内容不含 issue 引用时正确添加
#[test]
fn test_amend_preserves_issue_marks_when_missing() {
let original = "fix: some bug\n\nFixes: #123\nPMS: BUG-456\n";
let orig_commit = CommitMessage::parse(original);
let issue_marks: Vec<String> = orig_commit.marks.iter()
.filter(|mark| {
let mark_lower = mark.to_lowercase();
mark_lower.starts_with("fixes:") || mark_lower.starts_with("pms:")
})
.cloned()
.collect();

// 新内容不含 issue 引用
let new_content = "fix: improved bug fix\n\nBetter description";
let marks_to_add: Vec<String> = issue_marks.into_iter()
.filter(|mark| {
let mark_key = mark.split(':').next().unwrap_or("").trim().to_lowercase();
!new_content.lines().any(|line| {
line.trim().split(':').next()
.map_or(false, |k| k.trim().to_lowercase() == mark_key)
})
})
.collect();
assert_eq!(marks_to_add.len(), 2);
assert!(marks_to_add.contains(&"Fixes: #123".to_string()));
assert!(marks_to_add.contains(&"PMS: BUG-456".to_string()));
}
}