forked from mirrors/jj
templater: fast-path empty
and conflict
to not read trees
When there's a single parent, we can determine if a commit is empty by just comparing the tree ids. Also, when using tree-level conflicts, we don't need to read the trees to determine if there's a conflict. This patch adds both of those fast paths, speeding up `jj log -r ::main` from 317 ms to 227 ms (-28.4%). It has much larger impact with our cloud-based backend at Google (~5x faster). I made the same fix in the revset engine and the Git push code (thanks to Yuya for the suggestion).
This commit is contained in:
parent
e5ad32e29e
commit
e50f6acab1
4 changed files with 16 additions and 5 deletions
|
@ -905,7 +905,7 @@ fn cmd_git_push(
|
||||||
{
|
{
|
||||||
reasons.push("it has no author and/or committer set");
|
reasons.push("it has no author and/or committer set");
|
||||||
}
|
}
|
||||||
if commit.tree()?.has_conflict() {
|
if commit.has_conflict()? {
|
||||||
reasons.push("it has conflicts");
|
reasons.push("it has conflicts");
|
||||||
}
|
}
|
||||||
if !reasons.is_empty() {
|
if !reasons.is_empty() {
|
||||||
|
|
|
@ -299,10 +299,13 @@ fn build_commit_keyword_opt<'repo>(
|
||||||
let maybe_entries = repo.resolve_change_id(commit.change_id());
|
let maybe_entries = repo.resolve_change_id(commit.change_id());
|
||||||
maybe_entries.map_or(true, |entries| !entries.contains(commit.id()))
|
maybe_entries.map_or(true, |entries| !entries.contains(commit.id()))
|
||||||
})),
|
})),
|
||||||
"conflict" => language.wrap_boolean(wrap_fn(property, |commit| {
|
"conflict" => {
|
||||||
commit.tree().unwrap().has_conflict()
|
language.wrap_boolean(wrap_fn(property, |commit| commit.has_conflict().unwrap()))
|
||||||
})),
|
}
|
||||||
"empty" => language.wrap_boolean(wrap_fn(property, |commit| {
|
"empty" => language.wrap_boolean(wrap_fn(property, |commit| {
|
||||||
|
if let [parent] = &commit.parents()[..] {
|
||||||
|
return parent.tree_id() == commit.tree_id();
|
||||||
|
}
|
||||||
let parent_tree = rewrite::merge_commit_trees(repo, &commit.parents()).unwrap();
|
let parent_tree = rewrite::merge_commit_trees(repo, &commit.parents()).unwrap();
|
||||||
*commit.tree_id() == parent_tree.id()
|
*commit.tree_id() == parent_tree.id()
|
||||||
})),
|
})),
|
||||||
|
|
|
@ -108,6 +108,14 @@ impl Commit {
|
||||||
&self.data.root_tree
|
&self.data.root_tree
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn has_conflict(&self) -> Result<bool, BackendError> {
|
||||||
|
if let MergedTreeId::Merge(tree_ids) = self.tree_id() {
|
||||||
|
Ok(!tree_ids.is_resolved())
|
||||||
|
} else {
|
||||||
|
Ok(self.tree()?.has_conflict())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn change_id(&self) -> &ChangeId {
|
pub fn change_id(&self) -> &ChangeId {
|
||||||
&self.data.change_id
|
&self.data.change_id
|
||||||
}
|
}
|
||||||
|
|
|
@ -869,7 +869,7 @@ fn build_predicate_fn<'index>(
|
||||||
}
|
}
|
||||||
RevsetFilterPredicate::HasConflict => pure_predicate_fn(move |entry| {
|
RevsetFilterPredicate::HasConflict => pure_predicate_fn(move |entry| {
|
||||||
let commit = store.get_commit(&entry.commit_id()).unwrap();
|
let commit = store.get_commit(&entry.commit_id()).unwrap();
|
||||||
commit.tree().unwrap().has_conflict()
|
commit.has_conflict().unwrap()
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue