Skip to content

Commit f2540b5

Browse files
committed
feat: sort status tree by relevance
- sort order: current branch, then display_authors, then alphabetical
1 parent cad414d commit f2540b5

File tree

1 file changed

+49
-12
lines changed

1 file changed

+49
-12
lines changed

src/main.rs

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,31 @@ fn selection_marker() -> &'static str {
518518
}
519519
}
520520

521+
/// Check if a branch subtree contains the target branch or a display_author PR
522+
/// Returns (has_target_branch, has_display_author_pr)
523+
fn subtree_contains(
524+
branch: &Branch,
525+
target_branch: &str,
526+
display_authors: &[String],
527+
pr_cache: Option<&std::collections::HashMap<String, github::PullRequest>>,
528+
) -> (bool, bool) {
529+
// Check this branch
530+
let is_target = branch.name == target_branch;
531+
let has_author = pr_cache
532+
.and_then(|cache| cache.get(&branch.name))
533+
.map(|pr| display_authors.contains(&pr.user.login))
534+
.unwrap_or(false);
535+
536+
// Recursively check children
537+
let (child_has_target, child_has_author) = branch
538+
.branches
539+
.iter()
540+
.map(|b| subtree_contains(b, target_branch, display_authors, pr_cache))
541+
.fold((false, false), |(t1, a1), (t2, a2)| (t1 || t2, a1 || a2));
542+
543+
(is_target || child_has_target, has_author || child_has_author)
544+
}
545+
521546
#[allow(clippy::too_many_arguments)]
522547
fn recur_tree(
523548
git_repo: &GitRepo,
@@ -856,32 +881,44 @@ fn recur_tree(
856881
}
857882

858883
let mut branches_sorted = branch.branches.iter().collect::<Vec<_>>();
859-
// Pre-compute is_ancestor results to avoid repeated git merge-base calls during sorting
860-
let ancestor_cache: std::collections::HashMap<&str, bool> = branches_sorted
884+
885+
// Pre-compute subtree properties for sorting
886+
let subtree_cache: std::collections::HashMap<&str, (bool, bool)> = branches_sorted
861887
.iter()
862888
.map(|b| {
863889
(
864890
b.name.as_str(),
865-
git_repo.is_ancestor(&b.name, orig_branch).unwrap_or(false),
891+
subtree_contains(b, orig_branch, display_authors, pr_cache),
866892
)
867893
})
868894
.collect();
895+
869896
branches_sorted.sort_by(|&a, &b| {
870-
let a_is_ancestor = ancestor_cache
897+
let (a_has_current, a_has_author) = subtree_cache
871898
.get(a.name.as_str())
872899
.copied()
873-
.unwrap_or(false);
874-
let b_is_ancestor = ancestor_cache
900+
.unwrap_or((false, false));
901+
let (b_has_current, b_has_author) = subtree_cache
875902
.get(b.name.as_str())
876903
.copied()
877-
.unwrap_or(false);
878-
match (a_is_ancestor, b_is_ancestor) {
879-
(true, true) => a.name.cmp(&b.name),
880-
(true, false) => std::cmp::Ordering::Less,
881-
(false, true) => std::cmp::Ordering::Greater,
882-
(false, false) => a.name.cmp(&b.name),
904+
.unwrap_or((false, false));
905+
906+
// Priority 1: subtree contains current branch
907+
match (a_has_current, b_has_current) {
908+
(true, false) => return std::cmp::Ordering::Less,
909+
(false, true) => return std::cmp::Ordering::Greater,
910+
_ => {}
911+
}
912+
// Priority 2: subtree contains display_author PR
913+
match (a_has_author, b_has_author) {
914+
(true, false) => return std::cmp::Ordering::Less,
915+
(false, true) => return std::cmp::Ordering::Greater,
916+
_ => {}
883917
}
918+
// Priority 3: alphabetical
919+
a.name.cmp(&b.name)
884920
});
921+
885922
for child in branches_sorted {
886923
recur_tree(
887924
git_repo,

0 commit comments

Comments
 (0)