Skip to content

Commit 162887e

Browse files
committed
trim gix log to be mergeable.
For now, let's ignore file-based logs as it would take a moment to make it fast enough. Git can diff with pathspecs, which is probably something that would be needed to be fast here. In any case, more research would be needed to be competitive in performance. Maybe one day this will be re-added even in its current form to help with `gix blame` debugging, but I'd hope that there will be better ways to validate it.
1 parent c7e04e9 commit 162887e

File tree

1 file changed

+4
-124
lines changed
  • gitoxide-core/src/repository

1 file changed

+4
-124
lines changed

gitoxide-core/src/repository/log.rs

+4-124
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
use gix::bstr::{BStr, BString, ByteSlice};
2-
use gix::prelude::FindExt;
3-
use gix::ObjectId;
1+
use anyhow::bail;
2+
use gix::bstr::{BString, ByteSlice};
43

54
pub fn log(mut repo: gix::Repository, out: &mut dyn std::io::Write, path: Option<BString>) -> anyhow::Result<()> {
65
repo.object_cache_size_if_unset(repo.compute_object_cache_size_for_tree_diffs(&**repo.index_or_empty()?));
@@ -26,78 +25,8 @@ fn log_all(repo: gix::Repository, out: &mut dyn std::io::Write) -> Result<(), an
2625
Ok(())
2726
}
2827

29-
fn log_file(repo: gix::Repository, out: &mut dyn std::io::Write, path: BString) -> anyhow::Result<()> {
30-
let head = repo.head()?.peel_to_commit_in_place()?;
31-
let topo = gix::traverse::commit::topo::Builder::from_iters(&repo.objects, [head.id], None::<Vec<gix::ObjectId>>)
32-
.build()?;
33-
34-
'outer: for info in topo {
35-
let info = info?;
36-
let commit = repo.find_commit(info.id).unwrap();
37-
38-
let tree = repo.find_tree(commit.tree_id().unwrap()).unwrap();
39-
40-
let entry = tree.lookup_entry_by_path(path.to_path().unwrap()).unwrap();
41-
42-
let Some(entry) = entry else {
43-
continue;
44-
};
45-
46-
let parent_ids: Vec<_> = commit.parent_ids().collect();
47-
48-
if parent_ids.is_empty() {
49-
// We confirmed above that the file is in `commit`'s tree. If `parent_ids` is
50-
// empty, the file was added in `commit`.
51-
52-
write_info(&repo, out, &info)?;
53-
54-
break;
55-
}
56-
57-
let parent_ids_with_changes: Vec<_> = parent_ids
58-
.clone()
59-
.into_iter()
60-
.filter(|parent_id| {
61-
let parent_commit = repo.find_commit(*parent_id).unwrap();
62-
let parent_tree = repo.find_tree(parent_commit.tree_id().unwrap()).unwrap();
63-
let parent_entry = parent_tree.lookup_entry_by_path(path.to_path().unwrap()).unwrap();
64-
65-
if let Some(parent_entry) = parent_entry {
66-
if entry.oid() == parent_entry.oid() {
67-
// The blobs storing the file in `entry` and `parent_entry` are
68-
// identical which means the file was not changed in `commit`.
69-
70-
return false;
71-
}
72-
}
73-
74-
true
75-
})
76-
.collect();
77-
78-
if parent_ids.len() != parent_ids_with_changes.len() {
79-
// At least one parent had an identical version of the file which means it was not
80-
// changed in `commit`.
81-
82-
continue;
83-
}
84-
85-
for parent_id in parent_ids_with_changes {
86-
let modifications =
87-
get_modifications_for_file_path(&repo.objects, path.as_ref(), commit.id, parent_id.into());
88-
89-
if !modifications.is_empty() {
90-
write_info(&repo, &mut *out, &info)?;
91-
92-
// We continue because we’ve already determined that this commit is part of the
93-
// file’s history, so there’s no need to compare it to its other parents.
94-
95-
continue 'outer;
96-
}
97-
}
98-
}
99-
100-
Ok(())
28+
fn log_file(_repo: gix::Repository, _out: &mut dyn std::io::Write, _path: BString) -> anyhow::Result<()> {
29+
bail!("File-based lookup isn't yet implemented in a way that is competitively fast");
10130
}
10231

10332
fn write_info(
@@ -119,52 +48,3 @@ fn write_info(
11948

12049
Ok(())
12150
}
122-
123-
fn get_modifications_for_file_path(
124-
odb: impl gix::objs::Find + gix::objs::FindHeader,
125-
file_path: &BStr,
126-
id: ObjectId,
127-
parent_id: ObjectId,
128-
) -> Vec<gix::diff::tree::recorder::Change> {
129-
let mut buffer = Vec::new();
130-
131-
let parent = odb.find_commit(&parent_id, &mut buffer).unwrap();
132-
133-
let mut buffer = Vec::new();
134-
let parent_tree_iter = odb
135-
.find(&parent.tree(), &mut buffer)
136-
.unwrap()
137-
.try_into_tree_iter()
138-
.unwrap();
139-
140-
let mut buffer = Vec::new();
141-
let commit = odb.find_commit(&id, &mut buffer).unwrap();
142-
143-
let mut buffer = Vec::new();
144-
let tree_iter = odb
145-
.find(&commit.tree(), &mut buffer)
146-
.unwrap()
147-
.try_into_tree_iter()
148-
.unwrap();
149-
150-
let mut recorder = gix::diff::tree::Recorder::default();
151-
gix::diff::tree(
152-
parent_tree_iter,
153-
tree_iter,
154-
gix::diff::tree::State::default(),
155-
&odb,
156-
&mut recorder,
157-
)
158-
.unwrap();
159-
160-
recorder
161-
.records
162-
.iter()
163-
.filter(|change| match change {
164-
gix::diff::tree::recorder::Change::Modification { path, .. } => path == file_path,
165-
gix::diff::tree::recorder::Change::Addition { path, .. } => path == file_path,
166-
_ => false,
167-
})
168-
.cloned()
169-
.collect()
170-
}

0 commit comments

Comments
 (0)