diff --git a/asyncgit/src/error.rs b/asyncgit/src/error.rs index cd27e11622..e36040d814 100644 --- a/asyncgit/src/error.rs +++ b/asyncgit/src/error.rs @@ -17,7 +17,7 @@ pub enum GixError { /// #[error("gix::object::find::existing::with_conversion::Error error: {0}")] - ObjectFindExistingWithConversionError( + ObjectFindExistingWithConversion( #[from] gix::object::find::existing::with_conversion::Error, ), @@ -39,6 +39,14 @@ pub enum GixError { #[error("gix::reference::head_tree_id::Error error: {0}")] ReferenceHeadTreeId(#[from] gix::reference::head_tree_id::Error), + /// + #[error("gix::reference::iter::Error error: {0}")] + ReferenceIter(#[from] gix::reference::iter::Error), + + /// + #[error("gix::reference::iter::init::Error error: {0}")] + ReferenceIterInit(#[from] gix::reference::iter::init::Error), + /// #[error("gix::revision::walk error: {0}")] RevisionWalk(#[from] gix::revision::walk::Error), @@ -251,6 +259,18 @@ impl From for Error { } } +impl From for Error { + fn from(error: gix::reference::iter::Error) -> Self { + Self::Gix(GixError::from(error)) + } +} + +impl From for Error { + fn from(error: gix::reference::iter::init::Error) -> Self { + Self::Gix(GixError::from(error)) + } +} + impl From for Error { fn from(error: gix::revision::walk::Error) -> Self { Self::Gix(GixError::from(error)) diff --git a/asyncgit/src/sync/commits_info.rs b/asyncgit/src/sync/commits_info.rs index ce7c38c25c..0c31b4705b 100644 --- a/asyncgit/src/sync/commits_info.rs +++ b/asyncgit/src/sync/commits_info.rs @@ -96,6 +96,15 @@ impl From for CommitId { } } +impl From> for CommitId { + fn from(commit: gix::Commit<'_>) -> Self { + #[allow(clippy::expect_used)] + let oid = Oid::from_bytes(commit.id().as_bytes()).expect("`Oid::from_bytes(commit.id().as_bytes())` is expected to never fail"); + + Self::new(oid) + } +} + impl From for gix::ObjectId { fn from(id: CommitId) -> Self { Self::from_bytes_or_panic(id.0.as_bytes()) diff --git a/asyncgit/src/sync/tags.rs b/asyncgit/src/sync/tags.rs index fe7071db84..f2193b2193 100644 --- a/asyncgit/src/sync/tags.rs +++ b/asyncgit/src/sync/tags.rs @@ -1,13 +1,7 @@ use super::{get_commits_info, CommitId, RepoPath}; -use crate::{ - error::Result, - sync::{repository::repo, utils::bytes2string}, -}; +use crate::{error::Result, sync::repository::repo}; use scopetime::scope_time; -use std::{ - collections::{BTreeMap, HashMap, HashSet}, - ops::Not, -}; +use std::collections::{BTreeMap, HashMap, HashSet}; /// #[derive(Clone, Hash, PartialEq, Eq, Debug)] @@ -64,52 +58,29 @@ pub fn get_tags(repo_path: &RepoPath) -> Result { } }; - let repo = repo(repo_path)?; - - repo.tag_foreach(|id, name| { - if let Ok(name) = - // skip the `refs/tags/` part - String::from_utf8(name[10..name.len()].into()) - { - //NOTE: find_tag (using underlying git_tag_lookup) only - // works on annotated tags lightweight tags `id` already - // points to the target commit - // see https://github.com/libgit2/libgit2/issues/5586 - let commit = repo - .find_tag(id) - .and_then(|tag| tag.target()) - .and_then(|target| target.peel_to_commit()) - .map_or_else( - |_| { - if repo.find_commit(id).is_ok() { - Some(CommitId::new(id)) - } else { - None - } - }, - |commit| Some(CommitId::new(commit.id())), - ); - - let annotation = repo - .find_tag(id) - .ok() - .as_ref() - .and_then(git2::Tag::message_bytes) - .and_then(|msg| { - msg.is_empty() - .not() - .then(|| bytes2string(msg).ok()) - .flatten() - }); - - if let Some(commit) = commit { - adder(commit, Tag { name, annotation }); - } - - return true; + let gix_repo: gix::Repository = + gix::ThreadSafeRepository::discover_with_environment_overrides(repo_path.gitpath()) + .map(Into::into)?; + let platform = gix_repo.references()?; + for mut reference in (platform.tags()?).flatten() { + let commit = reference.peel_to_commit(); + let tag = reference.peel_to_tag(); + + if let Ok(commit) = commit { + let tag_ref = tag.as_ref().map(gix::Tag::decode); + + let name = match tag_ref { + Ok(Ok(tag)) => tag.name.to_string(), + _ => reference.name().shorten().to_string(), + }; + let annotation = match tag_ref { + Ok(Ok(tag)) => Some(tag.message.to_string()), + _ => None, + }; + + adder(commit.into(), Tag { name, annotation }); } - false - })?; + } Ok(res) }