diff --git a/apps/servers/octopus/supergit/src/bin/test.rs b/apps/servers/octopus/supergit/src/bin/test.rs index b7dba0379df..cb21d5c2564 100644 --- a/apps/servers/octopus/supergit/src/bin/test.rs +++ b/apps/servers/octopus/supergit/src/bin/test.rs @@ -22,12 +22,12 @@ fn main() { let head = main.get_head(); let tree = head.get_tree(); - - println!( - "{:?}", - tree.history(main.get_all(), "Cargo.toml") - .into_iter() - .map(|c| c.summary()) - .collect::>() - ); + + // println!( + // "{:?}", + // tree.history(main.get_all(), "infra/libkookie/nixpkgs/nixos/modules/module-list.nix") + // .into_iter() + // .map(|c| c.summary()) + // .collect::>() + // ); } diff --git a/apps/servers/octopus/supergit/src/branch.rs b/apps/servers/octopus/supergit/src/branch.rs index 3261d23b917..6b838f4ff42 100644 --- a/apps/servers/octopus/supergit/src/branch.rs +++ b/apps/servers/octopus/supergit/src/branch.rs @@ -1,4 +1,5 @@ use crate::{Commit, HashId}; +use atomptr::AtomPtr; use git2::Repository; use std::{mem, sync::Arc}; @@ -124,6 +125,8 @@ impl Branch { /// handles. This means that without explicitly branching, this /// iterator is first-parent. pub struct BranchIter { + rec: AtomPtr, + splits: AtomPtr>, repo: Arc, curr: Option, limit: SegLimit, @@ -133,6 +136,8 @@ impl BranchIter { /// Create a new branch segment iterator fn new(repo: Arc, last: HashId, limit: SegLimit) -> Self { Self { + rec: AtomPtr::new(IterMode::FirstParent), + splits: AtomPtr::new(vec![]), repo, curr: Some(last), limit, @@ -214,6 +219,25 @@ impl Iterator for BranchIter { } } +/// Specify the mode of a branch iterator +/// +/// The default value is `FirstParent`, meaning that merged branches +/// will create a new `Branch` handle that the user must iterate +/// manually. +/// +/// This is a reasonable default, but means that history searches for +/// files become more tedious. To improve this use-case, iterators +/// can internally be set to change their iteration behaviour, meaning +/// that returned commits are always `BranchCommit::Commit`, and can +pub enum IterMode { + /// Default value, iterating only first-parent commits + FirstParent, + /// Iterate a branch to completion, before picking the next + DepthFirst, + /// Iterate branches as they come up + BreadthFirst, +} + /// the limit applied to a branch segment pub enum SegLimit { /// No limit, enumerating all children @@ -259,3 +283,35 @@ impl BranchCommit { } } } + +/// Additional iterator data +struct IterData { + splits: AtomPtr>, +} + +impl IterData { + fn new() -> Self { + Self { + splits: AtomPtr::new(vec![]), + } + } + + fn append(&self, id: HashId) { + let mut vec = (**self.splits.get_ref()).clone(); + let mut new = vec![id]; + new.append(&mut vec); + self.splits.swap(new); + } + + fn next(&self) -> Option { + let mut vec = (**self.splits.get_ref()).clone(); + let next = if vec.len() < 0 { + Some(vec.remove(0)) + } else { + None + }; + + self.splits.swap(vec); + next + } +}