Skip to content

Commit 9ad2800

Browse files
committed
Write blame to stdout
1 parent ae6f127 commit 9ad2800

File tree

2 files changed

+42
-18
lines changed

2 files changed

+42
-18
lines changed
Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,54 @@
1-
use std::{ffi::OsStr, os::unix::ffi::OsStrExt, path::PathBuf};
1+
use std::{ffi::OsStr, os::unix::ffi::OsStrExt, path::PathBuf, str::Lines};
22

33
use gix::bstr::BStr;
44

5-
pub fn blame_file(repo: gix::Repository, file: &OsStr) -> anyhow::Result<()> {
6-
let traverse: Vec<Result<gix::traverse::commit::Info, gix::traverse::commit::simple::Error>> = vec![];
5+
pub fn blame_file(repo: gix::Repository, file: &OsStr, out: impl std::io::Write) -> anyhow::Result<()> {
6+
let suspect = repo.head()?.peel_to_commit_in_place()?;
7+
let traverse: Vec<_> = gix::traverse::commit::Simple::new(Some(suspect.id), &repo.objects).collect();
78
let mut resource_cache = repo.diff_resource_cache_for_tree_diff()?;
8-
let mut reference = gix::refs::file::Store::find(&repo.refs, "HEAD")?;
9-
10-
// Needed for `peel_to_id_in_place`.
11-
use gix::refs::file::ReferenceExt;
12-
13-
let suspect = reference.peel_to_id_in_place(&repo.refs, &repo.objects)?;
149

1510
let work_dir: PathBuf = repo.work_dir().expect("TODO").into();
1611
let file_path: &BStr = file.as_bytes().into();
1712

18-
if let Ok(_blame_entries) = gix::blame::blame_file(
19-
repo.objects,
13+
let blame_entries = gix::blame::blame_file(
14+
&repo.objects,
2015
traverse,
2116
&mut resource_cache,
22-
suspect,
23-
work_dir,
17+
suspect.id,
18+
work_dir.clone(),
2419
&file_path,
25-
) {
26-
todo!()
27-
} else {
28-
todo!()
20+
)
21+
.expect("TODO");
22+
23+
let absolute_path = work_dir.join(file);
24+
let file_content = std::fs::read_to_string(absolute_path).expect("TODO");
25+
let lines = file_content.lines();
26+
27+
write_blame_entries(out, lines, blame_entries)?;
28+
29+
Ok(())
30+
}
31+
32+
fn write_blame_entries(
33+
mut out: impl std::io::Write,
34+
mut lines: Lines<'_>,
35+
blame_entries: Vec<gix::blame::BlameEntry>,
36+
) -> Result<(), std::io::Error> {
37+
for blame_entry in blame_entries {
38+
for line_number in blame_entry.range_in_blamed_file {
39+
let line = lines.next().unwrap();
40+
41+
writeln!(
42+
out,
43+
"{} {} {}",
44+
blame_entry.commit_id.to_hex_with_len(8),
45+
// `line_number` is 0-based, but we want to show 1-based line numbers (as `git`
46+
// does).
47+
line_number + 1,
48+
line
49+
)?;
50+
}
2951
}
52+
53+
Ok(())
3054
}

src/plumbing/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1442,7 +1442,7 @@ pub fn main() -> Result<()> {
14421442
progress,
14431443
progress_keep_open,
14441444
None,
1445-
move |_progress, _out, _err| core::repository::blame::blame_file(repository(Mode::Lenient)?, &file),
1445+
move |_progress, out, _err| core::repository::blame::blame_file(repository(Mode::Lenient)?, &file, out),
14461446
),
14471447
Subcommands::Completions { shell, out_dir } => {
14481448
let mut app = Args::command();

0 commit comments

Comments
 (0)