|
|
@ -1,4 +1,5 @@ |
|
|
|
use crate::{Commit, HashId}; |
|
|
|
use crate::{Commit, HashId}; |
|
|
|
|
|
|
|
use atomptr::AtomPtr; |
|
|
|
use git2::Repository; |
|
|
|
use git2::Repository; |
|
|
|
use std::{mem, sync::Arc}; |
|
|
|
use std::{mem, sync::Arc}; |
|
|
|
|
|
|
|
|
|
|
@ -124,6 +125,8 @@ impl Branch { |
|
|
|
/// handles. This means that without explicitly branching, this
|
|
|
|
/// handles. This means that without explicitly branching, this
|
|
|
|
/// iterator is first-parent.
|
|
|
|
/// iterator is first-parent.
|
|
|
|
pub struct BranchIter { |
|
|
|
pub struct BranchIter { |
|
|
|
|
|
|
|
rec: AtomPtr<IterMode>, |
|
|
|
|
|
|
|
splits: AtomPtr<Vec<HashId>>, |
|
|
|
repo: Arc<Repository>, |
|
|
|
repo: Arc<Repository>, |
|
|
|
curr: Option<HashId>, |
|
|
|
curr: Option<HashId>, |
|
|
|
limit: SegLimit, |
|
|
|
limit: SegLimit, |
|
|
@ -133,6 +136,8 @@ impl BranchIter { |
|
|
|
/// Create a new branch segment iterator
|
|
|
|
/// Create a new branch segment iterator
|
|
|
|
fn new(repo: Arc<Repository>, last: HashId, limit: SegLimit) -> Self { |
|
|
|
fn new(repo: Arc<Repository>, last: HashId, limit: SegLimit) -> Self { |
|
|
|
Self { |
|
|
|
Self { |
|
|
|
|
|
|
|
rec: AtomPtr::new(IterMode::FirstParent), |
|
|
|
|
|
|
|
splits: AtomPtr::new(vec![]), |
|
|
|
repo, |
|
|
|
repo, |
|
|
|
curr: Some(last), |
|
|
|
curr: Some(last), |
|
|
|
limit, |
|
|
|
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
|
|
|
|
/// the limit applied to a branch segment
|
|
|
|
pub enum SegLimit { |
|
|
|
pub enum SegLimit { |
|
|
|
/// No limit, enumerating all children
|
|
|
|
/// No limit, enumerating all children
|
|
|
@ -259,3 +283,35 @@ impl BranchCommit { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Additional iterator data
|
|
|
|
|
|
|
|
struct IterData { |
|
|
|
|
|
|
|
splits: AtomPtr<Vec<HashId>>, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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<HashId> { |
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|