pub struct TagList { /* private fields */ }
Expand description
A collection of tags with efficient iteration and filtering methods
Implementations§
Source§impl TagList
impl TagList
Sourcepub fn iter(&self) -> impl Iterator<Item = &Tag> + '_
pub fn iter(&self) -> impl Iterator<Item = &Tag> + '_
Get an iterator over all tags
Examples found in repository?
examples/tag_operations.rs (line 131)
16fn main() -> Result<()> {
17 println!("Rustic Git - Tag Operations Example\n");
18
19 // Use a temporary directory for this example
20 let repo_path = env::temp_dir().join("rustic_git_tag_example");
21
22 // Clean up any previous run
23 if repo_path.exists() {
24 fs::remove_dir_all(&repo_path).expect("Failed to clean up previous example");
25 }
26
27 println!("Initializing repository at: {}", repo_path.display());
28
29 // Initialize repository and configure user
30 let repo = Repository::init(&repo_path, false)?;
31 repo.config()
32 .set_user("Tag Demo User", "tags@example.com")?;
33
34 // Create some commits to tag
35 println!("\nCreating initial commits...");
36
37 // First commit
38 fs::write(
39 repo_path.join("README.md"),
40 "# Tag Demo Project\n\nDemonstrating Git tag operations.\n",
41 )?;
42 repo.add(&["README.md"])?;
43 let first_commit_hash = repo.commit("Initial commit: Add README")?;
44 println!("Created commit: {}", first_commit_hash.short());
45
46 // Second commit
47 fs::create_dir_all(repo_path.join("src"))?;
48 fs::write(
49 repo_path.join("src/main.rs"),
50 "fn main() {\n println!(\"Hello, tags!\");\n}\n",
51 )?;
52 repo.add(&["src/main.rs"])?;
53 let second_commit_hash = repo.commit("Add main.rs with hello world")?;
54 println!("Created commit: {}", second_commit_hash.short());
55
56 // Third commit
57 fs::write(
58 repo_path.join("src/lib.rs"),
59 "//! Tag demo library\n\npub fn greet(name: &str) -> String {\n format!(\"Hello, {}!\", name)\n}\n",
60 )?;
61 repo.add(&["src/lib.rs"])?;
62 let third_commit_hash = repo.commit("Add library with greet function")?;
63 println!("Created commit: {}", third_commit_hash.short());
64
65 // Demonstrate tag creation
66 println!("\n=== Creating Tags ===");
67
68 // Create lightweight tags
69 println!("\n1. Creating lightweight tags:");
70
71 let v0_1_0 = repo.create_tag("v0.1.0", Some(&first_commit_hash))?;
72 println!(
73 "Created lightweight tag: {} -> {} ({})",
74 v0_1_0.name,
75 v0_1_0.hash.short(),
76 v0_1_0.tag_type
77 );
78
79 let v0_2_0 = repo.create_tag("v0.2.0", Some(&second_commit_hash))?;
80 println!(
81 "Created lightweight tag: {} -> {} ({})",
82 v0_2_0.name,
83 v0_2_0.hash.short(),
84 v0_2_0.tag_type
85 );
86
87 // Create annotated tags
88 println!("\n2. Creating annotated tags:");
89
90 let options =
91 TagOptions::new().with_message("First stable release with basic functionality".to_string());
92 let v1_0_0 = repo.create_tag_with_options("v1.0.0", Some(&third_commit_hash), options)?;
93 println!(
94 "Created annotated tag: {} -> {} ({})",
95 v1_0_0.name,
96 v1_0_0.hash.short(),
97 v1_0_0.tag_type
98 );
99 if let Some(message) = &v1_0_0.message {
100 println!(" Message: {}", message);
101 }
102
103 // Tag current HEAD
104 let latest_options = TagOptions::new().with_message("Latest development version".to_string());
105 let latest_tag = repo.create_tag_with_options("latest", None, latest_options)?;
106 println!(
107 "Created annotated tag on HEAD: {} -> {} ({})",
108 latest_tag.name,
109 latest_tag.hash.short(),
110 latest_tag.tag_type
111 );
112
113 // Create some feature tags
114 println!("\n3. Creating feature and release candidate tags:");
115
116 let feature_options = TagOptions::new().with_message("Feature branch snapshot".to_string());
117 repo.create_tag_with_options("feature/demo", None, feature_options)?;
118
119 let rc_options = TagOptions::new().with_message("Release candidate for v1.1.0".to_string());
120 repo.create_tag_with_options("v1.1.0-rc1", None, rc_options)?;
121
122 // Create a couple more version tags
123 repo.create_tag("v0.3.0", None)?;
124 repo.create_tag("v0.9.0", None)?;
125
126 // Demonstrate tag listing and filtering
127 println!("\n=== Tag Listing and Filtering ===");
128
129 let tags = repo.tags()?;
130 println!("\nAll tags ({} total):", tags.len());
131 for tag in tags.iter() {
132 let type_marker = match tag.tag_type {
133 TagType::Lightweight => "L",
134 TagType::Annotated => "A",
135 };
136 println!(" [{}] {} -> {}", type_marker, tag.name, tag.hash.short());
137 if let Some(message) = &tag.message {
138 println!(" Message: {}", message.lines().next().unwrap_or(""));
139 }
140 }
141
142 // Filter by type
143 println!("\nLightweight tags ({} total):", tags.lightweight_count());
144 for tag in tags.lightweight() {
145 println!(" {} -> {}", tag.name, tag.hash.short());
146 }
147
148 println!("\nAnnotated tags ({} total):", tags.annotated_count());
149 for tag in tags.annotated() {
150 println!(" {} -> {}", tag.name, tag.hash.short());
151 if let Some(message) = &tag.message {
152 println!(" Message: {}", message.lines().next().unwrap_or(""));
153 }
154 }
155
156 // Search and filtering
157 println!("\n=== Tag Searching ===");
158
159 // Find specific tag
160 if let Some(tag) = tags.find("v1.0.0") {
161 println!("\nFound tag 'v1.0.0':");
162 println!(" Type: {}", tag.tag_type);
163 println!(" Hash: {}", tag.hash.short());
164 if let Some(message) = &tag.message {
165 println!(" Message: {}", message);
166 }
167 }
168
169 // Find version tags
170 let version_tags: Vec<_> = tags.find_containing("v").collect();
171 println!(
172 "\nVersion tags (containing 'v'): {} found",
173 version_tags.len()
174 );
175 for tag in &version_tags {
176 println!(" {}", tag.name);
177 }
178
179 // Find release candidates
180 let rc_tags: Vec<_> = tags.find_containing("rc").collect();
181 println!("\nRelease candidate tags: {} found", rc_tags.len());
182 for tag in &rc_tags {
183 println!(" {}", tag.name);
184 }
185
186 // Find tags for specific commit
187 let tags_for_third_commit: Vec<_> = tags.for_commit(&third_commit_hash).collect();
188 println!(
189 "\nTags pointing to commit {}: {} found",
190 third_commit_hash.short(),
191 tags_for_third_commit.len()
192 );
193 for tag in &tags_for_third_commit {
194 println!(" {}", tag.name);
195 }
196
197 // Demonstrate tag details
198 println!("\n=== Tag Details ===");
199
200 let detailed_tag = repo.show_tag("v1.0.0")?;
201 println!("\nDetailed information for 'v1.0.0':");
202 println!(" Name: {}", detailed_tag.name);
203 println!(" Type: {}", detailed_tag.tag_type);
204 println!(" Commit: {}", detailed_tag.hash);
205 println!(" Short hash: {}", detailed_tag.hash.short());
206
207 if let Some(message) = &detailed_tag.message {
208 println!(" Message: {}", message);
209 }
210
211 if let Some(tagger) = &detailed_tag.tagger {
212 println!(" Tagger: {}", tagger);
213 println!(
214 " Tagged at: {}",
215 tagger.timestamp.format("%Y-%m-%d %H:%M:%S UTC")
216 );
217 }
218
219 if let Some(timestamp) = &detailed_tag.timestamp {
220 println!(" Timestamp: {}", timestamp.format("%Y-%m-%d %H:%M:%S UTC"));
221 }
222
223 // Demonstrate tag operations
224 println!("\n=== Tag Operations ===");
225
226 // Create and force overwrite a tag
227 println!("\n1. Testing tag overwrite:");
228
229 // This should fail (tag already exists)
230 match repo.create_tag("latest", None) {
231 Ok(_) => println!(" ERROR: Should have failed to create existing tag"),
232 Err(e) => println!(" Expected error creating existing tag: {}", e),
233 }
234
235 // Force overwrite
236 let force_options = TagOptions::new()
237 .with_force()
238 .with_message("Forcefully updated latest tag".to_string());
239
240 match repo.create_tag_with_options("latest", None, force_options) {
241 Ok(tag) => println!(" Successfully force-created tag: {}", tag.name),
242 Err(e) => println!(" Error force-creating tag: {}", e),
243 }
244
245 // Tag deletion
246 println!("\n2. Testing tag deletion:");
247
248 // Create a temporary tag to delete
249 repo.create_tag("temp-tag", None)?;
250 println!(" Created temporary tag: temp-tag");
251
252 // Verify it exists
253 let tags_before = repo.tags()?;
254 let temp_exists_before = tags_before.find("temp-tag").is_some();
255 println!(" Temp tag exists before deletion: {}", temp_exists_before);
256
257 // Delete it
258 repo.delete_tag("temp-tag")?;
259 println!(" Deleted temp-tag");
260
261 // Verify it's gone
262 let tags_after = repo.tags()?;
263 let temp_exists_after = tags_after.find("temp-tag").is_some();
264 println!(" Temp tag exists after deletion: {}", temp_exists_after);
265
266 // Summary
267 println!("\n=== Summary ===");
268 let final_tags = repo.tags()?;
269 println!("\nFinal repository state:");
270 println!(" Total tags: {}", final_tags.len());
271 println!(" Lightweight tags: {}", final_tags.lightweight_count());
272 println!(" Annotated tags: {}", final_tags.annotated_count());
273
274 println!("\nTag creation options demonstrated:");
275 println!(" ✓ Lightweight tags (simple references)");
276 println!(" ✓ Annotated tags (with messages and metadata)");
277 println!(" ✓ Tags on specific commits");
278 println!(" ✓ Tags on current HEAD");
279 println!(" ✓ Force tag creation/overwrite");
280
281 println!("\nTag listing and filtering demonstrated:");
282 println!(" ✓ List all tags");
283 println!(" ✓ Filter by tag type (lightweight/annotated)");
284 println!(" ✓ Search by name patterns");
285 println!(" ✓ Find tags by commit hash");
286 println!(" ✓ Show detailed tag information");
287
288 println!("\nTag management demonstrated:");
289 println!(" ✓ Tag creation with options");
290 println!(" ✓ Tag deletion");
291 println!(" ✓ Error handling for duplicate tags");
292
293 // Clean up
294 println!("\nCleaning up example repository...");
295 fs::remove_dir_all(&repo_path)?;
296 println!("Tag operations example completed successfully!");
297
298 Ok(())
299}
Sourcepub fn lightweight(&self) -> impl Iterator<Item = &Tag> + '_
pub fn lightweight(&self) -> impl Iterator<Item = &Tag> + '_
Get an iterator over lightweight tags only
Examples found in repository?
examples/tag_operations.rs (line 144)
16fn main() -> Result<()> {
17 println!("Rustic Git - Tag Operations Example\n");
18
19 // Use a temporary directory for this example
20 let repo_path = env::temp_dir().join("rustic_git_tag_example");
21
22 // Clean up any previous run
23 if repo_path.exists() {
24 fs::remove_dir_all(&repo_path).expect("Failed to clean up previous example");
25 }
26
27 println!("Initializing repository at: {}", repo_path.display());
28
29 // Initialize repository and configure user
30 let repo = Repository::init(&repo_path, false)?;
31 repo.config()
32 .set_user("Tag Demo User", "tags@example.com")?;
33
34 // Create some commits to tag
35 println!("\nCreating initial commits...");
36
37 // First commit
38 fs::write(
39 repo_path.join("README.md"),
40 "# Tag Demo Project\n\nDemonstrating Git tag operations.\n",
41 )?;
42 repo.add(&["README.md"])?;
43 let first_commit_hash = repo.commit("Initial commit: Add README")?;
44 println!("Created commit: {}", first_commit_hash.short());
45
46 // Second commit
47 fs::create_dir_all(repo_path.join("src"))?;
48 fs::write(
49 repo_path.join("src/main.rs"),
50 "fn main() {\n println!(\"Hello, tags!\");\n}\n",
51 )?;
52 repo.add(&["src/main.rs"])?;
53 let second_commit_hash = repo.commit("Add main.rs with hello world")?;
54 println!("Created commit: {}", second_commit_hash.short());
55
56 // Third commit
57 fs::write(
58 repo_path.join("src/lib.rs"),
59 "//! Tag demo library\n\npub fn greet(name: &str) -> String {\n format!(\"Hello, {}!\", name)\n}\n",
60 )?;
61 repo.add(&["src/lib.rs"])?;
62 let third_commit_hash = repo.commit("Add library with greet function")?;
63 println!("Created commit: {}", third_commit_hash.short());
64
65 // Demonstrate tag creation
66 println!("\n=== Creating Tags ===");
67
68 // Create lightweight tags
69 println!("\n1. Creating lightweight tags:");
70
71 let v0_1_0 = repo.create_tag("v0.1.0", Some(&first_commit_hash))?;
72 println!(
73 "Created lightweight tag: {} -> {} ({})",
74 v0_1_0.name,
75 v0_1_0.hash.short(),
76 v0_1_0.tag_type
77 );
78
79 let v0_2_0 = repo.create_tag("v0.2.0", Some(&second_commit_hash))?;
80 println!(
81 "Created lightweight tag: {} -> {} ({})",
82 v0_2_0.name,
83 v0_2_0.hash.short(),
84 v0_2_0.tag_type
85 );
86
87 // Create annotated tags
88 println!("\n2. Creating annotated tags:");
89
90 let options =
91 TagOptions::new().with_message("First stable release with basic functionality".to_string());
92 let v1_0_0 = repo.create_tag_with_options("v1.0.0", Some(&third_commit_hash), options)?;
93 println!(
94 "Created annotated tag: {} -> {} ({})",
95 v1_0_0.name,
96 v1_0_0.hash.short(),
97 v1_0_0.tag_type
98 );
99 if let Some(message) = &v1_0_0.message {
100 println!(" Message: {}", message);
101 }
102
103 // Tag current HEAD
104 let latest_options = TagOptions::new().with_message("Latest development version".to_string());
105 let latest_tag = repo.create_tag_with_options("latest", None, latest_options)?;
106 println!(
107 "Created annotated tag on HEAD: {} -> {} ({})",
108 latest_tag.name,
109 latest_tag.hash.short(),
110 latest_tag.tag_type
111 );
112
113 // Create some feature tags
114 println!("\n3. Creating feature and release candidate tags:");
115
116 let feature_options = TagOptions::new().with_message("Feature branch snapshot".to_string());
117 repo.create_tag_with_options("feature/demo", None, feature_options)?;
118
119 let rc_options = TagOptions::new().with_message("Release candidate for v1.1.0".to_string());
120 repo.create_tag_with_options("v1.1.0-rc1", None, rc_options)?;
121
122 // Create a couple more version tags
123 repo.create_tag("v0.3.0", None)?;
124 repo.create_tag("v0.9.0", None)?;
125
126 // Demonstrate tag listing and filtering
127 println!("\n=== Tag Listing and Filtering ===");
128
129 let tags = repo.tags()?;
130 println!("\nAll tags ({} total):", tags.len());
131 for tag in tags.iter() {
132 let type_marker = match tag.tag_type {
133 TagType::Lightweight => "L",
134 TagType::Annotated => "A",
135 };
136 println!(" [{}] {} -> {}", type_marker, tag.name, tag.hash.short());
137 if let Some(message) = &tag.message {
138 println!(" Message: {}", message.lines().next().unwrap_or(""));
139 }
140 }
141
142 // Filter by type
143 println!("\nLightweight tags ({} total):", tags.lightweight_count());
144 for tag in tags.lightweight() {
145 println!(" {} -> {}", tag.name, tag.hash.short());
146 }
147
148 println!("\nAnnotated tags ({} total):", tags.annotated_count());
149 for tag in tags.annotated() {
150 println!(" {} -> {}", tag.name, tag.hash.short());
151 if let Some(message) = &tag.message {
152 println!(" Message: {}", message.lines().next().unwrap_or(""));
153 }
154 }
155
156 // Search and filtering
157 println!("\n=== Tag Searching ===");
158
159 // Find specific tag
160 if let Some(tag) = tags.find("v1.0.0") {
161 println!("\nFound tag 'v1.0.0':");
162 println!(" Type: {}", tag.tag_type);
163 println!(" Hash: {}", tag.hash.short());
164 if let Some(message) = &tag.message {
165 println!(" Message: {}", message);
166 }
167 }
168
169 // Find version tags
170 let version_tags: Vec<_> = tags.find_containing("v").collect();
171 println!(
172 "\nVersion tags (containing 'v'): {} found",
173 version_tags.len()
174 );
175 for tag in &version_tags {
176 println!(" {}", tag.name);
177 }
178
179 // Find release candidates
180 let rc_tags: Vec<_> = tags.find_containing("rc").collect();
181 println!("\nRelease candidate tags: {} found", rc_tags.len());
182 for tag in &rc_tags {
183 println!(" {}", tag.name);
184 }
185
186 // Find tags for specific commit
187 let tags_for_third_commit: Vec<_> = tags.for_commit(&third_commit_hash).collect();
188 println!(
189 "\nTags pointing to commit {}: {} found",
190 third_commit_hash.short(),
191 tags_for_third_commit.len()
192 );
193 for tag in &tags_for_third_commit {
194 println!(" {}", tag.name);
195 }
196
197 // Demonstrate tag details
198 println!("\n=== Tag Details ===");
199
200 let detailed_tag = repo.show_tag("v1.0.0")?;
201 println!("\nDetailed information for 'v1.0.0':");
202 println!(" Name: {}", detailed_tag.name);
203 println!(" Type: {}", detailed_tag.tag_type);
204 println!(" Commit: {}", detailed_tag.hash);
205 println!(" Short hash: {}", detailed_tag.hash.short());
206
207 if let Some(message) = &detailed_tag.message {
208 println!(" Message: {}", message);
209 }
210
211 if let Some(tagger) = &detailed_tag.tagger {
212 println!(" Tagger: {}", tagger);
213 println!(
214 " Tagged at: {}",
215 tagger.timestamp.format("%Y-%m-%d %H:%M:%S UTC")
216 );
217 }
218
219 if let Some(timestamp) = &detailed_tag.timestamp {
220 println!(" Timestamp: {}", timestamp.format("%Y-%m-%d %H:%M:%S UTC"));
221 }
222
223 // Demonstrate tag operations
224 println!("\n=== Tag Operations ===");
225
226 // Create and force overwrite a tag
227 println!("\n1. Testing tag overwrite:");
228
229 // This should fail (tag already exists)
230 match repo.create_tag("latest", None) {
231 Ok(_) => println!(" ERROR: Should have failed to create existing tag"),
232 Err(e) => println!(" Expected error creating existing tag: {}", e),
233 }
234
235 // Force overwrite
236 let force_options = TagOptions::new()
237 .with_force()
238 .with_message("Forcefully updated latest tag".to_string());
239
240 match repo.create_tag_with_options("latest", None, force_options) {
241 Ok(tag) => println!(" Successfully force-created tag: {}", tag.name),
242 Err(e) => println!(" Error force-creating tag: {}", e),
243 }
244
245 // Tag deletion
246 println!("\n2. Testing tag deletion:");
247
248 // Create a temporary tag to delete
249 repo.create_tag("temp-tag", None)?;
250 println!(" Created temporary tag: temp-tag");
251
252 // Verify it exists
253 let tags_before = repo.tags()?;
254 let temp_exists_before = tags_before.find("temp-tag").is_some();
255 println!(" Temp tag exists before deletion: {}", temp_exists_before);
256
257 // Delete it
258 repo.delete_tag("temp-tag")?;
259 println!(" Deleted temp-tag");
260
261 // Verify it's gone
262 let tags_after = repo.tags()?;
263 let temp_exists_after = tags_after.find("temp-tag").is_some();
264 println!(" Temp tag exists after deletion: {}", temp_exists_after);
265
266 // Summary
267 println!("\n=== Summary ===");
268 let final_tags = repo.tags()?;
269 println!("\nFinal repository state:");
270 println!(" Total tags: {}", final_tags.len());
271 println!(" Lightweight tags: {}", final_tags.lightweight_count());
272 println!(" Annotated tags: {}", final_tags.annotated_count());
273
274 println!("\nTag creation options demonstrated:");
275 println!(" ✓ Lightweight tags (simple references)");
276 println!(" ✓ Annotated tags (with messages and metadata)");
277 println!(" ✓ Tags on specific commits");
278 println!(" ✓ Tags on current HEAD");
279 println!(" ✓ Force tag creation/overwrite");
280
281 println!("\nTag listing and filtering demonstrated:");
282 println!(" ✓ List all tags");
283 println!(" ✓ Filter by tag type (lightweight/annotated)");
284 println!(" ✓ Search by name patterns");
285 println!(" ✓ Find tags by commit hash");
286 println!(" ✓ Show detailed tag information");
287
288 println!("\nTag management demonstrated:");
289 println!(" ✓ Tag creation with options");
290 println!(" ✓ Tag deletion");
291 println!(" ✓ Error handling for duplicate tags");
292
293 // Clean up
294 println!("\nCleaning up example repository...");
295 fs::remove_dir_all(&repo_path)?;
296 println!("Tag operations example completed successfully!");
297
298 Ok(())
299}
Sourcepub fn annotated(&self) -> impl Iterator<Item = &Tag> + '_
pub fn annotated(&self) -> impl Iterator<Item = &Tag> + '_
Get an iterator over annotated tags only
Examples found in repository?
examples/tag_operations.rs (line 149)
16fn main() -> Result<()> {
17 println!("Rustic Git - Tag Operations Example\n");
18
19 // Use a temporary directory for this example
20 let repo_path = env::temp_dir().join("rustic_git_tag_example");
21
22 // Clean up any previous run
23 if repo_path.exists() {
24 fs::remove_dir_all(&repo_path).expect("Failed to clean up previous example");
25 }
26
27 println!("Initializing repository at: {}", repo_path.display());
28
29 // Initialize repository and configure user
30 let repo = Repository::init(&repo_path, false)?;
31 repo.config()
32 .set_user("Tag Demo User", "tags@example.com")?;
33
34 // Create some commits to tag
35 println!("\nCreating initial commits...");
36
37 // First commit
38 fs::write(
39 repo_path.join("README.md"),
40 "# Tag Demo Project\n\nDemonstrating Git tag operations.\n",
41 )?;
42 repo.add(&["README.md"])?;
43 let first_commit_hash = repo.commit("Initial commit: Add README")?;
44 println!("Created commit: {}", first_commit_hash.short());
45
46 // Second commit
47 fs::create_dir_all(repo_path.join("src"))?;
48 fs::write(
49 repo_path.join("src/main.rs"),
50 "fn main() {\n println!(\"Hello, tags!\");\n}\n",
51 )?;
52 repo.add(&["src/main.rs"])?;
53 let second_commit_hash = repo.commit("Add main.rs with hello world")?;
54 println!("Created commit: {}", second_commit_hash.short());
55
56 // Third commit
57 fs::write(
58 repo_path.join("src/lib.rs"),
59 "//! Tag demo library\n\npub fn greet(name: &str) -> String {\n format!(\"Hello, {}!\", name)\n}\n",
60 )?;
61 repo.add(&["src/lib.rs"])?;
62 let third_commit_hash = repo.commit("Add library with greet function")?;
63 println!("Created commit: {}", third_commit_hash.short());
64
65 // Demonstrate tag creation
66 println!("\n=== Creating Tags ===");
67
68 // Create lightweight tags
69 println!("\n1. Creating lightweight tags:");
70
71 let v0_1_0 = repo.create_tag("v0.1.0", Some(&first_commit_hash))?;
72 println!(
73 "Created lightweight tag: {} -> {} ({})",
74 v0_1_0.name,
75 v0_1_0.hash.short(),
76 v0_1_0.tag_type
77 );
78
79 let v0_2_0 = repo.create_tag("v0.2.0", Some(&second_commit_hash))?;
80 println!(
81 "Created lightweight tag: {} -> {} ({})",
82 v0_2_0.name,
83 v0_2_0.hash.short(),
84 v0_2_0.tag_type
85 );
86
87 // Create annotated tags
88 println!("\n2. Creating annotated tags:");
89
90 let options =
91 TagOptions::new().with_message("First stable release with basic functionality".to_string());
92 let v1_0_0 = repo.create_tag_with_options("v1.0.0", Some(&third_commit_hash), options)?;
93 println!(
94 "Created annotated tag: {} -> {} ({})",
95 v1_0_0.name,
96 v1_0_0.hash.short(),
97 v1_0_0.tag_type
98 );
99 if let Some(message) = &v1_0_0.message {
100 println!(" Message: {}", message);
101 }
102
103 // Tag current HEAD
104 let latest_options = TagOptions::new().with_message("Latest development version".to_string());
105 let latest_tag = repo.create_tag_with_options("latest", None, latest_options)?;
106 println!(
107 "Created annotated tag on HEAD: {} -> {} ({})",
108 latest_tag.name,
109 latest_tag.hash.short(),
110 latest_tag.tag_type
111 );
112
113 // Create some feature tags
114 println!("\n3. Creating feature and release candidate tags:");
115
116 let feature_options = TagOptions::new().with_message("Feature branch snapshot".to_string());
117 repo.create_tag_with_options("feature/demo", None, feature_options)?;
118
119 let rc_options = TagOptions::new().with_message("Release candidate for v1.1.0".to_string());
120 repo.create_tag_with_options("v1.1.0-rc1", None, rc_options)?;
121
122 // Create a couple more version tags
123 repo.create_tag("v0.3.0", None)?;
124 repo.create_tag("v0.9.0", None)?;
125
126 // Demonstrate tag listing and filtering
127 println!("\n=== Tag Listing and Filtering ===");
128
129 let tags = repo.tags()?;
130 println!("\nAll tags ({} total):", tags.len());
131 for tag in tags.iter() {
132 let type_marker = match tag.tag_type {
133 TagType::Lightweight => "L",
134 TagType::Annotated => "A",
135 };
136 println!(" [{}] {} -> {}", type_marker, tag.name, tag.hash.short());
137 if let Some(message) = &tag.message {
138 println!(" Message: {}", message.lines().next().unwrap_or(""));
139 }
140 }
141
142 // Filter by type
143 println!("\nLightweight tags ({} total):", tags.lightweight_count());
144 for tag in tags.lightweight() {
145 println!(" {} -> {}", tag.name, tag.hash.short());
146 }
147
148 println!("\nAnnotated tags ({} total):", tags.annotated_count());
149 for tag in tags.annotated() {
150 println!(" {} -> {}", tag.name, tag.hash.short());
151 if let Some(message) = &tag.message {
152 println!(" Message: {}", message.lines().next().unwrap_or(""));
153 }
154 }
155
156 // Search and filtering
157 println!("\n=== Tag Searching ===");
158
159 // Find specific tag
160 if let Some(tag) = tags.find("v1.0.0") {
161 println!("\nFound tag 'v1.0.0':");
162 println!(" Type: {}", tag.tag_type);
163 println!(" Hash: {}", tag.hash.short());
164 if let Some(message) = &tag.message {
165 println!(" Message: {}", message);
166 }
167 }
168
169 // Find version tags
170 let version_tags: Vec<_> = tags.find_containing("v").collect();
171 println!(
172 "\nVersion tags (containing 'v'): {} found",
173 version_tags.len()
174 );
175 for tag in &version_tags {
176 println!(" {}", tag.name);
177 }
178
179 // Find release candidates
180 let rc_tags: Vec<_> = tags.find_containing("rc").collect();
181 println!("\nRelease candidate tags: {} found", rc_tags.len());
182 for tag in &rc_tags {
183 println!(" {}", tag.name);
184 }
185
186 // Find tags for specific commit
187 let tags_for_third_commit: Vec<_> = tags.for_commit(&third_commit_hash).collect();
188 println!(
189 "\nTags pointing to commit {}: {} found",
190 third_commit_hash.short(),
191 tags_for_third_commit.len()
192 );
193 for tag in &tags_for_third_commit {
194 println!(" {}", tag.name);
195 }
196
197 // Demonstrate tag details
198 println!("\n=== Tag Details ===");
199
200 let detailed_tag = repo.show_tag("v1.0.0")?;
201 println!("\nDetailed information for 'v1.0.0':");
202 println!(" Name: {}", detailed_tag.name);
203 println!(" Type: {}", detailed_tag.tag_type);
204 println!(" Commit: {}", detailed_tag.hash);
205 println!(" Short hash: {}", detailed_tag.hash.short());
206
207 if let Some(message) = &detailed_tag.message {
208 println!(" Message: {}", message);
209 }
210
211 if let Some(tagger) = &detailed_tag.tagger {
212 println!(" Tagger: {}", tagger);
213 println!(
214 " Tagged at: {}",
215 tagger.timestamp.format("%Y-%m-%d %H:%M:%S UTC")
216 );
217 }
218
219 if let Some(timestamp) = &detailed_tag.timestamp {
220 println!(" Timestamp: {}", timestamp.format("%Y-%m-%d %H:%M:%S UTC"));
221 }
222
223 // Demonstrate tag operations
224 println!("\n=== Tag Operations ===");
225
226 // Create and force overwrite a tag
227 println!("\n1. Testing tag overwrite:");
228
229 // This should fail (tag already exists)
230 match repo.create_tag("latest", None) {
231 Ok(_) => println!(" ERROR: Should have failed to create existing tag"),
232 Err(e) => println!(" Expected error creating existing tag: {}", e),
233 }
234
235 // Force overwrite
236 let force_options = TagOptions::new()
237 .with_force()
238 .with_message("Forcefully updated latest tag".to_string());
239
240 match repo.create_tag_with_options("latest", None, force_options) {
241 Ok(tag) => println!(" Successfully force-created tag: {}", tag.name),
242 Err(e) => println!(" Error force-creating tag: {}", e),
243 }
244
245 // Tag deletion
246 println!("\n2. Testing tag deletion:");
247
248 // Create a temporary tag to delete
249 repo.create_tag("temp-tag", None)?;
250 println!(" Created temporary tag: temp-tag");
251
252 // Verify it exists
253 let tags_before = repo.tags()?;
254 let temp_exists_before = tags_before.find("temp-tag").is_some();
255 println!(" Temp tag exists before deletion: {}", temp_exists_before);
256
257 // Delete it
258 repo.delete_tag("temp-tag")?;
259 println!(" Deleted temp-tag");
260
261 // Verify it's gone
262 let tags_after = repo.tags()?;
263 let temp_exists_after = tags_after.find("temp-tag").is_some();
264 println!(" Temp tag exists after deletion: {}", temp_exists_after);
265
266 // Summary
267 println!("\n=== Summary ===");
268 let final_tags = repo.tags()?;
269 println!("\nFinal repository state:");
270 println!(" Total tags: {}", final_tags.len());
271 println!(" Lightweight tags: {}", final_tags.lightweight_count());
272 println!(" Annotated tags: {}", final_tags.annotated_count());
273
274 println!("\nTag creation options demonstrated:");
275 println!(" ✓ Lightweight tags (simple references)");
276 println!(" ✓ Annotated tags (with messages and metadata)");
277 println!(" ✓ Tags on specific commits");
278 println!(" ✓ Tags on current HEAD");
279 println!(" ✓ Force tag creation/overwrite");
280
281 println!("\nTag listing and filtering demonstrated:");
282 println!(" ✓ List all tags");
283 println!(" ✓ Filter by tag type (lightweight/annotated)");
284 println!(" ✓ Search by name patterns");
285 println!(" ✓ Find tags by commit hash");
286 println!(" ✓ Show detailed tag information");
287
288 println!("\nTag management demonstrated:");
289 println!(" ✓ Tag creation with options");
290 println!(" ✓ Tag deletion");
291 println!(" ✓ Error handling for duplicate tags");
292
293 // Clean up
294 println!("\nCleaning up example repository...");
295 fs::remove_dir_all(&repo_path)?;
296 println!("Tag operations example completed successfully!");
297
298 Ok(())
299}
Sourcepub fn find(&self, name: &str) -> Option<&Tag>
pub fn find(&self, name: &str) -> Option<&Tag>
Find a tag by exact name
Examples found in repository?
examples/tag_operations.rs (line 160)
16fn main() -> Result<()> {
17 println!("Rustic Git - Tag Operations Example\n");
18
19 // Use a temporary directory for this example
20 let repo_path = env::temp_dir().join("rustic_git_tag_example");
21
22 // Clean up any previous run
23 if repo_path.exists() {
24 fs::remove_dir_all(&repo_path).expect("Failed to clean up previous example");
25 }
26
27 println!("Initializing repository at: {}", repo_path.display());
28
29 // Initialize repository and configure user
30 let repo = Repository::init(&repo_path, false)?;
31 repo.config()
32 .set_user("Tag Demo User", "tags@example.com")?;
33
34 // Create some commits to tag
35 println!("\nCreating initial commits...");
36
37 // First commit
38 fs::write(
39 repo_path.join("README.md"),
40 "# Tag Demo Project\n\nDemonstrating Git tag operations.\n",
41 )?;
42 repo.add(&["README.md"])?;
43 let first_commit_hash = repo.commit("Initial commit: Add README")?;
44 println!("Created commit: {}", first_commit_hash.short());
45
46 // Second commit
47 fs::create_dir_all(repo_path.join("src"))?;
48 fs::write(
49 repo_path.join("src/main.rs"),
50 "fn main() {\n println!(\"Hello, tags!\");\n}\n",
51 )?;
52 repo.add(&["src/main.rs"])?;
53 let second_commit_hash = repo.commit("Add main.rs with hello world")?;
54 println!("Created commit: {}", second_commit_hash.short());
55
56 // Third commit
57 fs::write(
58 repo_path.join("src/lib.rs"),
59 "//! Tag demo library\n\npub fn greet(name: &str) -> String {\n format!(\"Hello, {}!\", name)\n}\n",
60 )?;
61 repo.add(&["src/lib.rs"])?;
62 let third_commit_hash = repo.commit("Add library with greet function")?;
63 println!("Created commit: {}", third_commit_hash.short());
64
65 // Demonstrate tag creation
66 println!("\n=== Creating Tags ===");
67
68 // Create lightweight tags
69 println!("\n1. Creating lightweight tags:");
70
71 let v0_1_0 = repo.create_tag("v0.1.0", Some(&first_commit_hash))?;
72 println!(
73 "Created lightweight tag: {} -> {} ({})",
74 v0_1_0.name,
75 v0_1_0.hash.short(),
76 v0_1_0.tag_type
77 );
78
79 let v0_2_0 = repo.create_tag("v0.2.0", Some(&second_commit_hash))?;
80 println!(
81 "Created lightweight tag: {} -> {} ({})",
82 v0_2_0.name,
83 v0_2_0.hash.short(),
84 v0_2_0.tag_type
85 );
86
87 // Create annotated tags
88 println!("\n2. Creating annotated tags:");
89
90 let options =
91 TagOptions::new().with_message("First stable release with basic functionality".to_string());
92 let v1_0_0 = repo.create_tag_with_options("v1.0.0", Some(&third_commit_hash), options)?;
93 println!(
94 "Created annotated tag: {} -> {} ({})",
95 v1_0_0.name,
96 v1_0_0.hash.short(),
97 v1_0_0.tag_type
98 );
99 if let Some(message) = &v1_0_0.message {
100 println!(" Message: {}", message);
101 }
102
103 // Tag current HEAD
104 let latest_options = TagOptions::new().with_message("Latest development version".to_string());
105 let latest_tag = repo.create_tag_with_options("latest", None, latest_options)?;
106 println!(
107 "Created annotated tag on HEAD: {} -> {} ({})",
108 latest_tag.name,
109 latest_tag.hash.short(),
110 latest_tag.tag_type
111 );
112
113 // Create some feature tags
114 println!("\n3. Creating feature and release candidate tags:");
115
116 let feature_options = TagOptions::new().with_message("Feature branch snapshot".to_string());
117 repo.create_tag_with_options("feature/demo", None, feature_options)?;
118
119 let rc_options = TagOptions::new().with_message("Release candidate for v1.1.0".to_string());
120 repo.create_tag_with_options("v1.1.0-rc1", None, rc_options)?;
121
122 // Create a couple more version tags
123 repo.create_tag("v0.3.0", None)?;
124 repo.create_tag("v0.9.0", None)?;
125
126 // Demonstrate tag listing and filtering
127 println!("\n=== Tag Listing and Filtering ===");
128
129 let tags = repo.tags()?;
130 println!("\nAll tags ({} total):", tags.len());
131 for tag in tags.iter() {
132 let type_marker = match tag.tag_type {
133 TagType::Lightweight => "L",
134 TagType::Annotated => "A",
135 };
136 println!(" [{}] {} -> {}", type_marker, tag.name, tag.hash.short());
137 if let Some(message) = &tag.message {
138 println!(" Message: {}", message.lines().next().unwrap_or(""));
139 }
140 }
141
142 // Filter by type
143 println!("\nLightweight tags ({} total):", tags.lightweight_count());
144 for tag in tags.lightweight() {
145 println!(" {} -> {}", tag.name, tag.hash.short());
146 }
147
148 println!("\nAnnotated tags ({} total):", tags.annotated_count());
149 for tag in tags.annotated() {
150 println!(" {} -> {}", tag.name, tag.hash.short());
151 if let Some(message) = &tag.message {
152 println!(" Message: {}", message.lines().next().unwrap_or(""));
153 }
154 }
155
156 // Search and filtering
157 println!("\n=== Tag Searching ===");
158
159 // Find specific tag
160 if let Some(tag) = tags.find("v1.0.0") {
161 println!("\nFound tag 'v1.0.0':");
162 println!(" Type: {}", tag.tag_type);
163 println!(" Hash: {}", tag.hash.short());
164 if let Some(message) = &tag.message {
165 println!(" Message: {}", message);
166 }
167 }
168
169 // Find version tags
170 let version_tags: Vec<_> = tags.find_containing("v").collect();
171 println!(
172 "\nVersion tags (containing 'v'): {} found",
173 version_tags.len()
174 );
175 for tag in &version_tags {
176 println!(" {}", tag.name);
177 }
178
179 // Find release candidates
180 let rc_tags: Vec<_> = tags.find_containing("rc").collect();
181 println!("\nRelease candidate tags: {} found", rc_tags.len());
182 for tag in &rc_tags {
183 println!(" {}", tag.name);
184 }
185
186 // Find tags for specific commit
187 let tags_for_third_commit: Vec<_> = tags.for_commit(&third_commit_hash).collect();
188 println!(
189 "\nTags pointing to commit {}: {} found",
190 third_commit_hash.short(),
191 tags_for_third_commit.len()
192 );
193 for tag in &tags_for_third_commit {
194 println!(" {}", tag.name);
195 }
196
197 // Demonstrate tag details
198 println!("\n=== Tag Details ===");
199
200 let detailed_tag = repo.show_tag("v1.0.0")?;
201 println!("\nDetailed information for 'v1.0.0':");
202 println!(" Name: {}", detailed_tag.name);
203 println!(" Type: {}", detailed_tag.tag_type);
204 println!(" Commit: {}", detailed_tag.hash);
205 println!(" Short hash: {}", detailed_tag.hash.short());
206
207 if let Some(message) = &detailed_tag.message {
208 println!(" Message: {}", message);
209 }
210
211 if let Some(tagger) = &detailed_tag.tagger {
212 println!(" Tagger: {}", tagger);
213 println!(
214 " Tagged at: {}",
215 tagger.timestamp.format("%Y-%m-%d %H:%M:%S UTC")
216 );
217 }
218
219 if let Some(timestamp) = &detailed_tag.timestamp {
220 println!(" Timestamp: {}", timestamp.format("%Y-%m-%d %H:%M:%S UTC"));
221 }
222
223 // Demonstrate tag operations
224 println!("\n=== Tag Operations ===");
225
226 // Create and force overwrite a tag
227 println!("\n1. Testing tag overwrite:");
228
229 // This should fail (tag already exists)
230 match repo.create_tag("latest", None) {
231 Ok(_) => println!(" ERROR: Should have failed to create existing tag"),
232 Err(e) => println!(" Expected error creating existing tag: {}", e),
233 }
234
235 // Force overwrite
236 let force_options = TagOptions::new()
237 .with_force()
238 .with_message("Forcefully updated latest tag".to_string());
239
240 match repo.create_tag_with_options("latest", None, force_options) {
241 Ok(tag) => println!(" Successfully force-created tag: {}", tag.name),
242 Err(e) => println!(" Error force-creating tag: {}", e),
243 }
244
245 // Tag deletion
246 println!("\n2. Testing tag deletion:");
247
248 // Create a temporary tag to delete
249 repo.create_tag("temp-tag", None)?;
250 println!(" Created temporary tag: temp-tag");
251
252 // Verify it exists
253 let tags_before = repo.tags()?;
254 let temp_exists_before = tags_before.find("temp-tag").is_some();
255 println!(" Temp tag exists before deletion: {}", temp_exists_before);
256
257 // Delete it
258 repo.delete_tag("temp-tag")?;
259 println!(" Deleted temp-tag");
260
261 // Verify it's gone
262 let tags_after = repo.tags()?;
263 let temp_exists_after = tags_after.find("temp-tag").is_some();
264 println!(" Temp tag exists after deletion: {}", temp_exists_after);
265
266 // Summary
267 println!("\n=== Summary ===");
268 let final_tags = repo.tags()?;
269 println!("\nFinal repository state:");
270 println!(" Total tags: {}", final_tags.len());
271 println!(" Lightweight tags: {}", final_tags.lightweight_count());
272 println!(" Annotated tags: {}", final_tags.annotated_count());
273
274 println!("\nTag creation options demonstrated:");
275 println!(" ✓ Lightweight tags (simple references)");
276 println!(" ✓ Annotated tags (with messages and metadata)");
277 println!(" ✓ Tags on specific commits");
278 println!(" ✓ Tags on current HEAD");
279 println!(" ✓ Force tag creation/overwrite");
280
281 println!("\nTag listing and filtering demonstrated:");
282 println!(" ✓ List all tags");
283 println!(" ✓ Filter by tag type (lightweight/annotated)");
284 println!(" ✓ Search by name patterns");
285 println!(" ✓ Find tags by commit hash");
286 println!(" ✓ Show detailed tag information");
287
288 println!("\nTag management demonstrated:");
289 println!(" ✓ Tag creation with options");
290 println!(" ✓ Tag deletion");
291 println!(" ✓ Error handling for duplicate tags");
292
293 // Clean up
294 println!("\nCleaning up example repository...");
295 fs::remove_dir_all(&repo_path)?;
296 println!("Tag operations example completed successfully!");
297
298 Ok(())
299}
Sourcepub fn find_containing<'a>(
&'a self,
substring: &'a str,
) -> impl Iterator<Item = &'a Tag> + 'a
pub fn find_containing<'a>( &'a self, substring: &'a str, ) -> impl Iterator<Item = &'a Tag> + 'a
Find tags whose names contain the given substring
Examples found in repository?
examples/tag_operations.rs (line 170)
16fn main() -> Result<()> {
17 println!("Rustic Git - Tag Operations Example\n");
18
19 // Use a temporary directory for this example
20 let repo_path = env::temp_dir().join("rustic_git_tag_example");
21
22 // Clean up any previous run
23 if repo_path.exists() {
24 fs::remove_dir_all(&repo_path).expect("Failed to clean up previous example");
25 }
26
27 println!("Initializing repository at: {}", repo_path.display());
28
29 // Initialize repository and configure user
30 let repo = Repository::init(&repo_path, false)?;
31 repo.config()
32 .set_user("Tag Demo User", "tags@example.com")?;
33
34 // Create some commits to tag
35 println!("\nCreating initial commits...");
36
37 // First commit
38 fs::write(
39 repo_path.join("README.md"),
40 "# Tag Demo Project\n\nDemonstrating Git tag operations.\n",
41 )?;
42 repo.add(&["README.md"])?;
43 let first_commit_hash = repo.commit("Initial commit: Add README")?;
44 println!("Created commit: {}", first_commit_hash.short());
45
46 // Second commit
47 fs::create_dir_all(repo_path.join("src"))?;
48 fs::write(
49 repo_path.join("src/main.rs"),
50 "fn main() {\n println!(\"Hello, tags!\");\n}\n",
51 )?;
52 repo.add(&["src/main.rs"])?;
53 let second_commit_hash = repo.commit("Add main.rs with hello world")?;
54 println!("Created commit: {}", second_commit_hash.short());
55
56 // Third commit
57 fs::write(
58 repo_path.join("src/lib.rs"),
59 "//! Tag demo library\n\npub fn greet(name: &str) -> String {\n format!(\"Hello, {}!\", name)\n}\n",
60 )?;
61 repo.add(&["src/lib.rs"])?;
62 let third_commit_hash = repo.commit("Add library with greet function")?;
63 println!("Created commit: {}", third_commit_hash.short());
64
65 // Demonstrate tag creation
66 println!("\n=== Creating Tags ===");
67
68 // Create lightweight tags
69 println!("\n1. Creating lightweight tags:");
70
71 let v0_1_0 = repo.create_tag("v0.1.0", Some(&first_commit_hash))?;
72 println!(
73 "Created lightweight tag: {} -> {} ({})",
74 v0_1_0.name,
75 v0_1_0.hash.short(),
76 v0_1_0.tag_type
77 );
78
79 let v0_2_0 = repo.create_tag("v0.2.0", Some(&second_commit_hash))?;
80 println!(
81 "Created lightweight tag: {} -> {} ({})",
82 v0_2_0.name,
83 v0_2_0.hash.short(),
84 v0_2_0.tag_type
85 );
86
87 // Create annotated tags
88 println!("\n2. Creating annotated tags:");
89
90 let options =
91 TagOptions::new().with_message("First stable release with basic functionality".to_string());
92 let v1_0_0 = repo.create_tag_with_options("v1.0.0", Some(&third_commit_hash), options)?;
93 println!(
94 "Created annotated tag: {} -> {} ({})",
95 v1_0_0.name,
96 v1_0_0.hash.short(),
97 v1_0_0.tag_type
98 );
99 if let Some(message) = &v1_0_0.message {
100 println!(" Message: {}", message);
101 }
102
103 // Tag current HEAD
104 let latest_options = TagOptions::new().with_message("Latest development version".to_string());
105 let latest_tag = repo.create_tag_with_options("latest", None, latest_options)?;
106 println!(
107 "Created annotated tag on HEAD: {} -> {} ({})",
108 latest_tag.name,
109 latest_tag.hash.short(),
110 latest_tag.tag_type
111 );
112
113 // Create some feature tags
114 println!("\n3. Creating feature and release candidate tags:");
115
116 let feature_options = TagOptions::new().with_message("Feature branch snapshot".to_string());
117 repo.create_tag_with_options("feature/demo", None, feature_options)?;
118
119 let rc_options = TagOptions::new().with_message("Release candidate for v1.1.0".to_string());
120 repo.create_tag_with_options("v1.1.0-rc1", None, rc_options)?;
121
122 // Create a couple more version tags
123 repo.create_tag("v0.3.0", None)?;
124 repo.create_tag("v0.9.0", None)?;
125
126 // Demonstrate tag listing and filtering
127 println!("\n=== Tag Listing and Filtering ===");
128
129 let tags = repo.tags()?;
130 println!("\nAll tags ({} total):", tags.len());
131 for tag in tags.iter() {
132 let type_marker = match tag.tag_type {
133 TagType::Lightweight => "L",
134 TagType::Annotated => "A",
135 };
136 println!(" [{}] {} -> {}", type_marker, tag.name, tag.hash.short());
137 if let Some(message) = &tag.message {
138 println!(" Message: {}", message.lines().next().unwrap_or(""));
139 }
140 }
141
142 // Filter by type
143 println!("\nLightweight tags ({} total):", tags.lightweight_count());
144 for tag in tags.lightweight() {
145 println!(" {} -> {}", tag.name, tag.hash.short());
146 }
147
148 println!("\nAnnotated tags ({} total):", tags.annotated_count());
149 for tag in tags.annotated() {
150 println!(" {} -> {}", tag.name, tag.hash.short());
151 if let Some(message) = &tag.message {
152 println!(" Message: {}", message.lines().next().unwrap_or(""));
153 }
154 }
155
156 // Search and filtering
157 println!("\n=== Tag Searching ===");
158
159 // Find specific tag
160 if let Some(tag) = tags.find("v1.0.0") {
161 println!("\nFound tag 'v1.0.0':");
162 println!(" Type: {}", tag.tag_type);
163 println!(" Hash: {}", tag.hash.short());
164 if let Some(message) = &tag.message {
165 println!(" Message: {}", message);
166 }
167 }
168
169 // Find version tags
170 let version_tags: Vec<_> = tags.find_containing("v").collect();
171 println!(
172 "\nVersion tags (containing 'v'): {} found",
173 version_tags.len()
174 );
175 for tag in &version_tags {
176 println!(" {}", tag.name);
177 }
178
179 // Find release candidates
180 let rc_tags: Vec<_> = tags.find_containing("rc").collect();
181 println!("\nRelease candidate tags: {} found", rc_tags.len());
182 for tag in &rc_tags {
183 println!(" {}", tag.name);
184 }
185
186 // Find tags for specific commit
187 let tags_for_third_commit: Vec<_> = tags.for_commit(&third_commit_hash).collect();
188 println!(
189 "\nTags pointing to commit {}: {} found",
190 third_commit_hash.short(),
191 tags_for_third_commit.len()
192 );
193 for tag in &tags_for_third_commit {
194 println!(" {}", tag.name);
195 }
196
197 // Demonstrate tag details
198 println!("\n=== Tag Details ===");
199
200 let detailed_tag = repo.show_tag("v1.0.0")?;
201 println!("\nDetailed information for 'v1.0.0':");
202 println!(" Name: {}", detailed_tag.name);
203 println!(" Type: {}", detailed_tag.tag_type);
204 println!(" Commit: {}", detailed_tag.hash);
205 println!(" Short hash: {}", detailed_tag.hash.short());
206
207 if let Some(message) = &detailed_tag.message {
208 println!(" Message: {}", message);
209 }
210
211 if let Some(tagger) = &detailed_tag.tagger {
212 println!(" Tagger: {}", tagger);
213 println!(
214 " Tagged at: {}",
215 tagger.timestamp.format("%Y-%m-%d %H:%M:%S UTC")
216 );
217 }
218
219 if let Some(timestamp) = &detailed_tag.timestamp {
220 println!(" Timestamp: {}", timestamp.format("%Y-%m-%d %H:%M:%S UTC"));
221 }
222
223 // Demonstrate tag operations
224 println!("\n=== Tag Operations ===");
225
226 // Create and force overwrite a tag
227 println!("\n1. Testing tag overwrite:");
228
229 // This should fail (tag already exists)
230 match repo.create_tag("latest", None) {
231 Ok(_) => println!(" ERROR: Should have failed to create existing tag"),
232 Err(e) => println!(" Expected error creating existing tag: {}", e),
233 }
234
235 // Force overwrite
236 let force_options = TagOptions::new()
237 .with_force()
238 .with_message("Forcefully updated latest tag".to_string());
239
240 match repo.create_tag_with_options("latest", None, force_options) {
241 Ok(tag) => println!(" Successfully force-created tag: {}", tag.name),
242 Err(e) => println!(" Error force-creating tag: {}", e),
243 }
244
245 // Tag deletion
246 println!("\n2. Testing tag deletion:");
247
248 // Create a temporary tag to delete
249 repo.create_tag("temp-tag", None)?;
250 println!(" Created temporary tag: temp-tag");
251
252 // Verify it exists
253 let tags_before = repo.tags()?;
254 let temp_exists_before = tags_before.find("temp-tag").is_some();
255 println!(" Temp tag exists before deletion: {}", temp_exists_before);
256
257 // Delete it
258 repo.delete_tag("temp-tag")?;
259 println!(" Deleted temp-tag");
260
261 // Verify it's gone
262 let tags_after = repo.tags()?;
263 let temp_exists_after = tags_after.find("temp-tag").is_some();
264 println!(" Temp tag exists after deletion: {}", temp_exists_after);
265
266 // Summary
267 println!("\n=== Summary ===");
268 let final_tags = repo.tags()?;
269 println!("\nFinal repository state:");
270 println!(" Total tags: {}", final_tags.len());
271 println!(" Lightweight tags: {}", final_tags.lightweight_count());
272 println!(" Annotated tags: {}", final_tags.annotated_count());
273
274 println!("\nTag creation options demonstrated:");
275 println!(" ✓ Lightweight tags (simple references)");
276 println!(" ✓ Annotated tags (with messages and metadata)");
277 println!(" ✓ Tags on specific commits");
278 println!(" ✓ Tags on current HEAD");
279 println!(" ✓ Force tag creation/overwrite");
280
281 println!("\nTag listing and filtering demonstrated:");
282 println!(" ✓ List all tags");
283 println!(" ✓ Filter by tag type (lightweight/annotated)");
284 println!(" ✓ Search by name patterns");
285 println!(" ✓ Find tags by commit hash");
286 println!(" ✓ Show detailed tag information");
287
288 println!("\nTag management demonstrated:");
289 println!(" ✓ Tag creation with options");
290 println!(" ✓ Tag deletion");
291 println!(" ✓ Error handling for duplicate tags");
292
293 // Clean up
294 println!("\nCleaning up example repository...");
295 fs::remove_dir_all(&repo_path)?;
296 println!("Tag operations example completed successfully!");
297
298 Ok(())
299}
Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Get the total number of tags
Examples found in repository?
examples/tag_operations.rs (line 130)
16fn main() -> Result<()> {
17 println!("Rustic Git - Tag Operations Example\n");
18
19 // Use a temporary directory for this example
20 let repo_path = env::temp_dir().join("rustic_git_tag_example");
21
22 // Clean up any previous run
23 if repo_path.exists() {
24 fs::remove_dir_all(&repo_path).expect("Failed to clean up previous example");
25 }
26
27 println!("Initializing repository at: {}", repo_path.display());
28
29 // Initialize repository and configure user
30 let repo = Repository::init(&repo_path, false)?;
31 repo.config()
32 .set_user("Tag Demo User", "tags@example.com")?;
33
34 // Create some commits to tag
35 println!("\nCreating initial commits...");
36
37 // First commit
38 fs::write(
39 repo_path.join("README.md"),
40 "# Tag Demo Project\n\nDemonstrating Git tag operations.\n",
41 )?;
42 repo.add(&["README.md"])?;
43 let first_commit_hash = repo.commit("Initial commit: Add README")?;
44 println!("Created commit: {}", first_commit_hash.short());
45
46 // Second commit
47 fs::create_dir_all(repo_path.join("src"))?;
48 fs::write(
49 repo_path.join("src/main.rs"),
50 "fn main() {\n println!(\"Hello, tags!\");\n}\n",
51 )?;
52 repo.add(&["src/main.rs"])?;
53 let second_commit_hash = repo.commit("Add main.rs with hello world")?;
54 println!("Created commit: {}", second_commit_hash.short());
55
56 // Third commit
57 fs::write(
58 repo_path.join("src/lib.rs"),
59 "//! Tag demo library\n\npub fn greet(name: &str) -> String {\n format!(\"Hello, {}!\", name)\n}\n",
60 )?;
61 repo.add(&["src/lib.rs"])?;
62 let third_commit_hash = repo.commit("Add library with greet function")?;
63 println!("Created commit: {}", third_commit_hash.short());
64
65 // Demonstrate tag creation
66 println!("\n=== Creating Tags ===");
67
68 // Create lightweight tags
69 println!("\n1. Creating lightweight tags:");
70
71 let v0_1_0 = repo.create_tag("v0.1.0", Some(&first_commit_hash))?;
72 println!(
73 "Created lightweight tag: {} -> {} ({})",
74 v0_1_0.name,
75 v0_1_0.hash.short(),
76 v0_1_0.tag_type
77 );
78
79 let v0_2_0 = repo.create_tag("v0.2.0", Some(&second_commit_hash))?;
80 println!(
81 "Created lightweight tag: {} -> {} ({})",
82 v0_2_0.name,
83 v0_2_0.hash.short(),
84 v0_2_0.tag_type
85 );
86
87 // Create annotated tags
88 println!("\n2. Creating annotated tags:");
89
90 let options =
91 TagOptions::new().with_message("First stable release with basic functionality".to_string());
92 let v1_0_0 = repo.create_tag_with_options("v1.0.0", Some(&third_commit_hash), options)?;
93 println!(
94 "Created annotated tag: {} -> {} ({})",
95 v1_0_0.name,
96 v1_0_0.hash.short(),
97 v1_0_0.tag_type
98 );
99 if let Some(message) = &v1_0_0.message {
100 println!(" Message: {}", message);
101 }
102
103 // Tag current HEAD
104 let latest_options = TagOptions::new().with_message("Latest development version".to_string());
105 let latest_tag = repo.create_tag_with_options("latest", None, latest_options)?;
106 println!(
107 "Created annotated tag on HEAD: {} -> {} ({})",
108 latest_tag.name,
109 latest_tag.hash.short(),
110 latest_tag.tag_type
111 );
112
113 // Create some feature tags
114 println!("\n3. Creating feature and release candidate tags:");
115
116 let feature_options = TagOptions::new().with_message("Feature branch snapshot".to_string());
117 repo.create_tag_with_options("feature/demo", None, feature_options)?;
118
119 let rc_options = TagOptions::new().with_message("Release candidate for v1.1.0".to_string());
120 repo.create_tag_with_options("v1.1.0-rc1", None, rc_options)?;
121
122 // Create a couple more version tags
123 repo.create_tag("v0.3.0", None)?;
124 repo.create_tag("v0.9.0", None)?;
125
126 // Demonstrate tag listing and filtering
127 println!("\n=== Tag Listing and Filtering ===");
128
129 let tags = repo.tags()?;
130 println!("\nAll tags ({} total):", tags.len());
131 for tag in tags.iter() {
132 let type_marker = match tag.tag_type {
133 TagType::Lightweight => "L",
134 TagType::Annotated => "A",
135 };
136 println!(" [{}] {} -> {}", type_marker, tag.name, tag.hash.short());
137 if let Some(message) = &tag.message {
138 println!(" Message: {}", message.lines().next().unwrap_or(""));
139 }
140 }
141
142 // Filter by type
143 println!("\nLightweight tags ({} total):", tags.lightweight_count());
144 for tag in tags.lightweight() {
145 println!(" {} -> {}", tag.name, tag.hash.short());
146 }
147
148 println!("\nAnnotated tags ({} total):", tags.annotated_count());
149 for tag in tags.annotated() {
150 println!(" {} -> {}", tag.name, tag.hash.short());
151 if let Some(message) = &tag.message {
152 println!(" Message: {}", message.lines().next().unwrap_or(""));
153 }
154 }
155
156 // Search and filtering
157 println!("\n=== Tag Searching ===");
158
159 // Find specific tag
160 if let Some(tag) = tags.find("v1.0.0") {
161 println!("\nFound tag 'v1.0.0':");
162 println!(" Type: {}", tag.tag_type);
163 println!(" Hash: {}", tag.hash.short());
164 if let Some(message) = &tag.message {
165 println!(" Message: {}", message);
166 }
167 }
168
169 // Find version tags
170 let version_tags: Vec<_> = tags.find_containing("v").collect();
171 println!(
172 "\nVersion tags (containing 'v'): {} found",
173 version_tags.len()
174 );
175 for tag in &version_tags {
176 println!(" {}", tag.name);
177 }
178
179 // Find release candidates
180 let rc_tags: Vec<_> = tags.find_containing("rc").collect();
181 println!("\nRelease candidate tags: {} found", rc_tags.len());
182 for tag in &rc_tags {
183 println!(" {}", tag.name);
184 }
185
186 // Find tags for specific commit
187 let tags_for_third_commit: Vec<_> = tags.for_commit(&third_commit_hash).collect();
188 println!(
189 "\nTags pointing to commit {}: {} found",
190 third_commit_hash.short(),
191 tags_for_third_commit.len()
192 );
193 for tag in &tags_for_third_commit {
194 println!(" {}", tag.name);
195 }
196
197 // Demonstrate tag details
198 println!("\n=== Tag Details ===");
199
200 let detailed_tag = repo.show_tag("v1.0.0")?;
201 println!("\nDetailed information for 'v1.0.0':");
202 println!(" Name: {}", detailed_tag.name);
203 println!(" Type: {}", detailed_tag.tag_type);
204 println!(" Commit: {}", detailed_tag.hash);
205 println!(" Short hash: {}", detailed_tag.hash.short());
206
207 if let Some(message) = &detailed_tag.message {
208 println!(" Message: {}", message);
209 }
210
211 if let Some(tagger) = &detailed_tag.tagger {
212 println!(" Tagger: {}", tagger);
213 println!(
214 " Tagged at: {}",
215 tagger.timestamp.format("%Y-%m-%d %H:%M:%S UTC")
216 );
217 }
218
219 if let Some(timestamp) = &detailed_tag.timestamp {
220 println!(" Timestamp: {}", timestamp.format("%Y-%m-%d %H:%M:%S UTC"));
221 }
222
223 // Demonstrate tag operations
224 println!("\n=== Tag Operations ===");
225
226 // Create and force overwrite a tag
227 println!("\n1. Testing tag overwrite:");
228
229 // This should fail (tag already exists)
230 match repo.create_tag("latest", None) {
231 Ok(_) => println!(" ERROR: Should have failed to create existing tag"),
232 Err(e) => println!(" Expected error creating existing tag: {}", e),
233 }
234
235 // Force overwrite
236 let force_options = TagOptions::new()
237 .with_force()
238 .with_message("Forcefully updated latest tag".to_string());
239
240 match repo.create_tag_with_options("latest", None, force_options) {
241 Ok(tag) => println!(" Successfully force-created tag: {}", tag.name),
242 Err(e) => println!(" Error force-creating tag: {}", e),
243 }
244
245 // Tag deletion
246 println!("\n2. Testing tag deletion:");
247
248 // Create a temporary tag to delete
249 repo.create_tag("temp-tag", None)?;
250 println!(" Created temporary tag: temp-tag");
251
252 // Verify it exists
253 let tags_before = repo.tags()?;
254 let temp_exists_before = tags_before.find("temp-tag").is_some();
255 println!(" Temp tag exists before deletion: {}", temp_exists_before);
256
257 // Delete it
258 repo.delete_tag("temp-tag")?;
259 println!(" Deleted temp-tag");
260
261 // Verify it's gone
262 let tags_after = repo.tags()?;
263 let temp_exists_after = tags_after.find("temp-tag").is_some();
264 println!(" Temp tag exists after deletion: {}", temp_exists_after);
265
266 // Summary
267 println!("\n=== Summary ===");
268 let final_tags = repo.tags()?;
269 println!("\nFinal repository state:");
270 println!(" Total tags: {}", final_tags.len());
271 println!(" Lightweight tags: {}", final_tags.lightweight_count());
272 println!(" Annotated tags: {}", final_tags.annotated_count());
273
274 println!("\nTag creation options demonstrated:");
275 println!(" ✓ Lightweight tags (simple references)");
276 println!(" ✓ Annotated tags (with messages and metadata)");
277 println!(" ✓ Tags on specific commits");
278 println!(" ✓ Tags on current HEAD");
279 println!(" ✓ Force tag creation/overwrite");
280
281 println!("\nTag listing and filtering demonstrated:");
282 println!(" ✓ List all tags");
283 println!(" ✓ Filter by tag type (lightweight/annotated)");
284 println!(" ✓ Search by name patterns");
285 println!(" ✓ Find tags by commit hash");
286 println!(" ✓ Show detailed tag information");
287
288 println!("\nTag management demonstrated:");
289 println!(" ✓ Tag creation with options");
290 println!(" ✓ Tag deletion");
291 println!(" ✓ Error handling for duplicate tags");
292
293 // Clean up
294 println!("\nCleaning up example repository...");
295 fs::remove_dir_all(&repo_path)?;
296 println!("Tag operations example completed successfully!");
297
298 Ok(())
299}
Sourcepub fn lightweight_count(&self) -> usize
pub fn lightweight_count(&self) -> usize
Get the number of lightweight tags
Examples found in repository?
examples/tag_operations.rs (line 143)
16fn main() -> Result<()> {
17 println!("Rustic Git - Tag Operations Example\n");
18
19 // Use a temporary directory for this example
20 let repo_path = env::temp_dir().join("rustic_git_tag_example");
21
22 // Clean up any previous run
23 if repo_path.exists() {
24 fs::remove_dir_all(&repo_path).expect("Failed to clean up previous example");
25 }
26
27 println!("Initializing repository at: {}", repo_path.display());
28
29 // Initialize repository and configure user
30 let repo = Repository::init(&repo_path, false)?;
31 repo.config()
32 .set_user("Tag Demo User", "tags@example.com")?;
33
34 // Create some commits to tag
35 println!("\nCreating initial commits...");
36
37 // First commit
38 fs::write(
39 repo_path.join("README.md"),
40 "# Tag Demo Project\n\nDemonstrating Git tag operations.\n",
41 )?;
42 repo.add(&["README.md"])?;
43 let first_commit_hash = repo.commit("Initial commit: Add README")?;
44 println!("Created commit: {}", first_commit_hash.short());
45
46 // Second commit
47 fs::create_dir_all(repo_path.join("src"))?;
48 fs::write(
49 repo_path.join("src/main.rs"),
50 "fn main() {\n println!(\"Hello, tags!\");\n}\n",
51 )?;
52 repo.add(&["src/main.rs"])?;
53 let second_commit_hash = repo.commit("Add main.rs with hello world")?;
54 println!("Created commit: {}", second_commit_hash.short());
55
56 // Third commit
57 fs::write(
58 repo_path.join("src/lib.rs"),
59 "//! Tag demo library\n\npub fn greet(name: &str) -> String {\n format!(\"Hello, {}!\", name)\n}\n",
60 )?;
61 repo.add(&["src/lib.rs"])?;
62 let third_commit_hash = repo.commit("Add library with greet function")?;
63 println!("Created commit: {}", third_commit_hash.short());
64
65 // Demonstrate tag creation
66 println!("\n=== Creating Tags ===");
67
68 // Create lightweight tags
69 println!("\n1. Creating lightweight tags:");
70
71 let v0_1_0 = repo.create_tag("v0.1.0", Some(&first_commit_hash))?;
72 println!(
73 "Created lightweight tag: {} -> {} ({})",
74 v0_1_0.name,
75 v0_1_0.hash.short(),
76 v0_1_0.tag_type
77 );
78
79 let v0_2_0 = repo.create_tag("v0.2.0", Some(&second_commit_hash))?;
80 println!(
81 "Created lightweight tag: {} -> {} ({})",
82 v0_2_0.name,
83 v0_2_0.hash.short(),
84 v0_2_0.tag_type
85 );
86
87 // Create annotated tags
88 println!("\n2. Creating annotated tags:");
89
90 let options =
91 TagOptions::new().with_message("First stable release with basic functionality".to_string());
92 let v1_0_0 = repo.create_tag_with_options("v1.0.0", Some(&third_commit_hash), options)?;
93 println!(
94 "Created annotated tag: {} -> {} ({})",
95 v1_0_0.name,
96 v1_0_0.hash.short(),
97 v1_0_0.tag_type
98 );
99 if let Some(message) = &v1_0_0.message {
100 println!(" Message: {}", message);
101 }
102
103 // Tag current HEAD
104 let latest_options = TagOptions::new().with_message("Latest development version".to_string());
105 let latest_tag = repo.create_tag_with_options("latest", None, latest_options)?;
106 println!(
107 "Created annotated tag on HEAD: {} -> {} ({})",
108 latest_tag.name,
109 latest_tag.hash.short(),
110 latest_tag.tag_type
111 );
112
113 // Create some feature tags
114 println!("\n3. Creating feature and release candidate tags:");
115
116 let feature_options = TagOptions::new().with_message("Feature branch snapshot".to_string());
117 repo.create_tag_with_options("feature/demo", None, feature_options)?;
118
119 let rc_options = TagOptions::new().with_message("Release candidate for v1.1.0".to_string());
120 repo.create_tag_with_options("v1.1.0-rc1", None, rc_options)?;
121
122 // Create a couple more version tags
123 repo.create_tag("v0.3.0", None)?;
124 repo.create_tag("v0.9.0", None)?;
125
126 // Demonstrate tag listing and filtering
127 println!("\n=== Tag Listing and Filtering ===");
128
129 let tags = repo.tags()?;
130 println!("\nAll tags ({} total):", tags.len());
131 for tag in tags.iter() {
132 let type_marker = match tag.tag_type {
133 TagType::Lightweight => "L",
134 TagType::Annotated => "A",
135 };
136 println!(" [{}] {} -> {}", type_marker, tag.name, tag.hash.short());
137 if let Some(message) = &tag.message {
138 println!(" Message: {}", message.lines().next().unwrap_or(""));
139 }
140 }
141
142 // Filter by type
143 println!("\nLightweight tags ({} total):", tags.lightweight_count());
144 for tag in tags.lightweight() {
145 println!(" {} -> {}", tag.name, tag.hash.short());
146 }
147
148 println!("\nAnnotated tags ({} total):", tags.annotated_count());
149 for tag in tags.annotated() {
150 println!(" {} -> {}", tag.name, tag.hash.short());
151 if let Some(message) = &tag.message {
152 println!(" Message: {}", message.lines().next().unwrap_or(""));
153 }
154 }
155
156 // Search and filtering
157 println!("\n=== Tag Searching ===");
158
159 // Find specific tag
160 if let Some(tag) = tags.find("v1.0.0") {
161 println!("\nFound tag 'v1.0.0':");
162 println!(" Type: {}", tag.tag_type);
163 println!(" Hash: {}", tag.hash.short());
164 if let Some(message) = &tag.message {
165 println!(" Message: {}", message);
166 }
167 }
168
169 // Find version tags
170 let version_tags: Vec<_> = tags.find_containing("v").collect();
171 println!(
172 "\nVersion tags (containing 'v'): {} found",
173 version_tags.len()
174 );
175 for tag in &version_tags {
176 println!(" {}", tag.name);
177 }
178
179 // Find release candidates
180 let rc_tags: Vec<_> = tags.find_containing("rc").collect();
181 println!("\nRelease candidate tags: {} found", rc_tags.len());
182 for tag in &rc_tags {
183 println!(" {}", tag.name);
184 }
185
186 // Find tags for specific commit
187 let tags_for_third_commit: Vec<_> = tags.for_commit(&third_commit_hash).collect();
188 println!(
189 "\nTags pointing to commit {}: {} found",
190 third_commit_hash.short(),
191 tags_for_third_commit.len()
192 );
193 for tag in &tags_for_third_commit {
194 println!(" {}", tag.name);
195 }
196
197 // Demonstrate tag details
198 println!("\n=== Tag Details ===");
199
200 let detailed_tag = repo.show_tag("v1.0.0")?;
201 println!("\nDetailed information for 'v1.0.0':");
202 println!(" Name: {}", detailed_tag.name);
203 println!(" Type: {}", detailed_tag.tag_type);
204 println!(" Commit: {}", detailed_tag.hash);
205 println!(" Short hash: {}", detailed_tag.hash.short());
206
207 if let Some(message) = &detailed_tag.message {
208 println!(" Message: {}", message);
209 }
210
211 if let Some(tagger) = &detailed_tag.tagger {
212 println!(" Tagger: {}", tagger);
213 println!(
214 " Tagged at: {}",
215 tagger.timestamp.format("%Y-%m-%d %H:%M:%S UTC")
216 );
217 }
218
219 if let Some(timestamp) = &detailed_tag.timestamp {
220 println!(" Timestamp: {}", timestamp.format("%Y-%m-%d %H:%M:%S UTC"));
221 }
222
223 // Demonstrate tag operations
224 println!("\n=== Tag Operations ===");
225
226 // Create and force overwrite a tag
227 println!("\n1. Testing tag overwrite:");
228
229 // This should fail (tag already exists)
230 match repo.create_tag("latest", None) {
231 Ok(_) => println!(" ERROR: Should have failed to create existing tag"),
232 Err(e) => println!(" Expected error creating existing tag: {}", e),
233 }
234
235 // Force overwrite
236 let force_options = TagOptions::new()
237 .with_force()
238 .with_message("Forcefully updated latest tag".to_string());
239
240 match repo.create_tag_with_options("latest", None, force_options) {
241 Ok(tag) => println!(" Successfully force-created tag: {}", tag.name),
242 Err(e) => println!(" Error force-creating tag: {}", e),
243 }
244
245 // Tag deletion
246 println!("\n2. Testing tag deletion:");
247
248 // Create a temporary tag to delete
249 repo.create_tag("temp-tag", None)?;
250 println!(" Created temporary tag: temp-tag");
251
252 // Verify it exists
253 let tags_before = repo.tags()?;
254 let temp_exists_before = tags_before.find("temp-tag").is_some();
255 println!(" Temp tag exists before deletion: {}", temp_exists_before);
256
257 // Delete it
258 repo.delete_tag("temp-tag")?;
259 println!(" Deleted temp-tag");
260
261 // Verify it's gone
262 let tags_after = repo.tags()?;
263 let temp_exists_after = tags_after.find("temp-tag").is_some();
264 println!(" Temp tag exists after deletion: {}", temp_exists_after);
265
266 // Summary
267 println!("\n=== Summary ===");
268 let final_tags = repo.tags()?;
269 println!("\nFinal repository state:");
270 println!(" Total tags: {}", final_tags.len());
271 println!(" Lightweight tags: {}", final_tags.lightweight_count());
272 println!(" Annotated tags: {}", final_tags.annotated_count());
273
274 println!("\nTag creation options demonstrated:");
275 println!(" ✓ Lightweight tags (simple references)");
276 println!(" ✓ Annotated tags (with messages and metadata)");
277 println!(" ✓ Tags on specific commits");
278 println!(" ✓ Tags on current HEAD");
279 println!(" ✓ Force tag creation/overwrite");
280
281 println!("\nTag listing and filtering demonstrated:");
282 println!(" ✓ List all tags");
283 println!(" ✓ Filter by tag type (lightweight/annotated)");
284 println!(" ✓ Search by name patterns");
285 println!(" ✓ Find tags by commit hash");
286 println!(" ✓ Show detailed tag information");
287
288 println!("\nTag management demonstrated:");
289 println!(" ✓ Tag creation with options");
290 println!(" ✓ Tag deletion");
291 println!(" ✓ Error handling for duplicate tags");
292
293 // Clean up
294 println!("\nCleaning up example repository...");
295 fs::remove_dir_all(&repo_path)?;
296 println!("Tag operations example completed successfully!");
297
298 Ok(())
299}
Sourcepub fn annotated_count(&self) -> usize
pub fn annotated_count(&self) -> usize
Get the number of annotated tags
Examples found in repository?
examples/tag_operations.rs (line 148)
16fn main() -> Result<()> {
17 println!("Rustic Git - Tag Operations Example\n");
18
19 // Use a temporary directory for this example
20 let repo_path = env::temp_dir().join("rustic_git_tag_example");
21
22 // Clean up any previous run
23 if repo_path.exists() {
24 fs::remove_dir_all(&repo_path).expect("Failed to clean up previous example");
25 }
26
27 println!("Initializing repository at: {}", repo_path.display());
28
29 // Initialize repository and configure user
30 let repo = Repository::init(&repo_path, false)?;
31 repo.config()
32 .set_user("Tag Demo User", "tags@example.com")?;
33
34 // Create some commits to tag
35 println!("\nCreating initial commits...");
36
37 // First commit
38 fs::write(
39 repo_path.join("README.md"),
40 "# Tag Demo Project\n\nDemonstrating Git tag operations.\n",
41 )?;
42 repo.add(&["README.md"])?;
43 let first_commit_hash = repo.commit("Initial commit: Add README")?;
44 println!("Created commit: {}", first_commit_hash.short());
45
46 // Second commit
47 fs::create_dir_all(repo_path.join("src"))?;
48 fs::write(
49 repo_path.join("src/main.rs"),
50 "fn main() {\n println!(\"Hello, tags!\");\n}\n",
51 )?;
52 repo.add(&["src/main.rs"])?;
53 let second_commit_hash = repo.commit("Add main.rs with hello world")?;
54 println!("Created commit: {}", second_commit_hash.short());
55
56 // Third commit
57 fs::write(
58 repo_path.join("src/lib.rs"),
59 "//! Tag demo library\n\npub fn greet(name: &str) -> String {\n format!(\"Hello, {}!\", name)\n}\n",
60 )?;
61 repo.add(&["src/lib.rs"])?;
62 let third_commit_hash = repo.commit("Add library with greet function")?;
63 println!("Created commit: {}", third_commit_hash.short());
64
65 // Demonstrate tag creation
66 println!("\n=== Creating Tags ===");
67
68 // Create lightweight tags
69 println!("\n1. Creating lightweight tags:");
70
71 let v0_1_0 = repo.create_tag("v0.1.0", Some(&first_commit_hash))?;
72 println!(
73 "Created lightweight tag: {} -> {} ({})",
74 v0_1_0.name,
75 v0_1_0.hash.short(),
76 v0_1_0.tag_type
77 );
78
79 let v0_2_0 = repo.create_tag("v0.2.0", Some(&second_commit_hash))?;
80 println!(
81 "Created lightweight tag: {} -> {} ({})",
82 v0_2_0.name,
83 v0_2_0.hash.short(),
84 v0_2_0.tag_type
85 );
86
87 // Create annotated tags
88 println!("\n2. Creating annotated tags:");
89
90 let options =
91 TagOptions::new().with_message("First stable release with basic functionality".to_string());
92 let v1_0_0 = repo.create_tag_with_options("v1.0.0", Some(&third_commit_hash), options)?;
93 println!(
94 "Created annotated tag: {} -> {} ({})",
95 v1_0_0.name,
96 v1_0_0.hash.short(),
97 v1_0_0.tag_type
98 );
99 if let Some(message) = &v1_0_0.message {
100 println!(" Message: {}", message);
101 }
102
103 // Tag current HEAD
104 let latest_options = TagOptions::new().with_message("Latest development version".to_string());
105 let latest_tag = repo.create_tag_with_options("latest", None, latest_options)?;
106 println!(
107 "Created annotated tag on HEAD: {} -> {} ({})",
108 latest_tag.name,
109 latest_tag.hash.short(),
110 latest_tag.tag_type
111 );
112
113 // Create some feature tags
114 println!("\n3. Creating feature and release candidate tags:");
115
116 let feature_options = TagOptions::new().with_message("Feature branch snapshot".to_string());
117 repo.create_tag_with_options("feature/demo", None, feature_options)?;
118
119 let rc_options = TagOptions::new().with_message("Release candidate for v1.1.0".to_string());
120 repo.create_tag_with_options("v1.1.0-rc1", None, rc_options)?;
121
122 // Create a couple more version tags
123 repo.create_tag("v0.3.0", None)?;
124 repo.create_tag("v0.9.0", None)?;
125
126 // Demonstrate tag listing and filtering
127 println!("\n=== Tag Listing and Filtering ===");
128
129 let tags = repo.tags()?;
130 println!("\nAll tags ({} total):", tags.len());
131 for tag in tags.iter() {
132 let type_marker = match tag.tag_type {
133 TagType::Lightweight => "L",
134 TagType::Annotated => "A",
135 };
136 println!(" [{}] {} -> {}", type_marker, tag.name, tag.hash.short());
137 if let Some(message) = &tag.message {
138 println!(" Message: {}", message.lines().next().unwrap_or(""));
139 }
140 }
141
142 // Filter by type
143 println!("\nLightweight tags ({} total):", tags.lightweight_count());
144 for tag in tags.lightweight() {
145 println!(" {} -> {}", tag.name, tag.hash.short());
146 }
147
148 println!("\nAnnotated tags ({} total):", tags.annotated_count());
149 for tag in tags.annotated() {
150 println!(" {} -> {}", tag.name, tag.hash.short());
151 if let Some(message) = &tag.message {
152 println!(" Message: {}", message.lines().next().unwrap_or(""));
153 }
154 }
155
156 // Search and filtering
157 println!("\n=== Tag Searching ===");
158
159 // Find specific tag
160 if let Some(tag) = tags.find("v1.0.0") {
161 println!("\nFound tag 'v1.0.0':");
162 println!(" Type: {}", tag.tag_type);
163 println!(" Hash: {}", tag.hash.short());
164 if let Some(message) = &tag.message {
165 println!(" Message: {}", message);
166 }
167 }
168
169 // Find version tags
170 let version_tags: Vec<_> = tags.find_containing("v").collect();
171 println!(
172 "\nVersion tags (containing 'v'): {} found",
173 version_tags.len()
174 );
175 for tag in &version_tags {
176 println!(" {}", tag.name);
177 }
178
179 // Find release candidates
180 let rc_tags: Vec<_> = tags.find_containing("rc").collect();
181 println!("\nRelease candidate tags: {} found", rc_tags.len());
182 for tag in &rc_tags {
183 println!(" {}", tag.name);
184 }
185
186 // Find tags for specific commit
187 let tags_for_third_commit: Vec<_> = tags.for_commit(&third_commit_hash).collect();
188 println!(
189 "\nTags pointing to commit {}: {} found",
190 third_commit_hash.short(),
191 tags_for_third_commit.len()
192 );
193 for tag in &tags_for_third_commit {
194 println!(" {}", tag.name);
195 }
196
197 // Demonstrate tag details
198 println!("\n=== Tag Details ===");
199
200 let detailed_tag = repo.show_tag("v1.0.0")?;
201 println!("\nDetailed information for 'v1.0.0':");
202 println!(" Name: {}", detailed_tag.name);
203 println!(" Type: {}", detailed_tag.tag_type);
204 println!(" Commit: {}", detailed_tag.hash);
205 println!(" Short hash: {}", detailed_tag.hash.short());
206
207 if let Some(message) = &detailed_tag.message {
208 println!(" Message: {}", message);
209 }
210
211 if let Some(tagger) = &detailed_tag.tagger {
212 println!(" Tagger: {}", tagger);
213 println!(
214 " Tagged at: {}",
215 tagger.timestamp.format("%Y-%m-%d %H:%M:%S UTC")
216 );
217 }
218
219 if let Some(timestamp) = &detailed_tag.timestamp {
220 println!(" Timestamp: {}", timestamp.format("%Y-%m-%d %H:%M:%S UTC"));
221 }
222
223 // Demonstrate tag operations
224 println!("\n=== Tag Operations ===");
225
226 // Create and force overwrite a tag
227 println!("\n1. Testing tag overwrite:");
228
229 // This should fail (tag already exists)
230 match repo.create_tag("latest", None) {
231 Ok(_) => println!(" ERROR: Should have failed to create existing tag"),
232 Err(e) => println!(" Expected error creating existing tag: {}", e),
233 }
234
235 // Force overwrite
236 let force_options = TagOptions::new()
237 .with_force()
238 .with_message("Forcefully updated latest tag".to_string());
239
240 match repo.create_tag_with_options("latest", None, force_options) {
241 Ok(tag) => println!(" Successfully force-created tag: {}", tag.name),
242 Err(e) => println!(" Error force-creating tag: {}", e),
243 }
244
245 // Tag deletion
246 println!("\n2. Testing tag deletion:");
247
248 // Create a temporary tag to delete
249 repo.create_tag("temp-tag", None)?;
250 println!(" Created temporary tag: temp-tag");
251
252 // Verify it exists
253 let tags_before = repo.tags()?;
254 let temp_exists_before = tags_before.find("temp-tag").is_some();
255 println!(" Temp tag exists before deletion: {}", temp_exists_before);
256
257 // Delete it
258 repo.delete_tag("temp-tag")?;
259 println!(" Deleted temp-tag");
260
261 // Verify it's gone
262 let tags_after = repo.tags()?;
263 let temp_exists_after = tags_after.find("temp-tag").is_some();
264 println!(" Temp tag exists after deletion: {}", temp_exists_after);
265
266 // Summary
267 println!("\n=== Summary ===");
268 let final_tags = repo.tags()?;
269 println!("\nFinal repository state:");
270 println!(" Total tags: {}", final_tags.len());
271 println!(" Lightweight tags: {}", final_tags.lightweight_count());
272 println!(" Annotated tags: {}", final_tags.annotated_count());
273
274 println!("\nTag creation options demonstrated:");
275 println!(" ✓ Lightweight tags (simple references)");
276 println!(" ✓ Annotated tags (with messages and metadata)");
277 println!(" ✓ Tags on specific commits");
278 println!(" ✓ Tags on current HEAD");
279 println!(" ✓ Force tag creation/overwrite");
280
281 println!("\nTag listing and filtering demonstrated:");
282 println!(" ✓ List all tags");
283 println!(" ✓ Filter by tag type (lightweight/annotated)");
284 println!(" ✓ Search by name patterns");
285 println!(" ✓ Find tags by commit hash");
286 println!(" ✓ Show detailed tag information");
287
288 println!("\nTag management demonstrated:");
289 println!(" ✓ Tag creation with options");
290 println!(" ✓ Tag deletion");
291 println!(" ✓ Error handling for duplicate tags");
292
293 // Clean up
294 println!("\nCleaning up example repository...");
295 fs::remove_dir_all(&repo_path)?;
296 println!("Tag operations example completed successfully!");
297
298 Ok(())
299}
Sourcepub fn for_commit<'a>(
&'a self,
hash: &'a Hash,
) -> impl Iterator<Item = &'a Tag> + 'a
pub fn for_commit<'a>( &'a self, hash: &'a Hash, ) -> impl Iterator<Item = &'a Tag> + 'a
Get tags that point to a specific commit
Examples found in repository?
examples/tag_operations.rs (line 187)
16fn main() -> Result<()> {
17 println!("Rustic Git - Tag Operations Example\n");
18
19 // Use a temporary directory for this example
20 let repo_path = env::temp_dir().join("rustic_git_tag_example");
21
22 // Clean up any previous run
23 if repo_path.exists() {
24 fs::remove_dir_all(&repo_path).expect("Failed to clean up previous example");
25 }
26
27 println!("Initializing repository at: {}", repo_path.display());
28
29 // Initialize repository and configure user
30 let repo = Repository::init(&repo_path, false)?;
31 repo.config()
32 .set_user("Tag Demo User", "tags@example.com")?;
33
34 // Create some commits to tag
35 println!("\nCreating initial commits...");
36
37 // First commit
38 fs::write(
39 repo_path.join("README.md"),
40 "# Tag Demo Project\n\nDemonstrating Git tag operations.\n",
41 )?;
42 repo.add(&["README.md"])?;
43 let first_commit_hash = repo.commit("Initial commit: Add README")?;
44 println!("Created commit: {}", first_commit_hash.short());
45
46 // Second commit
47 fs::create_dir_all(repo_path.join("src"))?;
48 fs::write(
49 repo_path.join("src/main.rs"),
50 "fn main() {\n println!(\"Hello, tags!\");\n}\n",
51 )?;
52 repo.add(&["src/main.rs"])?;
53 let second_commit_hash = repo.commit("Add main.rs with hello world")?;
54 println!("Created commit: {}", second_commit_hash.short());
55
56 // Third commit
57 fs::write(
58 repo_path.join("src/lib.rs"),
59 "//! Tag demo library\n\npub fn greet(name: &str) -> String {\n format!(\"Hello, {}!\", name)\n}\n",
60 )?;
61 repo.add(&["src/lib.rs"])?;
62 let third_commit_hash = repo.commit("Add library with greet function")?;
63 println!("Created commit: {}", third_commit_hash.short());
64
65 // Demonstrate tag creation
66 println!("\n=== Creating Tags ===");
67
68 // Create lightweight tags
69 println!("\n1. Creating lightweight tags:");
70
71 let v0_1_0 = repo.create_tag("v0.1.0", Some(&first_commit_hash))?;
72 println!(
73 "Created lightweight tag: {} -> {} ({})",
74 v0_1_0.name,
75 v0_1_0.hash.short(),
76 v0_1_0.tag_type
77 );
78
79 let v0_2_0 = repo.create_tag("v0.2.0", Some(&second_commit_hash))?;
80 println!(
81 "Created lightweight tag: {} -> {} ({})",
82 v0_2_0.name,
83 v0_2_0.hash.short(),
84 v0_2_0.tag_type
85 );
86
87 // Create annotated tags
88 println!("\n2. Creating annotated tags:");
89
90 let options =
91 TagOptions::new().with_message("First stable release with basic functionality".to_string());
92 let v1_0_0 = repo.create_tag_with_options("v1.0.0", Some(&third_commit_hash), options)?;
93 println!(
94 "Created annotated tag: {} -> {} ({})",
95 v1_0_0.name,
96 v1_0_0.hash.short(),
97 v1_0_0.tag_type
98 );
99 if let Some(message) = &v1_0_0.message {
100 println!(" Message: {}", message);
101 }
102
103 // Tag current HEAD
104 let latest_options = TagOptions::new().with_message("Latest development version".to_string());
105 let latest_tag = repo.create_tag_with_options("latest", None, latest_options)?;
106 println!(
107 "Created annotated tag on HEAD: {} -> {} ({})",
108 latest_tag.name,
109 latest_tag.hash.short(),
110 latest_tag.tag_type
111 );
112
113 // Create some feature tags
114 println!("\n3. Creating feature and release candidate tags:");
115
116 let feature_options = TagOptions::new().with_message("Feature branch snapshot".to_string());
117 repo.create_tag_with_options("feature/demo", None, feature_options)?;
118
119 let rc_options = TagOptions::new().with_message("Release candidate for v1.1.0".to_string());
120 repo.create_tag_with_options("v1.1.0-rc1", None, rc_options)?;
121
122 // Create a couple more version tags
123 repo.create_tag("v0.3.0", None)?;
124 repo.create_tag("v0.9.0", None)?;
125
126 // Demonstrate tag listing and filtering
127 println!("\n=== Tag Listing and Filtering ===");
128
129 let tags = repo.tags()?;
130 println!("\nAll tags ({} total):", tags.len());
131 for tag in tags.iter() {
132 let type_marker = match tag.tag_type {
133 TagType::Lightweight => "L",
134 TagType::Annotated => "A",
135 };
136 println!(" [{}] {} -> {}", type_marker, tag.name, tag.hash.short());
137 if let Some(message) = &tag.message {
138 println!(" Message: {}", message.lines().next().unwrap_or(""));
139 }
140 }
141
142 // Filter by type
143 println!("\nLightweight tags ({} total):", tags.lightweight_count());
144 for tag in tags.lightweight() {
145 println!(" {} -> {}", tag.name, tag.hash.short());
146 }
147
148 println!("\nAnnotated tags ({} total):", tags.annotated_count());
149 for tag in tags.annotated() {
150 println!(" {} -> {}", tag.name, tag.hash.short());
151 if let Some(message) = &tag.message {
152 println!(" Message: {}", message.lines().next().unwrap_or(""));
153 }
154 }
155
156 // Search and filtering
157 println!("\n=== Tag Searching ===");
158
159 // Find specific tag
160 if let Some(tag) = tags.find("v1.0.0") {
161 println!("\nFound tag 'v1.0.0':");
162 println!(" Type: {}", tag.tag_type);
163 println!(" Hash: {}", tag.hash.short());
164 if let Some(message) = &tag.message {
165 println!(" Message: {}", message);
166 }
167 }
168
169 // Find version tags
170 let version_tags: Vec<_> = tags.find_containing("v").collect();
171 println!(
172 "\nVersion tags (containing 'v'): {} found",
173 version_tags.len()
174 );
175 for tag in &version_tags {
176 println!(" {}", tag.name);
177 }
178
179 // Find release candidates
180 let rc_tags: Vec<_> = tags.find_containing("rc").collect();
181 println!("\nRelease candidate tags: {} found", rc_tags.len());
182 for tag in &rc_tags {
183 println!(" {}", tag.name);
184 }
185
186 // Find tags for specific commit
187 let tags_for_third_commit: Vec<_> = tags.for_commit(&third_commit_hash).collect();
188 println!(
189 "\nTags pointing to commit {}: {} found",
190 third_commit_hash.short(),
191 tags_for_third_commit.len()
192 );
193 for tag in &tags_for_third_commit {
194 println!(" {}", tag.name);
195 }
196
197 // Demonstrate tag details
198 println!("\n=== Tag Details ===");
199
200 let detailed_tag = repo.show_tag("v1.0.0")?;
201 println!("\nDetailed information for 'v1.0.0':");
202 println!(" Name: {}", detailed_tag.name);
203 println!(" Type: {}", detailed_tag.tag_type);
204 println!(" Commit: {}", detailed_tag.hash);
205 println!(" Short hash: {}", detailed_tag.hash.short());
206
207 if let Some(message) = &detailed_tag.message {
208 println!(" Message: {}", message);
209 }
210
211 if let Some(tagger) = &detailed_tag.tagger {
212 println!(" Tagger: {}", tagger);
213 println!(
214 " Tagged at: {}",
215 tagger.timestamp.format("%Y-%m-%d %H:%M:%S UTC")
216 );
217 }
218
219 if let Some(timestamp) = &detailed_tag.timestamp {
220 println!(" Timestamp: {}", timestamp.format("%Y-%m-%d %H:%M:%S UTC"));
221 }
222
223 // Demonstrate tag operations
224 println!("\n=== Tag Operations ===");
225
226 // Create and force overwrite a tag
227 println!("\n1. Testing tag overwrite:");
228
229 // This should fail (tag already exists)
230 match repo.create_tag("latest", None) {
231 Ok(_) => println!(" ERROR: Should have failed to create existing tag"),
232 Err(e) => println!(" Expected error creating existing tag: {}", e),
233 }
234
235 // Force overwrite
236 let force_options = TagOptions::new()
237 .with_force()
238 .with_message("Forcefully updated latest tag".to_string());
239
240 match repo.create_tag_with_options("latest", None, force_options) {
241 Ok(tag) => println!(" Successfully force-created tag: {}", tag.name),
242 Err(e) => println!(" Error force-creating tag: {}", e),
243 }
244
245 // Tag deletion
246 println!("\n2. Testing tag deletion:");
247
248 // Create a temporary tag to delete
249 repo.create_tag("temp-tag", None)?;
250 println!(" Created temporary tag: temp-tag");
251
252 // Verify it exists
253 let tags_before = repo.tags()?;
254 let temp_exists_before = tags_before.find("temp-tag").is_some();
255 println!(" Temp tag exists before deletion: {}", temp_exists_before);
256
257 // Delete it
258 repo.delete_tag("temp-tag")?;
259 println!(" Deleted temp-tag");
260
261 // Verify it's gone
262 let tags_after = repo.tags()?;
263 let temp_exists_after = tags_after.find("temp-tag").is_some();
264 println!(" Temp tag exists after deletion: {}", temp_exists_after);
265
266 // Summary
267 println!("\n=== Summary ===");
268 let final_tags = repo.tags()?;
269 println!("\nFinal repository state:");
270 println!(" Total tags: {}", final_tags.len());
271 println!(" Lightweight tags: {}", final_tags.lightweight_count());
272 println!(" Annotated tags: {}", final_tags.annotated_count());
273
274 println!("\nTag creation options demonstrated:");
275 println!(" ✓ Lightweight tags (simple references)");
276 println!(" ✓ Annotated tags (with messages and metadata)");
277 println!(" ✓ Tags on specific commits");
278 println!(" ✓ Tags on current HEAD");
279 println!(" ✓ Force tag creation/overwrite");
280
281 println!("\nTag listing and filtering demonstrated:");
282 println!(" ✓ List all tags");
283 println!(" ✓ Filter by tag type (lightweight/annotated)");
284 println!(" ✓ Search by name patterns");
285 println!(" ✓ Find tags by commit hash");
286 println!(" ✓ Show detailed tag information");
287
288 println!("\nTag management demonstrated:");
289 println!(" ✓ Tag creation with options");
290 println!(" ✓ Tag deletion");
291 println!(" ✓ Error handling for duplicate tags");
292
293 // Clean up
294 println!("\nCleaning up example repository...");
295 fs::remove_dir_all(&repo_path)?;
296 println!("Tag operations example completed successfully!");
297
298 Ok(())
299}
Trait Implementations§
Auto Trait Implementations§
impl Freeze for TagList
impl RefUnwindSafe for TagList
impl Send for TagList
impl Sync for TagList
impl Unpin for TagList
impl UnwindSafe for TagList
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more