feat(git): add commit-note support and previews in history
This change adds Git notes support to the history UI. Commits now carry a has_note flag which triggers a note indicator. Notes can be previewed on hover and loaded on demand, then the history can be refreshed after edits. - Adds has_note support on commits and parses from logs. - Renders a note indicator in history rows with a hover preview. - Triggers history refresh after note-related actions.
This commit is contained in:
Notes:
Christoph Brandau
2026-08-13 22:56:29 +02:00
one more test
+55
-3
@@ -119,6 +119,7 @@ pub struct GitCommit {
|
||||
pub refs: Vec<String>,
|
||||
pub parents: Vec<String>,
|
||||
pub files: Vec<GitCommitFile>,
|
||||
pub has_note: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
|
||||
@@ -3503,7 +3504,10 @@ fn commit_page_for_repo(
|
||||
repo,
|
||||
[
|
||||
"log",
|
||||
"--all",
|
||||
"--branches",
|
||||
"--remotes",
|
||||
"--tags",
|
||||
"HEAD",
|
||||
"--topo-order",
|
||||
"--decorate=short",
|
||||
"--name-status",
|
||||
@@ -3518,7 +3522,28 @@ fn commit_page_for_repo(
|
||||
],
|
||||
)?;
|
||||
|
||||
parse_commit_log_inline(&output)
|
||||
let mut commits = parse_commit_log_inline(&output)?;
|
||||
mark_commits_with_notes(repo, &mut commits)?;
|
||||
Ok(commits)
|
||||
}
|
||||
|
||||
fn mark_commits_with_notes(repo: &Path, commits: &mut [GitCommit]) -> Result<(), String> {
|
||||
if commits.is_empty() || !ref_exists(repo, COMMIT_NOTES_REF)? {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let output = run_git(repo, ["notes", "--ref", COMMIT_NOTES_REF, "list"])?;
|
||||
let noted_commits: BTreeSet<String> = String::from_utf8_lossy(&output)
|
||||
.lines()
|
||||
.filter_map(|line| line.split_whitespace().nth(1))
|
||||
.map(ToString::to_string)
|
||||
.collect();
|
||||
|
||||
for commit in commits {
|
||||
commit.has_note = noted_commits.contains(&commit.hash);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -3704,7 +3729,9 @@ fn list_file_history_core(
|
||||
let output = run_git_cancellable(repo, args, cancellation, "Git file history failed")?;
|
||||
check_search_cancelled(cancellation)?;
|
||||
|
||||
parse_commit_log(repo, &output)
|
||||
let mut commits = parse_commit_log(repo, &output)?;
|
||||
mark_commits_with_notes(repo, &mut commits)?;
|
||||
Ok(commits)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -5139,6 +5166,7 @@ fn parse_commit_log_inline(output: &[u8]) -> Result<Vec<GitCommit>, String> {
|
||||
parents,
|
||||
summary: String::from_utf8_lossy(parts[7]).to_string(),
|
||||
files: parse_commit_files(files_bytes)?,
|
||||
has_note: false,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5187,6 +5215,7 @@ fn parse_commit_log(repo: &Path, output: &[u8]) -> Result<Vec<GitCommit>, String
|
||||
parents,
|
||||
summary: fields[7].to_string(),
|
||||
files,
|
||||
has_note: false,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5233,6 +5262,7 @@ fn parse_commit_log_metadata(output: &[u8]) -> Result<Vec<GitCommit>, String> {
|
||||
parents,
|
||||
summary: fields[7].to_string(),
|
||||
files: Vec::new(),
|
||||
has_note: false,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -6369,6 +6399,19 @@ mod tests {
|
||||
"Review: sieht gut aus\nBuild: 42",
|
||||
)
|
||||
.expect("note should be created");
|
||||
let commits = commits_for_repo(&repo.path, Some(20)).expect("history should load");
|
||||
assert!(
|
||||
commits
|
||||
.iter()
|
||||
.find(|commit| commit.hash == commit_before)
|
||||
.expect("annotated commit should be in history")
|
||||
.has_note
|
||||
);
|
||||
assert!(
|
||||
commits
|
||||
.iter()
|
||||
.all(|commit| commit.summary != "Notes added by 'git notes add'")
|
||||
);
|
||||
assert_eq!(
|
||||
commit_note_for_repo(&repo.path, &commit_before).expect("note should load"),
|
||||
Some("Review: sieht gut aus\nBuild: 42".to_string())
|
||||
@@ -6382,6 +6425,14 @@ mod tests {
|
||||
);
|
||||
|
||||
delete_commit_note_for_repo(&repo.path, &commit_before).expect("note should be deleted");
|
||||
let commits = commits_for_repo(&repo.path, Some(20)).expect("history should reload");
|
||||
assert!(
|
||||
!commits
|
||||
.iter()
|
||||
.find(|commit| commit.hash == commit_before)
|
||||
.expect("commit should remain in history")
|
||||
.has_note
|
||||
);
|
||||
assert_eq!(
|
||||
commit_note_for_repo(&repo.path, &commit_before)
|
||||
.expect("deleted note lookup should work"),
|
||||
@@ -6782,6 +6833,7 @@ mod tests {
|
||||
],
|
||||
summary: "Add history panel".to_string(),
|
||||
files: Vec::new(),
|
||||
has_note: false,
|
||||
}]
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user