use time::OffsetDateTime;
use crate::{error::Error, util::convert_git2_time, GitRepository};
#[derive(Debug, Clone)]
pub struct Tag {
pub id: String,
pub date: OffsetDateTime,
pub name: String,
pub name_full: String,
pub message: Option<String>,
pub commit_id: String,
}
impl PartialEq for Tag {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
impl Tag {
pub fn is_annotated(&self) -> bool {
self.message.is_some()
}
}
pub fn list_tags(repo: &GitRepository) -> Result<Vec<String>, Error> {
let tags = repo.tag_names(None)?;
let tags = tags
.into_iter()
.filter_map(|t| t.map(|s| s.to_string()))
.collect();
Ok(tags)
}
pub fn get_tag_refs(repo: &GitRepository) -> Result<Vec<Tag>, Error> {
let refs = repo.references()?;
let mut tags = vec![];
for res in refs {
let rf = res?;
let rf = rf.resolve()?;
let id = rf.target().unwrap().to_string();
let full_name = rf.name().unwrap_or("__invalid__").to_string();
let name = rf.shorthand().unwrap_or("__invalid__").to_string();
if !full_name.starts_with("refs/tags/") {
continue;
}
let tag = rf.peel_to_tag().ok();
let tag_message = tag.map(|t| t.message().unwrap_or("__invalid__").trim().to_string());
let commit = rf.peel_to_commit()?;
let commit_id = commit.id().to_string();
let date = convert_git2_time(commit.time())?;
tags.push({
Tag {
id,
date,
name,
name_full: full_name,
message: tag_message,
commit_id,
}
})
}
Ok(tags)
}
pub fn set_annotated_tag(repo: &GitRepository, tag: &str, message: &str) -> Result<(), Error> {
let head_commit = repo.head()?.peel_to_commit()?;
let tagger = repo.signature()?;
let _oid = repo.tag(tag, head_commit.as_object(), &tagger, message, false)?;
Ok(())
}
#[cfg(test)]
mod tests {
use crate::repo::discover_repo;
use super::*;
#[test]
fn test_tags_simple() {
let cwd = std::env::current_dir().unwrap();
let repo = discover_repo(&cwd).unwrap();
let tags = list_tags(&repo).unwrap();
for tag in tags {
eprintln!("{tag}")
}
}
#[test]
fn test_tags_refs() {
let cwd = std::env::current_dir().unwrap();
let repo = discover_repo(&cwd).unwrap();
let tags = get_tag_refs(&repo).unwrap();
for tag in tags {
eprintln!("{}: {} ({})", tag.id, tag.name, tag.commit_id)
}
}
}