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