Skip to content

Commit

Permalink
Add count_commits() function to the git module
Browse files Browse the repository at this point in the history
Add count_commits() function to the git module so that I could easily
count the commits from one oid upto another oid. This is going to be
needed to support figuring out the number of commits we are behind when
running the gps list command.

The approach I took was simply to use the git2::revwalk() function to
build an iterator to walk the tree from the from_oid to the to_oid and
then consume the iterator counting the up the number of commits.

This relates to issue #234.

<!-- ps-id: 6cbab0ea-3efd-4791-9821-bfbc637aaed1 -->
  • Loading branch information
drewdeponte committed Dec 26, 2023
1 parent 4d36674 commit 635af45
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/ps/private/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ mod config_get_bool;
mod config_get_error;
mod config_get_string;
mod config_get_to_option;
mod count_commits;
mod create_commit;
mod create_cwd_repo;
mod create_signed_commit;
Expand Down Expand Up @@ -71,6 +72,7 @@ pub use config_get_bool::*;
pub use config_get_error::*;
pub use config_get_string::*;
pub use config_get_to_option::*;
pub use count_commits::*;
pub use create_commit::*;
pub use create_cwd_repo::*;
pub use create_signed_commit::*;
Expand Down
45 changes: 45 additions & 0 deletions src/ps/private/git/count_commits.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use git2;
use std::result::Result;

#[derive(Debug)]
pub enum CountCommitsError {
UnhandledError(Box<dyn std::error::Error>),
}

impl std::fmt::Display for CountCommitsError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::UnhandledError(boxed_e) => write!(f, "{}", boxed_e),
}
}
}

impl From<git2::Error> for CountCommitsError {
fn from(e: git2::Error) -> Self {
Self::UnhandledError(e.into())
}
}

impl std::error::Error for CountCommitsError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::UnhandledError(boxed_e) => Some(boxed_e.as_ref()), // Self::MergeBase(e) => Some(e),
}
}
}

/// Returns count of commits between `from_oid` (inclusive) and `to_oid` (exclusive).
///
/// `to_oid` should be an ancestor of `from_oid`
pub fn count_commits(
repo: &git2::Repository,
from_oid: git2::Oid,
to_oid: git2::Oid,
) -> Result<usize, CountCommitsError> {
let mut rev_walk = repo.revwalk()?;
rev_walk.push(from_oid)?;
rev_walk.hide(to_oid)?;
rev_walk.set_sorting(git2::Sort::REVERSE)?;

Ok(rev_walk.count())
}

0 comments on commit 635af45

Please sign in to comment.