From 24de93d8218fd1ab31a1265eee909a96b5d5aaa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20R=C3=BC=C3=9Fler?= Date: Mon, 9 Jun 2025 14:18:01 +0200 Subject: [PATCH 1/3] Use gitoxide in get_tags --- asyncgit/src/error.rs | 13 ++++++ asyncgit/src/sync/commits_info.rs | 9 ++++ asyncgit/src/sync/tags.rs | 77 ++++++++++--------------------- 3 files changed, 47 insertions(+), 52 deletions(-) diff --git a/asyncgit/src/error.rs b/asyncgit/src/error.rs index ffd0bd899b..aec564276d 100644 --- a/asyncgit/src/error.rs +++ b/asyncgit/src/error.rs @@ -159,6 +159,19 @@ pub enum Error { #[error("gix::worktree::open_index::Error error: {0}")] GixWorktreeOpenIndex( #[from] Box, + ) + + #[error("gix::reference::iter::Error error: {0}")] + GixReferenceIter(#[from] gix::reference::iter::Error), + + /// + #[error("gix::reference::iter::init::Error error: {0}")] + GixReferenceIterInit(#[from] gix::reference::iter::init::Error), + + /// + #[error("gix::reference::peel::to_kind::Error error: {0}")] + GixReferencePeelToKind( + #[from] gix::reference::peel::to_kind::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..40029a32e4 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,31 @@ 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() + 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().ok(); + let tag = reference.peel_to_tag().ok(); + let reference_name = reference.name().as_bstr(); + + if let Some(commit) = commit { + let name = tag .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; + .and_then(|tag| { + let tag_ref = tag.decode().ok(); + tag_ref.map(|tag_ref| tag_ref.name.to_string()) + }) + .unwrap_or_else(|| reference_name[10..].to_string()); + let annotation = tag.and_then(|tag| { + let tag_ref = tag.decode().ok(); + tag_ref.map(|tag_ref| tag_ref.message.to_string()) + }); + + adder(commit.into(), Tag { name, annotation }); } - false - })?; + } Ok(res) } From f71ccc13bc20f8d70f428ccc2a6e9a6aa1a60016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20R=C3=BC=C3=9Fler?= Date: Mon, 9 Jun 2025 15:37:09 +0200 Subject: [PATCH 2/3] Use reference.name().shorten() --- asyncgit/src/sync/tags.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/asyncgit/src/sync/tags.rs b/asyncgit/src/sync/tags.rs index 40029a32e4..bb720aeddb 100644 --- a/asyncgit/src/sync/tags.rs +++ b/asyncgit/src/sync/tags.rs @@ -65,7 +65,6 @@ pub fn get_tags(repo_path: &RepoPath) -> Result { for mut reference in (platform.tags()?).flatten() { let commit = reference.peel_to_commit().ok(); let tag = reference.peel_to_tag().ok(); - let reference_name = reference.name().as_bstr(); if let Some(commit) = commit { let name = tag @@ -74,7 +73,9 @@ pub fn get_tags(repo_path: &RepoPath) -> Result { let tag_ref = tag.decode().ok(); tag_ref.map(|tag_ref| tag_ref.name.to_string()) }) - .unwrap_or_else(|| reference_name[10..].to_string()); + .unwrap_or_else(|| { + reference.name().shorten().to_string() + }); let annotation = tag.and_then(|tag| { let tag_ref = tag.decode().ok(); tag_ref.map(|tag_ref| tag_ref.message.to_string()) From 1750d967e282d7cc233aca859452f09fbe642dab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20R=C3=BC=C3=9Fler?= Date: Mon, 9 Jun 2025 15:43:40 +0200 Subject: [PATCH 3/3] Call gix::Tag::decode only once --- asyncgit/src/sync/tags.rs | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/asyncgit/src/sync/tags.rs b/asyncgit/src/sync/tags.rs index bb720aeddb..f2193b2193 100644 --- a/asyncgit/src/sync/tags.rs +++ b/asyncgit/src/sync/tags.rs @@ -63,23 +63,20 @@ pub fn get_tags(repo_path: &RepoPath) -> Result { .map(Into::into)?; let platform = gix_repo.references()?; for mut reference in (platform.tags()?).flatten() { - let commit = reference.peel_to_commit().ok(); - let tag = reference.peel_to_tag().ok(); - - if let Some(commit) = commit { - let name = tag - .as_ref() - .and_then(|tag| { - let tag_ref = tag.decode().ok(); - tag_ref.map(|tag_ref| tag_ref.name.to_string()) - }) - .unwrap_or_else(|| { - reference.name().shorten().to_string() - }); - let annotation = tag.and_then(|tag| { - let tag_ref = tag.decode().ok(); - tag_ref.map(|tag_ref| tag_ref.message.to_string()) - }); + 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 }); }