From 49cd6a75e904d6b76e0648ebd0cf31f995c6341a 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 | 14 ++++++ asyncgit/src/sync/commits_info.rs | 9 ++++ asyncgit/src/sync/tags.rs | 77 ++++++++++--------------------- 3 files changed, 48 insertions(+), 52 deletions(-) diff --git a/asyncgit/src/error.rs b/asyncgit/src/error.rs index 1578ed1e50..9513ab48ab 100644 --- a/asyncgit/src/error.rs +++ b/asyncgit/src/error.rs @@ -123,6 +123,20 @@ pub enum Error { #[from] gix::object::find::existing::with_conversion::Error, ), + /// + #[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, + ), + /// #[error("amend error: config commit.gpgsign=true detected.\ngpg signing is not supported for amending non-last commits")] SignAmendNonLastCommit, diff --git a/asyncgit/src/sync/commits_info.rs b/asyncgit/src/sync/commits_info.rs index c00ddcba64..349123a58f 100644 --- a/asyncgit/src/sync/commits_info.rs +++ b/asyncgit/src/sync/commits_info.rs @@ -93,6 +93,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 7ac44f1fae27715aef50a06e3bfb01e259c5f6eb 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 3e1c48f756d6440d03deda873f40226c4dcafdda 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 }); }