changeset_git/repository/
tag.rs1use crate::{Result, TagInfo};
2
3use super::Repository;
4
5impl Repository {
6 pub fn delete_tag(&self, name: &str) -> Result<bool> {
14 let refname = format!("refs/tags/{name}");
15 match self.inner.find_reference(&refname) {
16 Ok(mut reference) => {
17 reference.delete()?;
18 Ok(true)
19 }
20 Err(e) if e.code() == git2::ErrorCode::NotFound => Ok(false),
21 Err(e) => Err(e.into()),
22 }
23 }
24
25 pub fn create_tag(&self, name: &str, message: &str) -> Result<TagInfo> {
29 let head = self.inner.head()?.peel_to_commit()?;
30 let sig = self.inner.signature()?;
31
32 self.inner
33 .tag(name, head.as_object(), &sig, message, false)?;
34
35 Ok(TagInfo {
36 name: name.to_string(),
37 target_sha: head.id().to_string(),
38 })
39 }
40}
41
42#[cfg(test)]
43mod tests {
44 use super::super::tests::setup_test_repo;
45
46 #[test]
47 fn create_annotated_tag() -> anyhow::Result<()> {
48 let (_dir, repo) = setup_test_repo()?;
49
50 let tag_info = repo.create_tag("v1.0.0", "Release version 1.0.0")?;
51
52 assert_eq!(tag_info.name, "v1.0.0");
53
54 let head = repo.inner.head()?.peel_to_commit()?;
55 assert_eq!(tag_info.target_sha, head.id().to_string());
56
57 let tag = repo.inner.find_reference("refs/tags/v1.0.0")?;
58 assert!(tag.peel_to_tag().is_ok());
59
60 Ok(())
61 }
62
63 #[test]
64 fn create_tag_with_crate_prefix() -> anyhow::Result<()> {
65 let (_dir, repo) = setup_test_repo()?;
66
67 let tag_info = repo.create_tag("my-crate-v0.1.0", "Release my-crate version 0.1.0")?;
68
69 assert_eq!(tag_info.name, "my-crate-v0.1.0");
70
71 let tag = repo.inner.find_reference("refs/tags/my-crate-v0.1.0")?;
72 assert!(tag.peel_to_tag().is_ok());
73
74 Ok(())
75 }
76
77 #[test]
78 fn duplicate_tag_fails() -> anyhow::Result<()> {
79 let (_dir, repo) = setup_test_repo()?;
80
81 repo.create_tag("v1.0.0", "First tag")?;
82 let result = repo.create_tag("v1.0.0", "Duplicate tag");
83
84 assert!(result.is_err());
85
86 Ok(())
87 }
88
89 #[test]
90 fn delete_existing_tag_returns_true() -> anyhow::Result<()> {
91 let (_dir, repo) = setup_test_repo()?;
92
93 repo.create_tag("v1.0.0", "Tag to delete")?;
94 assert!(repo.inner.find_reference("refs/tags/v1.0.0").is_ok());
95
96 let deleted = repo.delete_tag("v1.0.0")?;
97
98 assert!(deleted);
99 assert!(repo.inner.find_reference("refs/tags/v1.0.0").is_err());
100
101 Ok(())
102 }
103
104 #[test]
105 fn delete_nonexistent_tag_returns_false() -> anyhow::Result<()> {
106 let (_dir, repo) = setup_test_repo()?;
107
108 let deleted = repo.delete_tag("nonexistent-tag")?;
109
110 assert!(!deleted);
111
112 Ok(())
113 }
114}