optimize logfilter to not check stashes

logfilter using `get_commit_diff` on each entry lead to a lot of unneeded calls to `get_stashes` and `is_stash_commit` which should be not even needed for file history log entries. this is not happening now anymore
This commit is contained in:
extrawurst 2023-08-11 11:38:21 +02:00
parent e90656d61c
commit 9eb8d470a4
5 changed files with 35 additions and 39 deletions

View file

@ -1,14 +1,14 @@
//! Functions for getting infos about files in commits //! Functions for getting infos about files in commits
use super::{ use super::{diff::DiffOptions, CommitId, RepoPath};
diff::DiffOptions, stash::is_stash_commit, CommitId, RepoPath,
};
use crate::{ use crate::{
error::Result, sync::repository::repo, StatusItem, StatusItemType, error::Result,
sync::{get_stashes, repository::repo},
StatusItem, StatusItemType,
}; };
use git2::{Diff, Repository}; use git2::{Diff, Repository};
use scopetime::scope_time; use scopetime::scope_time;
use std::cmp::Ordering; use std::{cmp::Ordering, collections::HashSet};
/// get all files that are part of a commit /// get all files that are part of a commit
pub fn get_commit_files( pub fn get_commit_files(
@ -23,7 +23,13 @@ pub fn get_commit_files(
let diff = if let Some(other) = other { let diff = if let Some(other) = other {
get_compare_commits_diff(&repo, (id, other), None, None)? get_compare_commits_diff(&repo, (id, other), None, None)?
} else { } else {
get_commit_diff(repo_path, &repo, id, None, None)? get_commit_diff(
&repo,
id,
None,
None,
Some(&get_stashes(repo_path)?.into_iter().collect()),
)?
}; };
let res = diff let res = diff
@ -91,12 +97,12 @@ pub fn get_compare_commits_diff(
} }
/// get diff of a commit to its first parent /// get diff of a commit to its first parent
pub fn get_commit_diff<'a>( pub(crate) fn get_commit_diff<'a>(
repo_path: &RepoPath,
repo: &'a Repository, repo: &'a Repository,
id: CommitId, id: CommitId,
pathspec: Option<String>, pathspec: Option<String>,
options: Option<DiffOptions>, options: Option<DiffOptions>,
stashes: Option<&HashSet<CommitId>>,
) -> Result<Diff<'a>> { ) -> Result<Diff<'a>> {
// scope_time!("get_commit_diff"); // scope_time!("get_commit_diff");
@ -128,14 +134,17 @@ pub fn get_commit_diff<'a>(
Some(&mut opts), Some(&mut opts),
)?; )?;
if is_stash_commit(repo_path, &id)? { if stashes
.map(|stashes| stashes.contains(&id))
.unwrap_or_default()
{
if let Ok(untracked_commit) = commit.parent_id(2) { if let Ok(untracked_commit) = commit.parent_id(2) {
let untracked_diff = get_commit_diff( let untracked_diff = get_commit_diff(
repo_path,
repo, repo,
CommitId::new(untracked_commit), CommitId::new(untracked_commit),
pathspec, pathspec,
options, options,
stashes,
)?; )?;
diff.merge(&untracked_diff)?; diff.merge(&untracked_diff)?;

View file

@ -6,7 +6,10 @@ use super::{
CommitId, RepoPath, CommitId, RepoPath,
}; };
use crate::{ use crate::{
error::Error, error::Result, hash, sync::repository::repo, error::Error,
error::Result,
hash,
sync::{get_stashes, repository::repo},
}; };
use easy_cast::Conv; use easy_cast::Conv;
use git2::{ use git2::{
@ -223,8 +226,13 @@ pub fn get_diff_commit(
let repo = repo(repo_path)?; let repo = repo(repo_path)?;
let work_dir = work_dir(&repo)?; let work_dir = work_dir(&repo)?;
let diff = let diff = get_commit_diff(
get_commit_diff(repo_path, &repo, id, Some(p), options)?; &repo,
id,
Some(p),
options,
Some(&get_stashes(repo_path)?.into_iter().collect()),
)?;
raw_diff_to_file_diff(&diff, work_dir) raw_diff_to_file_diff(&diff, work_dir)
} }

View file

@ -1,5 +1,4 @@
use super::CommitId; use super::CommitId;
use crate::sync::RepoPath;
use crate::{error::Result, sync::commit_files::get_commit_diff}; use crate::{error::Result, sync::commit_files::get_commit_diff};
use git2::{Commit, Oid, Repository}; use git2::{Commit, Oid, Repository};
use std::{ use std::{
@ -36,20 +35,17 @@ pub type LogWalkerFilter = Arc<
>; >;
/// ///
pub fn diff_contains_file( pub fn diff_contains_file(file_path: String) -> LogWalkerFilter {
repo_path: RepoPath,
file_path: String,
) -> LogWalkerFilter {
Arc::new(Box::new( Arc::new(Box::new(
move |repo: &Repository, move |repo: &Repository,
commit_id: &CommitId| commit_id: &CommitId|
-> Result<bool> { -> Result<bool> {
let diff = get_commit_diff( let diff = get_commit_diff(
&repo_path,
repo, repo,
*commit_id, *commit_id,
Some(file_path.clone()), Some(file_path.clone()),
None, None,
None,
)?; )?;
let contains_file = diff.deltas().len() > 0; let contains_file = diff.deltas().len() > 0;
@ -224,9 +220,7 @@ mod tests {
let _third_commit_id = commit(&repo_path, "commit3").unwrap(); let _third_commit_id = commit(&repo_path, "commit3").unwrap();
let repo_path_clone = repo_path.clone(); let diff_contains_baz = diff_contains_file("baz".into());
let diff_contains_baz =
diff_contains_file(repo_path_clone, "baz".into());
let mut items = Vec::new(); let mut items = Vec::new();
let mut walker = LogWalker::new(&repo, 100)? let mut walker = LogWalker::new(&repo, 100)?
@ -241,8 +235,7 @@ mod tests {
assert_eq!(items.len(), 0); assert_eq!(items.len(), 0);
let diff_contains_bar = let diff_contains_bar = diff_contains_file("bar".into());
diff_contains_file(repo_path, "bar".into());
let mut items = Vec::new(); let mut items = Vec::new();
let mut walker = LogWalker::new(&repo, 100)? let mut walker = LogWalker::new(&repo, 100)?

View file

@ -14,9 +14,7 @@ pub fn get_stashes(repo_path: &RepoPath) -> Result<Vec<CommitId>> {
scope_time!("get_stashes"); scope_time!("get_stashes");
let mut repo = repo(repo_path)?; let mut repo = repo(repo_path)?;
let mut list = Vec::new(); let mut list = Vec::new();
repo.stash_foreach(|_index, _msg, id| { repo.stash_foreach(|_index, _msg, id| {
list.push((*id).into()); list.push((*id).into());
true true
@ -25,15 +23,6 @@ pub fn get_stashes(repo_path: &RepoPath) -> Result<Vec<CommitId>> {
Ok(list) Ok(list)
} }
/// checks whether a given commit is a stash commit.
pub fn is_stash_commit(
repo_path: &RepoPath,
id: &CommitId,
) -> Result<bool> {
let stashes = get_stashes(repo_path)?;
Ok(stashes.contains(id))
}
/// ///
pub fn stash_drop( pub fn stash_drop(
repo_path: &RepoPath, repo_path: &RepoPath,

View file

@ -117,10 +117,7 @@ impl FileRevlogComponent {
pub fn open(&mut self, open_request: FileRevOpen) -> Result<()> { pub fn open(&mut self, open_request: FileRevOpen) -> Result<()> {
self.open_request = Some(open_request.clone()); self.open_request = Some(open_request.clone());
let filter = diff_contains_file( let filter = diff_contains_file(open_request.file_path);
self.repo_path.borrow().clone(),
open_request.file_path,
);
self.git_log = Some(AsyncLog::new( self.git_log = Some(AsyncLog::new(
self.repo_path.borrow().clone(), self.repo_path.borrow().clone(),
&self.sender, &self.sender,