Skip to content

Commit 1a49eda

Browse files
committed
Use gix for simple ref-walk that won't go past the merge-base.
1 parent 73d640e commit 1a49eda

File tree

5 files changed

+64
-11
lines changed

5 files changed

+64
-11
lines changed

Cargo.lock

Lines changed: 31 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/gitbutler-branch-actions/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ reqwest = { version = "0.12.4", features = ["json"] }
4343
once_cell = "1.19"
4444
pretty_assertions = "1.4"
4545
gitbutler-testsupport.workspace = true
46-
gix = { workspace = true, features = ["max-performance-safe"] }
46+
gix = { workspace = true, features = ["max-performance"] }
4747
gitbutler-git = { workspace = true, features = ["test-askpass-path"] }
4848
glob = "0.3.1"
4949
serial_test = "3.1.1"

crates/gitbutler-branch-actions/src/branch.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,8 @@ pub fn get_branch_listing_details(
426426
.filter_map(Result::ok)
427427
.collect();
428428
let repo = ctx.repository();
429+
let mut repo2 = ctx.gix_repository_minimal()?;
430+
repo2.object_cache_size_if_unset(4 * 1024);
429431
let branches = list_branches(ctx, None, Some(branch_names))?;
430432

431433
let (default_target_current_upstream_commit_id, default_target_seen_at_last_update) = {
@@ -465,23 +467,29 @@ pub fn get_branch_listing_details(
465467

466468
let head = branch.head;
467469

468-
let mut revwalk = repo.revwalk()?;
469-
revwalk.push(head)?;
470-
revwalk.hide(base)?;
471-
let mut commits = Vec::new();
470+
let gix_base = git2_to_gix_object_id(base);
471+
// TODO: make this API nicer, maybe have one that is not based on `ancestors()` but
472+
// similar to revwalk because it's so common?
473+
let revwalk = git2_to_gix_object_id(head)
474+
.attach(&repo2)
475+
.ancestors()
476+
.selected(|id| id != gix_base)?;
477+
let mut num_commits = 0;
472478
let mut authors = HashSet::new();
473-
for oid in revwalk {
474-
let commit = repo.find_commit(oid?)?;
475-
authors.insert(commit.author().into());
476-
commits.push(commit);
479+
for commit_info in revwalk {
480+
let commit_info = commit_info?;
481+
// TODO: offer direct `find_<kind>` methods.
482+
let commit = repo2.find_object(commit_info.id)?.try_into_commit()?;
483+
authors.insert(commit.author()?.into());
484+
num_commits += 1;
477485
}
478486
let branch_data = BranchListingDetails {
479487
name: branch.name,
480488
lines_added: diff_stats.insertions(),
481489
lines_removed: diff_stats.deletions(),
482490
number_of_files: diff_stats.files_changed(),
483491
authors: authors.into_iter().collect(),
484-
number_of_commits: commits.len(),
492+
number_of_commits: num_commits,
485493
};
486494
enriched_branches.push(branch_data);
487495
}

crates/gitbutler-branch-actions/tests/fixtures/branch-details-benches.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10075,4 +10075,5 @@ git clone remote revwalk-repo
1007510075

1007610076
# pretend the remote is at the same state as our local `main`
1007710077
git update-ref refs/remotes/origin/main main
10078+
git gc --aggressive
1007810079
)

crates/gitbutler-command-context/src/lib.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ impl CommandContext {
7171
&self.git_repository
7272
}
7373

74-
/// Return a currently newly opened `gitoxide` repository.
74+
/// Return a newly opened `gitoxide` repository, with all configuration available
75+
/// to correctly figure out author and committer names (i.e. with most global configuration loaded).
7576
///
7677
/// ### Note
7778
///
@@ -84,4 +85,16 @@ impl CommandContext {
8485
pub fn gix_repository(&self) -> Result<gix::Repository> {
8586
Ok(gix::open(self.repository().path())?)
8687
}
88+
89+
/// Return a newly opened `gitoxide` repository with only the repository-local configuration
90+
/// available. This is a little faster as it has to open less files upon startup.
91+
///
92+
/// Such repositories are only useful for reference and object-access, but *can't be used* to create
93+
/// commits, fetch or push.
94+
pub fn gix_repository_minimal(&self) -> Result<gix::Repository> {
95+
Ok(gix::open_opts(
96+
self.repository().path(),
97+
gix::open::Options::isolated(),
98+
)?)
99+
}
87100
}

0 commit comments

Comments
 (0)