TagList

Struct TagList 

Source
pub struct TagList { /* private fields */ }
Expand description

A collection of tags with efficient iteration and filtering methods

Implementations§

Source§

impl TagList

Source

pub fn new(tags: Vec<Tag>) -> Self

Create a new TagList from a vector of tags

Source

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}
Source

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}
Source

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}
Source

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}
Source

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}
Source

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}
Source

pub fn is_empty(&self) -> bool

Check if the tag list is empty

Source

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}
Source

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}
Source

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§

Source§

impl Clone for TagList

Source§

fn clone(&self) -> TagList

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for TagList

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.