From 7c8bf89e02bb5188457bb28bcefda6b175d4e2e8 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 9 Nov 2016 19:18:58 -0800 Subject: [PATCH] log: Walk series commits by hand, to allow pruning while walking Current versions of libgit2 no longer allow hiding commits while walking. With those versions, the revwalk would walk the entire project history, not just the series history, taking seconds or minutes on large repositories. Work around that by doing the initial walk of series commits by hand rather than with a revwalk. The second walk still uses a revwalk, for topological sorting. --- src/main.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/main.rs b/src/main.rs index ae8bc3487468ce020d5a554b83182b01da2fae8e..6a241233dae3b22739d2524902cbf93f119d4dd8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1371,27 +1371,25 @@ fn log(out: &mut Output, repo: &Repository, m: &ArgMatches) -> Result<()> { try!(out.auto_pager(&config, "log", true)); let diffcolors = try!(DiffColors::new(out, &config)); - let mut revwalk = try!(repo.revwalk()); - try!(revwalk.push_ref(SHEAD_REF)); - - // Walk once before sorting, to find all the commits to hide. Revwalk doesn't support hiding on - // the fly when sorted. + let shead_id = try!(repo.refname_to_id(SHEAD_REF)); let mut hidden_ids = std::collections::HashSet::new(); - while let Some(oid) = revwalk.next() { - let oid = try!(oid); + let mut commit_stack = Vec::new(); + commit_stack.push(shead_id); + while let Some(oid) = commit_stack.pop() { let commit = try!(repo.find_commit(oid)); let tree = try!(commit.tree()); for parent_id in commit.parent_ids() { if tree.get_id(parent_id).is_some() { - try!(revwalk.hide(parent_id)); hidden_ids.insert(parent_id); + } else { + commit_stack.push(parent_id); } } } - // set_sorting resets the revwalk + let mut revwalk = try!(repo.revwalk()); revwalk.set_sorting(git2::SORT_TOPOLOGICAL); - try!(revwalk.push_ref(SHEAD_REF)); + try!(revwalk.push(shead_id)); for id in hidden_ids { try!(revwalk.hide(id)); }