mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-18 14:31:30 +03:00
Merge pull request #3820 from gitbutlerapp/oplog-diff-optimization
fixes incorrect snapshot diff
This commit is contained in:
commit
239eb9a84a
@ -1,5 +1,5 @@
|
|||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use git2::FileMode;
|
use git2::{FileMode, Oid};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
@ -576,18 +576,11 @@ impl Oplog for Project {
|
|||||||
let commit = repo.find_commit(git2::Oid::from_str(&sha)?)?;
|
let commit = repo.find_commit(git2::Oid::from_str(&sha)?)?;
|
||||||
// Top tree
|
// Top tree
|
||||||
let tree = commit.tree()?;
|
let tree = commit.tree()?;
|
||||||
let old_tree = commit.parent(0)?.tree()?;
|
|
||||||
|
|
||||||
let wd_tree_entry = tree
|
let wd_tree_entry = tree
|
||||||
.get_name("workdir")
|
.get_name("workdir")
|
||||||
.ok_or(anyhow!("failed to get workdir tree entry"))?;
|
.ok_or(anyhow!("failed to get workdir tree entry"))?;
|
||||||
let old_wd_tree_entry = old_tree
|
|
||||||
.get_name("workdir")
|
|
||||||
.ok_or(anyhow!("failed to get old workdir tree entry"))?;
|
|
||||||
|
|
||||||
// workdir tree
|
// workdir tree
|
||||||
let wd_tree = repo.find_tree(wd_tree_entry.id())?;
|
let wd_tree = repo.find_tree(wd_tree_entry.id())?;
|
||||||
let old_wd_tree = repo.find_tree(old_wd_tree_entry.id())?;
|
|
||||||
|
|
||||||
// Exclude files that are larger than the limit (eg. database.sql which may never be intended to be committed)
|
// Exclude files that are larger than the limit (eg. database.sql which may never be intended to be committed)
|
||||||
let files_to_exclude = get_exclude_list(&repo)?;
|
let files_to_exclude = get_exclude_list(&repo)?;
|
||||||
@ -602,11 +595,45 @@ impl Oplog for Project {
|
|||||||
.ignore_submodules(true)
|
.ignore_submodules(true)
|
||||||
.show_untracked_content(true);
|
.show_untracked_content(true);
|
||||||
|
|
||||||
let diff =
|
let oplog_state = OplogHandle::new(&self.gb_dir());
|
||||||
repo.diff_tree_to_tree(Some(&old_wd_tree), Some(&wd_tree), Some(&mut diff_opts))?;
|
let head_sha = oplog_state.get_oplog_head()?;
|
||||||
|
let child_commit_oid = get_child_commit(&repo, head_sha, commit.id())?;
|
||||||
|
|
||||||
let hunks = hunks_by_filepath(None, &diff)?;
|
if let Some(child_commit_oid) = child_commit_oid {
|
||||||
Ok(hunks)
|
let child_commit = repo.find_commit(child_commit_oid)?;
|
||||||
|
let child_tree = child_commit.tree()?;
|
||||||
|
let child_wd_tree_entry = child_tree
|
||||||
|
.get_name("workdir")
|
||||||
|
.ok_or(anyhow!("failed to get workdir tree entry"))?;
|
||||||
|
let child_wd_tree = repo.find_tree(child_wd_tree_entry.id())?;
|
||||||
|
let diff = repo.diff_tree_to_tree(Some(&wd_tree), Some(&child_wd_tree), None)?;
|
||||||
|
let hunks = hunks_by_filepath(None, &diff)?;
|
||||||
|
Ok(hunks)
|
||||||
|
} else {
|
||||||
|
let diff =
|
||||||
|
repo.diff_tree_to_workdir_with_index(Some(&wd_tree), Some(&mut diff_opts))?;
|
||||||
|
let hunks = hunks_by_filepath(None, &diff)?;
|
||||||
|
Ok(hunks)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_child_commit(
|
||||||
|
repo: &git2::Repository,
|
||||||
|
head_sha: Option<String>,
|
||||||
|
sha: Oid,
|
||||||
|
) -> Result<Option<Oid>> {
|
||||||
|
if let Some(head_sha) = head_sha {
|
||||||
|
// If this is the head, there are no children
|
||||||
|
if sha.to_string() == head_sha {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
let mut revwalk = repo.revwalk()?;
|
||||||
|
_ = revwalk.push_range(&format!("{:}..{:}", sha, &head_sha));
|
||||||
|
let mut commits = revwalk.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
Ok(commits.pop())
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user