pub struct RepoConfig<'a> { /* private fields */ }
Expand description
Repository configuration manager
Provides methods for getting and setting git configuration values for a specific repository.
Implementations§
Source§impl<'a> RepoConfig<'a>
impl<'a> RepoConfig<'a>
pub const USER_NAME_KEY: &'static str = "user.name"
pub const USER_EMAIL_KEY: &'static str = "user.email"
Sourcepub fn set_user(&self, name: &str, email: &str) -> Result<()>
pub fn set_user(&self, name: &str, email: &str) -> Result<()>
Configure git user name and email for this repository
This is a convenience method that sets both user.name and user.email configuration values.
§Arguments
name
- The user’s full nameemail
- The user’s email address
§Example
use rustic_git::Repository;
use std::{env, fs};
let test_path = env::temp_dir().join("config_set_user_test");
if test_path.exists() {
fs::remove_dir_all(&test_path).unwrap();
}
let repo = Repository::init(&test_path, false)?;
repo.config().set_user("John Doe", "john@example.com")?;
// Clean up
fs::remove_dir_all(&test_path).unwrap();
Examples found in repository?
examples/reset_operations.rs (line 30)
13fn main() -> Result<()> {
14 println!("=== Reset Operations Demo ===\n");
15
16 // Create a temporary directory for our example
17 let temp_dir = env::temp_dir().join("rustic_git_reset_demo");
18
19 // Clean up if exists
20 if temp_dir.exists() {
21 fs::remove_dir_all(&temp_dir)?;
22 }
23
24 println!("Working in temporary directory: {:?}\n", temp_dir);
25
26 // Initialize a new repository
27 let repo = Repository::init(&temp_dir, false)?;
28
29 // Configure user for commits
30 repo.config().set_user("Example User", "example@test.com")?;
31
32 demonstrate_reset_modes(&repo, &temp_dir)?;
33 demonstrate_file_resets(&repo, &temp_dir)?;
34 demonstrate_error_handling(&repo)?;
35
36 println!("\n=== Reset Operations Demo Complete ===");
37
38 // Clean up
39 fs::remove_dir_all(&temp_dir)?;
40 Ok(())
41}
More examples
examples/merge_operations.rs (line 31)
14fn main() -> Result<()> {
15 println!("=== Merge Operations Demo ===\n");
16
17 // Create a temporary directory for our example
18 let temp_dir = env::temp_dir().join("rustic_git_merge_demo");
19
20 // Clean up if exists
21 if temp_dir.exists() {
22 fs::remove_dir_all(&temp_dir)?;
23 }
24
25 println!("Working in temporary directory: {:?}\n", temp_dir);
26
27 // Initialize a new repository
28 let repo = Repository::init(&temp_dir, false)?;
29
30 // Configure user for commits
31 repo.config().set_user("Example User", "example@test.com")?;
32
33 demonstrate_fast_forward_merge(&repo, &temp_dir)?;
34 demonstrate_no_fast_forward_merge(&repo, &temp_dir)?;
35 demonstrate_merge_conflicts(&repo, &temp_dir)?;
36 demonstrate_merge_status_and_abort(&repo, &temp_dir)?;
37
38 println!("\n=== Merge Operations Demo Complete ===");
39
40 // Clean up
41 fs::remove_dir_all(&temp_dir)?;
42 Ok(())
43}
examples/config_operations.rs (line 36)
14fn main() -> Result<()> {
15 println!("Rustic Git - Repository Configuration Operations Example\n");
16
17 // Use a temporary directory for this example
18 let repo_path = env::temp_dir().join("rustic_git_config_example");
19
20 // Clean up any previous run
21 if repo_path.exists() {
22 fs::remove_dir_all(&repo_path).expect("Failed to clean up previous example");
23 }
24
25 println!("Initializing new repository at: {}", repo_path.display());
26
27 // Initialize a new repository
28 let repo = Repository::init(&repo_path, false)?;
29
30 // ==================== USER CONFIGURATION ====================
31
32 println!("\n[CONFIG] Configuring git user settings...");
33
34 // Set user configuration (convenience method)
35 repo.config()
36 .set_user("Alice Developer", "alice@example.com")?;
37 println!("Set user configuration");
38
39 // Verify user configuration
40 let (name, email) = repo.config().get_user()?;
41 println!("Current user: {} <{}>", name, email);
42
43 // ==================== GENERAL CONFIGURATION ====================
44
45 println!("\n[CONFIG] Setting repository configuration values...");
46
47 // Set various git configuration values
48 repo.config().set("core.autocrlf", "false")?;
49 repo.config().set("core.ignorecase", "true")?;
50 repo.config().set("pull.rebase", "true")?;
51 repo.config().set("push.default", "simple")?;
52 repo.config().set("branch.autosetupmerge", "always")?;
53
54 println!("Set core configuration values");
55
56 // Get and display configuration values
57 println!("\n[CONFIG] Current repository configuration:");
58
59 let configs = [
60 "core.autocrlf",
61 "core.ignorecase",
62 "pull.rebase",
63 "push.default",
64 "branch.autosetupmerge",
65 ];
66
67 for config_key in &configs {
68 match repo.config().get(config_key) {
69 Ok(value) => println!(" {} = {}", config_key, value),
70 Err(_) => println!(" {} = <not set>", config_key),
71 }
72 }
73
74 // ==================== CONFIGURATION WITH COMMITS ====================
75
76 println!("\n[COMMIT] Testing configuration with commit operations...");
77
78 // Create a test file
79 let test_file_path = repo_path.join("test.txt");
80 fs::write(
81 &test_file_path,
82 "Hello from rustic-git configuration example!",
83 )?;
84 println!("Created test file: test.txt");
85
86 // Stage the file
87 repo.add(&["test.txt"])?;
88 println!("Staged test.txt");
89
90 // Create a commit (this will use our configured user)
91 let commit_hash = repo.commit("Add test file with configuration example")?;
92 println!("Created commit: {}", commit_hash.short());
93
94 // ==================== CONFIGURATION MODIFICATION ====================
95
96 println!("\n[UPDATE] Modifying configuration values...");
97
98 // Change some configuration values
99 repo.config().set("core.autocrlf", "true")?;
100 repo.config()
101 .set("user.email", "alice.developer@newcompany.com")?;
102
103 println!("Updated configuration values");
104
105 // Display updated values
106 let autocrlf = repo.config().get("core.autocrlf")?;
107 let (updated_name, updated_email) = repo.config().get_user()?;
108
109 println!("Updated configuration:");
110 println!(" core.autocrlf = {}", autocrlf);
111 println!(" user: {} <{}>", updated_name, updated_email);
112
113 // ==================== CONFIGURATION REMOVAL ====================
114
115 println!("\n[REMOVE] Removing configuration values...");
116
117 // Remove a configuration value
118 repo.config().unset("branch.autosetupmerge")?;
119 println!("Removed branch.autosetupmerge");
120
121 // Try to get the removed value (should fail)
122 match repo.config().get("branch.autosetupmerge") {
123 Ok(value) => println!("Unexpected: branch.autosetupmerge = {}", value),
124 Err(_) => println!("Confirmed: branch.autosetupmerge is not set"),
125 }
126
127 // ==================== ADVANCED CONFIGURATION ====================
128
129 println!("\n[ADVANCED] Setting advanced configuration...");
130
131 // Set some advanced git configuration
132 repo.config().set("diff.tool", "vimdiff")?;
133 repo.config().set("merge.tool", "vimdiff")?;
134 repo.config().set("alias.st", "status")?;
135 repo.config().set("alias.co", "checkout")?;
136 repo.config().set("alias.br", "branch")?;
137 repo.config().set("alias.ci", "commit")?;
138
139 println!("Set advanced configuration (diff/merge tools and aliases)");
140
141 // Display all custom configuration
142 println!("\n[SUMMARY] Complete repository configuration summary:");
143
144 let all_configs = [
145 ("User", vec![("user.name", ""), ("user.email", "")]),
146 ("Core", vec![("core.autocrlf", ""), ("core.ignorecase", "")]),
147 ("Workflow", vec![("pull.rebase", ""), ("push.default", "")]),
148 ("Tools", vec![("diff.tool", ""), ("merge.tool", "")]),
149 (
150 "Aliases",
151 vec![
152 ("alias.st", ""),
153 ("alias.co", ""),
154 ("alias.br", ""),
155 ("alias.ci", ""),
156 ],
157 ),
158 ];
159
160 for (category, configs) in &all_configs {
161 println!("\n {}:", category);
162 for (key, _) in configs {
163 match repo.config().get(key) {
164 Ok(value) => println!(" {} = {}", key, value),
165 Err(_) => println!(" {} = <not set>", key),
166 }
167 }
168 }
169
170 // ==================== PRACTICAL EXAMPLE ====================
171
172 println!("\n[TEAM] Practical example: Setting up repository for a team...");
173
174 // Configure repository for team development
175 repo.config().set("user.name", "Team Member")?;
176 repo.config().set("user.email", "team@company.com")?;
177 repo.config().set("core.autocrlf", "input")?;
178 repo.config().set("core.safecrlf", "true")?;
179 repo.config().set("pull.rebase", "true")?;
180 repo.config().set("push.default", "current")?;
181 repo.config().set("init.defaultBranch", "main")?;
182
183 println!("Configured repository for team development");
184
185 // Create another commit with the team configuration
186 fs::write(
187 repo_path.join("team.md"),
188 "# Team Development\n\nThis repository is configured for team development.",
189 )?;
190 repo.add(&["team.md"])?;
191 let team_commit = repo.commit("Add team development documentation")?;
192
193 println!("Created team commit: {}", team_commit.short());
194
195 // Final verification
196 let (final_name, final_email) = repo.config().get_user()?;
197 println!("\n[FINAL] Final repository configuration:");
198 println!(" User: {} <{}>", final_name, final_email);
199 println!(" Repository configured for team development workflow");
200
201 // ==================== CLEANUP ====================
202
203 println!("\n[CLEANUP] Cleaning up...");
204 fs::remove_dir_all(&repo_path).expect("Failed to clean up example");
205 println!("Example completed successfully!");
206
207 Ok(())
208}
examples/diff_operations.rs (line 20)
4fn main() -> rustic_git::Result<()> {
5 println!("Rustic Git - Diff Operations Example\n");
6
7 let repo_path = env::temp_dir().join("rustic_git_diff_example");
8 // Clean up any previous run
9 if repo_path.exists() {
10 fs::remove_dir_all(&repo_path).ok();
11 }
12 println!("Working in temporary directory: {}", repo_path.display());
13
14 // Initialize repository
15 let repo = Repository::init(&repo_path, false)?;
16 println!("Repository initialized successfully\n");
17
18 // Configure git user for commits
19 let config = repo.config();
20 config.set_user("Test User", "test@example.com")?;
21
22 println!("=== Creating Initial Files ===");
23
24 // Create initial files
25 let readme_path = repo_path.join("README.md");
26 let src_dir = repo_path.join("src");
27 fs::create_dir_all(&src_dir).unwrap();
28 let main_path = src_dir.join("main.rs");
29 let lib_path = src_dir.join("lib.rs");
30
31 fs::write(
32 &readme_path,
33 "# Test Project\n\nA sample project for testing diff operations.\n",
34 )
35 .unwrap();
36 fs::write(
37 &main_path,
38 "fn main() {\n println!(\"Hello, world!\");\n}\n",
39 )
40 .unwrap();
41 fs::write(
42 &lib_path,
43 "pub fn add(a: i32, b: i32) -> i32 {\n a + b\n}\n",
44 )
45 .unwrap();
46
47 println!("Created initial files: README.md, src/main.rs, src/lib.rs");
48
49 // Stage and commit initial files
50 repo.add_all()?;
51 let initial_commit = repo.commit("feat: initial commit with basic files")?;
52 println!("Initial commit: {}\n", initial_commit.short());
53
54 println!("=== Testing Different Diff Operations ===");
55
56 // Test 1: Diff with no changes (should be empty)
57 println!("1. Diff with no changes:");
58 let diff = repo.diff()?;
59 if diff.is_empty() {
60 println!(" ✓ No changes detected (as expected)");
61 } else {
62 println!(" ✗ Unexpected changes found");
63 }
64 println!();
65
66 // Test 2: Modify files and show unstaged changes
67 println!("2. Creating unstaged changes:");
68 fs::write(&readme_path, "# Test Project\n\nA sample project for testing diff operations.\n\n## Features\n- Git operations\n- Diff functionality\n").unwrap();
69 fs::write(&main_path, "fn main() {\n println!(\"Hello, world!\");\n println!(\"Testing diff operations!\");\n}\n").unwrap();
70
71 let diff = repo.diff()?;
72 println!(" Unstaged changes found:");
73 println!(" Files changed: {}", diff.len());
74 for file in diff.iter() {
75 println!(" - {} ({})", file.path.display(), file.status);
76 }
77 println!(" {}", diff.stats);
78 println!();
79
80 // Test 3: Stage some changes and show staged vs unstaged
81 println!("3. Staging README.md and checking staged diff:");
82 repo.add(&[&readme_path])?;
83
84 let staged_diff = repo.diff_staged()?;
85 println!(" Staged changes:");
86 for file in staged_diff.iter() {
87 println!(" - {} ({})", file.path.display(), file.status);
88 }
89 println!(" {}", staged_diff.stats);
90
91 let unstaged_diff = repo.diff()?;
92 println!(" Remaining unstaged changes:");
93 for file in unstaged_diff.iter() {
94 println!(" - {} ({})", file.path.display(), file.status);
95 }
96 println!(" {}", unstaged_diff.stats);
97 println!();
98
99 // Test 4: Diff with options
100 println!("4. Using diff options (name-only):");
101 let name_only_diff = repo.diff_with_options(&DiffOptions::new().name_only())?;
102 println!(" Modified files (name-only):");
103 for file in name_only_diff.iter() {
104 println!(" - {}", file.path.display());
105 }
106 println!();
107
108 // Test 5: Diff with file filtering
109 println!("5. Diff with path filtering (src/ only):");
110 let src_paths = vec![src_dir.clone()];
111 let filtered_diff = repo.diff_with_options(&DiffOptions::new().paths(src_paths))?;
112 println!(" Changes in src/ directory:");
113 for file in filtered_diff.iter() {
114 println!(" - {} ({})", file.path.display(), file.status);
115 }
116 println!();
117
118 // Stage remaining changes and commit
119 repo.add_all()?;
120 let second_commit = repo.commit("feat: add features section and improve main function")?;
121 println!("Second commit: {}", second_commit.short());
122
123 // Test 6: Diff between commits
124 println!("\n6. Diff between commits:");
125 let commit_diff = repo.diff_commits(&initial_commit, &second_commit)?;
126 println!(
127 " Changes from {} to {}:",
128 initial_commit.short(),
129 second_commit.short()
130 );
131 for file in commit_diff.iter() {
132 println!(
133 " - {} ({}) +{} -{}",
134 file.path.display(),
135 file.status,
136 file.additions,
137 file.deletions
138 );
139 }
140 println!(" {}", commit_diff.stats);
141 println!();
142
143 // Test 7: Add a new file and show it in diff
144 println!("7. Adding new file and checking diff:");
145 let test_path = repo_path.join("test.txt");
146 fs::write(
147 &test_path,
148 "This is a new test file.\nWith multiple lines.\n",
149 )
150 .unwrap();
151
152 let new_file_diff = repo.diff()?;
153 println!(" New file detected:");
154 for file in new_file_diff.iter() {
155 println!(" - {} ({})", file.path.display(), file.status);
156 }
157 println!();
158
159 // Test 8: Delete a file and show in diff
160 println!("8. Deleting file and checking diff:");
161 fs::remove_file(&lib_path).unwrap();
162
163 let deleted_file_diff = repo.diff()?;
164 println!(" Changes after file deletion:");
165 for file in deleted_file_diff.iter() {
166 println!(" - {} ({})", file.path.display(), file.status);
167 }
168 println!();
169
170 // Test 9: Diff with ignore whitespace options
171 println!("9. Testing whitespace options:");
172
173 // Add some whitespace changes
174 fs::write(&main_path, "fn main() {\n println!(\"Hello, world!\");\n println!(\"Testing diff operations!\"); \n}\n").unwrap();
175
176 let normal_diff = repo.diff()?;
177 let whitespace_diff = repo.diff_with_options(&DiffOptions::new().ignore_whitespace())?;
178
179 println!(" Normal diff shows {} files changed", normal_diff.len());
180 println!(
181 " Whitespace-ignoring diff shows {} files changed",
182 whitespace_diff.len()
183 );
184 println!();
185
186 // Test 10: Show diff with HEAD
187 println!("10. Diff with HEAD (all changes since last commit):");
188 let head_diff = repo.diff_head()?;
189 println!(" All changes since last commit:");
190 for file in head_diff.iter() {
191 println!(" - {} ({})", file.path.display(), file.status);
192 }
193 println!(" {}", head_diff.stats);
194 println!();
195
196 // Test 11: Different diff output formats
197 println!("11. Testing different output formats:");
198
199 let stat_diff = repo.diff_with_options(&DiffOptions::new().stat_only())?;
200 println!(" Stat format:");
201 println!(" {}", stat_diff);
202
203 let numstat_diff = repo.diff_with_options(&DiffOptions::new().numstat())?;
204 println!(" Numstat format - {} files changed", numstat_diff.len());
205 for file in numstat_diff.iter() {
206 println!(
207 " {} +{} -{}",
208 file.path.display(),
209 file.additions,
210 file.deletions
211 );
212 }
213 println!();
214
215 // Test 12: Filtering by file status
216 println!("12. Filtering files by status:");
217 let all_changes = repo.diff_head()?;
218
219 let added_files: Vec<_> = all_changes.files_with_status(DiffStatus::Added).collect();
220 let modified_files: Vec<_> = all_changes
221 .files_with_status(DiffStatus::Modified)
222 .collect();
223 let deleted_files: Vec<_> = all_changes.files_with_status(DiffStatus::Deleted).collect();
224
225 println!(" Added files: {}", added_files.len());
226 for file in added_files {
227 println!(" - {}", file.path.display());
228 }
229
230 println!(" Modified files: {}", modified_files.len());
231 for file in modified_files {
232 println!(" - {}", file.path.display());
233 }
234
235 println!(" Deleted files: {}", deleted_files.len());
236 for file in deleted_files {
237 println!(" - {}", file.path.display());
238 }
239 println!();
240
241 println!("=== Diff Operations Demo Complete ===");
242 println!("All diff operations completed successfully!");
243 println!("Summary of tested features:");
244 println!("✓ Basic diff operations (working dir vs index)");
245 println!("✓ Staged diff operations (index vs HEAD)");
246 println!("✓ Diff between specific commits");
247 println!("✓ Diff with various options (name-only, stat, numstat)");
248 println!("✓ Path filtering");
249 println!("✓ Whitespace handling options");
250 println!("✓ File status filtering");
251 println!("✓ Comprehensive diff statistics");
252
253 println!("\nCleaning up temporary repository...");
254 fs::remove_dir_all(&repo_path).ok();
255
256 Ok(())
257}
examples/tag_operations.rs (line 32)
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}
examples/stash_operations.rs (line 33)
17fn main() -> Result<()> {
18 println!("Rustic Git - Stash Operations Example\n");
19
20 // Use a temporary directory for this example
21 let repo_path = env::temp_dir().join("rustic_git_stash_example");
22
23 // Clean up any previous run
24 if repo_path.exists() {
25 fs::remove_dir_all(&repo_path).expect("Failed to clean up previous example");
26 }
27
28 println!("Initializing repository at: {}", repo_path.display());
29
30 // Initialize repository and configure user
31 let repo = Repository::init(&repo_path, false)?;
32 repo.config()
33 .set_user("Stash Demo User", "stash@example.com")?;
34
35 // Create initial commit to have a base
36 println!("\nCreating initial commit...");
37 fs::write(
38 repo_path.join("README.md"),
39 "# Stash Demo Project\n\nDemonstrating Git stash operations.\n",
40 )?;
41 repo.add(&["README.md"])?;
42 let initial_commit = repo.commit("Initial commit: Add README")?;
43 println!("Created initial commit: {}", initial_commit.short());
44
45 // Create some work to stash
46 println!("\n=== Creating Work to Stash ===");
47
48 // Create tracked file modifications
49 fs::write(
50 repo_path.join("README.md"),
51 "# Stash Demo Project\n\nDemonstrating Git stash operations.\n\nAdded some new content!\n",
52 )?;
53
54 // Create new tracked files
55 fs::create_dir_all(repo_path.join("src"))?;
56 fs::write(
57 repo_path.join("src/main.rs"),
58 "fn main() {\n println!(\"Hello, stash!\");\n}\n",
59 )?;
60
61 // Create untracked files
62 fs::write(
63 repo_path.join("untracked.txt"),
64 "This file is not tracked by git\n",
65 )?;
66 fs::write(repo_path.join("temp.log"), "Temporary log file\n")?;
67
68 // Stage some changes
69 repo.add(&["src/main.rs"])?;
70
71 println!("Created various types of changes:");
72 println!(" - Modified tracked file (README.md)");
73 println!(" - Added new file and staged it (src/main.rs)");
74 println!(" - Created untracked files (untracked.txt, temp.log)");
75
76 // Check repository status before stashing
77 let status = repo.status()?;
78 println!("\nRepository status before stashing:");
79 println!(" Staged files: {}", status.staged_files().count());
80 println!(" Unstaged files: {}", status.unstaged_files().count());
81 println!(" Untracked files: {}", status.untracked_entries().count());
82
83 // Demonstrate stash creation
84 println!("\n=== Creating Stashes ===");
85
86 // 1. Simple stash save
87 println!("\n1. Creating simple stash:");
88 let simple_stash = repo.stash_save("WIP: working on main function")?;
89 println!("Created stash: {}", simple_stash);
90 println!(" Index: {}", simple_stash.index);
91 println!(" Branch: {}", simple_stash.branch);
92 println!(" Hash: {}", simple_stash.hash.short());
93
94 // Check status after stash
95 let status_after_stash = repo.status()?;
96 println!("\nStatus after simple stash:");
97 println!(
98 " Staged files: {}",
99 status_after_stash.staged_files().count()
100 );
101 println!(
102 " Unstaged files: {}",
103 status_after_stash.unstaged_files().count()
104 );
105 println!(
106 " Untracked files: {}",
107 status_after_stash.untracked_entries().count()
108 );
109
110 // 2. Make more changes and create stash with untracked files
111 println!("\n2. Creating stash with untracked files:");
112
113 // Modify file again
114 fs::write(
115 repo_path.join("README.md"),
116 "# Stash Demo Project\n\nDemonstrating Git stash operations.\n\nSecond round of changes!\n",
117 )?;
118
119 // Create more untracked files
120 fs::write(repo_path.join("config.json"), "{\"debug\": true}\n")?;
121
122 let untracked_options = StashOptions::new().with_untracked().with_keep_index();
123 let untracked_stash = repo.stash_push(
124 "WIP: config changes with untracked files",
125 untracked_options,
126 )?;
127 println!("Created stash with untracked files: {}", untracked_stash);
128
129 // 3. Create stash with specific paths
130 println!("\n3. Creating stash with specific paths:");
131
132 // Make changes to multiple files and add them to git
133 fs::write(repo_path.join("file1.txt"), "Content for file 1\n")?;
134 fs::write(repo_path.join("file2.txt"), "Content for file 2\n")?;
135 fs::write(repo_path.join("file3.txt"), "Content for file 3\n")?;
136
137 // Add all files so they're tracked
138 repo.add(&["file1.txt", "file2.txt", "file3.txt"])?;
139
140 // Now modify them so there are changes to stash
141 fs::write(repo_path.join("file1.txt"), "Modified content for file 1\n")?;
142 fs::write(repo_path.join("file2.txt"), "Modified content for file 2\n")?;
143 fs::write(repo_path.join("file3.txt"), "Modified content for file 3\n")?;
144
145 let path_options = StashOptions::new().with_paths(vec!["file1.txt".into(), "file2.txt".into()]);
146 let path_stash = repo.stash_push("WIP: specific files only", path_options)?;
147 println!("Created stash with specific paths: {}", path_stash);
148
149 // Demonstrate stash listing and filtering
150 println!("\n=== Stash Listing and Filtering ===");
151
152 let stashes = repo.stash_list()?;
153 println!("\nAll stashes ({} total):", stashes.len());
154 for stash in stashes.iter() {
155 println!(
156 " [{}] {} -> {}",
157 stash.index,
158 stash.message,
159 stash.hash.short()
160 );
161 println!(
162 " Branch: {} | Created: {}",
163 stash.branch,
164 stash.timestamp.format("%Y-%m-%d %H:%M:%S")
165 );
166 }
167
168 // Test filtering
169 println!("\nFiltering examples:");
170
171 // Find stashes containing specific text
172 let wip_stashes: Vec<_> = stashes.find_containing("WIP").collect();
173 println!("Stashes containing 'WIP': {} found", wip_stashes.len());
174 for stash in &wip_stashes {
175 println!(" - {}", stash.message);
176 }
177
178 let config_stashes: Vec<_> = stashes.find_containing("config").collect();
179 println!(
180 "Stashes containing 'config': {} found",
181 config_stashes.len()
182 );
183
184 // Get latest stash
185 if let Some(latest) = stashes.latest() {
186 println!("Latest stash: {}", latest.message);
187 }
188
189 // Get specific stash by index
190 if let Some(second_stash) = stashes.get(1) {
191 println!("Second stash: {}", second_stash.message);
192 }
193
194 // Demonstrate stash content viewing
195 println!("\n=== Viewing Stash Contents ===");
196
197 println!("\nShowing contents of latest stash:");
198 let stash_contents = repo.stash_show(0)?;
199 println!("{}", stash_contents);
200
201 // Demonstrate stash application
202 println!("\n=== Applying and Popping Stashes ===");
203
204 println!("\n1. Testing stash apply (keeps stash in list):");
205 let stashes_before_apply = repo.stash_list()?;
206 println!("Stashes before apply: {}", stashes_before_apply.len());
207
208 // Apply the latest stash
209 repo.stash_apply(0, StashApplyOptions::new())?;
210 println!("Applied stash@{{0}}");
211
212 let stashes_after_apply = repo.stash_list()?;
213 println!("Stashes after apply: {}", stashes_after_apply.len());
214
215 // Check what was restored
216 let status_after_apply = repo.status()?;
217 println!("Status after apply:");
218 println!(
219 " Staged files: {}",
220 status_after_apply.staged_files().count()
221 );
222 println!(
223 " Unstaged files: {}",
224 status_after_apply.unstaged_files().count()
225 );
226 println!(
227 " Untracked files: {}",
228 status_after_apply.untracked_entries().count()
229 );
230
231 println!("\n2. Testing stash pop (removes stash from list):");
232
233 // First, stash current changes again to have something to pop
234 repo.stash_save("Temporary stash for pop test")?;
235
236 let stashes_before_pop = repo.stash_list()?;
237 println!("Stashes before pop: {}", stashes_before_pop.len());
238
239 // Pop the latest stash
240 repo.stash_pop(0, StashApplyOptions::new().with_quiet())?;
241 println!("Popped stash@{{0}}");
242
243 let stashes_after_pop = repo.stash_list()?;
244 println!("Stashes after pop: {}", stashes_after_pop.len());
245
246 // Demonstrate advanced apply options
247 println!("\n3. Testing apply with index restoration:");
248
249 // Create a stash with staged changes
250 fs::write(repo_path.join("staged_file.txt"), "This will be staged\n")?;
251 repo.add(&["staged_file.txt"])?;
252
253 fs::write(
254 repo_path.join("unstaged_file.txt"),
255 "This will be unstaged\n",
256 )?;
257
258 repo.stash_save("Stash with staged and unstaged changes")?;
259
260 // Apply with index restoration
261 let apply_options = StashApplyOptions::new().with_index();
262 repo.stash_apply(0, apply_options)?;
263 println!("Applied stash with index restoration");
264
265 let final_status = repo.status()?;
266 println!("Final status after index restoration:");
267 println!(" Staged files: {}", final_status.staged_files().count());
268 println!(
269 " Unstaged files: {}",
270 final_status.unstaged_files().count()
271 );
272
273 // Demonstrate stash management
274 println!("\n=== Stash Management ===");
275
276 // Create a few test stashes
277 for i in 1..=3 {
278 fs::write(
279 repo_path.join(format!("test{}.txt", i)),
280 format!("Test content {}\n", i),
281 )?;
282 repo.stash_save(&format!("Test stash {}", i))?;
283 }
284
285 let management_stashes = repo.stash_list()?;
286 println!(
287 "\nCreated {} test stashes for management demo",
288 management_stashes.len()
289 );
290
291 // Drop a specific stash
292 println!("\n1. Dropping middle stash:");
293 println!("Before drop: {} stashes", management_stashes.len());
294
295 repo.stash_drop(1)?; // Drop second stash (index 1)
296 println!("Dropped stash@{{1}}");
297
298 let after_drop = repo.stash_list()?;
299 println!("After drop: {} stashes", after_drop.len());
300
301 // Show remaining stashes
302 println!("Remaining stashes:");
303 for stash in after_drop.iter() {
304 println!(" [{}] {}", stash.index, stash.message);
305 }
306
307 // Clear all stashes
308 println!("\n2. Clearing all stashes:");
309 repo.stash_clear()?;
310 println!("Cleared all stashes");
311
312 let final_stashes = repo.stash_list()?;
313 println!("Stashes after clear: {}", final_stashes.len());
314
315 // Demonstrate error handling
316 println!("\n=== Error Handling ===");
317
318 println!("\n1. Testing operations on empty stash list:");
319
320 // Try to apply non-existent stash
321 match repo.stash_apply(0, StashApplyOptions::new()) {
322 Ok(_) => println!("ERROR: Should have failed to apply non-existent stash"),
323 Err(e) => println!("Expected error applying non-existent stash: {}", e),
324 }
325
326 // Try to show non-existent stash
327 match repo.stash_show(0) {
328 Ok(_) => println!("ERROR: Should have failed to show non-existent stash"),
329 Err(e) => println!("Expected error showing non-existent stash: {}", e),
330 }
331
332 // Try to drop non-existent stash
333 match repo.stash_drop(0) {
334 Ok(_) => println!("ERROR: Should have failed to drop non-existent stash"),
335 Err(e) => println!("Expected error dropping non-existent stash: {}", e),
336 }
337
338 // Summary
339 println!("\n=== Summary ===");
340 println!("\nStash operations demonstrated:");
341 println!(" ✓ Basic stash save and push with options");
342 println!(" ✓ Stash with untracked files and keep-index");
343 println!(" ✓ Stash specific paths only");
344 println!(" ✓ Comprehensive stash listing and filtering");
345 println!(" ✓ Stash content viewing");
346 println!(" ✓ Apply vs pop operations");
347 println!(" ✓ Index restoration during apply");
348 println!(" ✓ Stash dropping and clearing");
349 println!(" ✓ Error handling for edge cases");
350
351 println!("\nStash options demonstrated:");
352 println!(" ✓ with_untracked() - Include untracked files");
353 println!(" ✓ with_keep_index() - Keep staged changes");
354 println!(" ✓ with_paths() - Stash specific files only");
355 println!(" ✓ with_index() - Restore staged state on apply");
356 println!(" ✓ with_quiet() - Suppress output messages");
357
358 println!("\nStash filtering demonstrated:");
359 println!(" ✓ find_containing() - Search by message content");
360 println!(" ✓ latest() - Get most recent stash");
361 println!(" ✓ get() - Get stash by index");
362 println!(" ✓ for_branch() - Filter by branch name");
363
364 // Clean up
365 println!("\nCleaning up example repository...");
366 fs::remove_dir_all(&repo_path)?;
367 println!("Stash operations example completed successfully!");
368
369 Ok(())
370}
Additional examples can be found in:
Sourcepub fn get_user(&self) -> Result<(String, String)>
pub fn get_user(&self) -> Result<(String, String)>
Get the current git user configuration
Returns a tuple of (name, email) from the repository configuration.
§Returns
A tuple containing the user name and email, or an error if either configuration value is not set.
Examples found in repository?
examples/config_operations.rs (line 40)
14fn main() -> Result<()> {
15 println!("Rustic Git - Repository Configuration Operations Example\n");
16
17 // Use a temporary directory for this example
18 let repo_path = env::temp_dir().join("rustic_git_config_example");
19
20 // Clean up any previous run
21 if repo_path.exists() {
22 fs::remove_dir_all(&repo_path).expect("Failed to clean up previous example");
23 }
24
25 println!("Initializing new repository at: {}", repo_path.display());
26
27 // Initialize a new repository
28 let repo = Repository::init(&repo_path, false)?;
29
30 // ==================== USER CONFIGURATION ====================
31
32 println!("\n[CONFIG] Configuring git user settings...");
33
34 // Set user configuration (convenience method)
35 repo.config()
36 .set_user("Alice Developer", "alice@example.com")?;
37 println!("Set user configuration");
38
39 // Verify user configuration
40 let (name, email) = repo.config().get_user()?;
41 println!("Current user: {} <{}>", name, email);
42
43 // ==================== GENERAL CONFIGURATION ====================
44
45 println!("\n[CONFIG] Setting repository configuration values...");
46
47 // Set various git configuration values
48 repo.config().set("core.autocrlf", "false")?;
49 repo.config().set("core.ignorecase", "true")?;
50 repo.config().set("pull.rebase", "true")?;
51 repo.config().set("push.default", "simple")?;
52 repo.config().set("branch.autosetupmerge", "always")?;
53
54 println!("Set core configuration values");
55
56 // Get and display configuration values
57 println!("\n[CONFIG] Current repository configuration:");
58
59 let configs = [
60 "core.autocrlf",
61 "core.ignorecase",
62 "pull.rebase",
63 "push.default",
64 "branch.autosetupmerge",
65 ];
66
67 for config_key in &configs {
68 match repo.config().get(config_key) {
69 Ok(value) => println!(" {} = {}", config_key, value),
70 Err(_) => println!(" {} = <not set>", config_key),
71 }
72 }
73
74 // ==================== CONFIGURATION WITH COMMITS ====================
75
76 println!("\n[COMMIT] Testing configuration with commit operations...");
77
78 // Create a test file
79 let test_file_path = repo_path.join("test.txt");
80 fs::write(
81 &test_file_path,
82 "Hello from rustic-git configuration example!",
83 )?;
84 println!("Created test file: test.txt");
85
86 // Stage the file
87 repo.add(&["test.txt"])?;
88 println!("Staged test.txt");
89
90 // Create a commit (this will use our configured user)
91 let commit_hash = repo.commit("Add test file with configuration example")?;
92 println!("Created commit: {}", commit_hash.short());
93
94 // ==================== CONFIGURATION MODIFICATION ====================
95
96 println!("\n[UPDATE] Modifying configuration values...");
97
98 // Change some configuration values
99 repo.config().set("core.autocrlf", "true")?;
100 repo.config()
101 .set("user.email", "alice.developer@newcompany.com")?;
102
103 println!("Updated configuration values");
104
105 // Display updated values
106 let autocrlf = repo.config().get("core.autocrlf")?;
107 let (updated_name, updated_email) = repo.config().get_user()?;
108
109 println!("Updated configuration:");
110 println!(" core.autocrlf = {}", autocrlf);
111 println!(" user: {} <{}>", updated_name, updated_email);
112
113 // ==================== CONFIGURATION REMOVAL ====================
114
115 println!("\n[REMOVE] Removing configuration values...");
116
117 // Remove a configuration value
118 repo.config().unset("branch.autosetupmerge")?;
119 println!("Removed branch.autosetupmerge");
120
121 // Try to get the removed value (should fail)
122 match repo.config().get("branch.autosetupmerge") {
123 Ok(value) => println!("Unexpected: branch.autosetupmerge = {}", value),
124 Err(_) => println!("Confirmed: branch.autosetupmerge is not set"),
125 }
126
127 // ==================== ADVANCED CONFIGURATION ====================
128
129 println!("\n[ADVANCED] Setting advanced configuration...");
130
131 // Set some advanced git configuration
132 repo.config().set("diff.tool", "vimdiff")?;
133 repo.config().set("merge.tool", "vimdiff")?;
134 repo.config().set("alias.st", "status")?;
135 repo.config().set("alias.co", "checkout")?;
136 repo.config().set("alias.br", "branch")?;
137 repo.config().set("alias.ci", "commit")?;
138
139 println!("Set advanced configuration (diff/merge tools and aliases)");
140
141 // Display all custom configuration
142 println!("\n[SUMMARY] Complete repository configuration summary:");
143
144 let all_configs = [
145 ("User", vec![("user.name", ""), ("user.email", "")]),
146 ("Core", vec![("core.autocrlf", ""), ("core.ignorecase", "")]),
147 ("Workflow", vec![("pull.rebase", ""), ("push.default", "")]),
148 ("Tools", vec![("diff.tool", ""), ("merge.tool", "")]),
149 (
150 "Aliases",
151 vec![
152 ("alias.st", ""),
153 ("alias.co", ""),
154 ("alias.br", ""),
155 ("alias.ci", ""),
156 ],
157 ),
158 ];
159
160 for (category, configs) in &all_configs {
161 println!("\n {}:", category);
162 for (key, _) in configs {
163 match repo.config().get(key) {
164 Ok(value) => println!(" {} = {}", key, value),
165 Err(_) => println!(" {} = <not set>", key),
166 }
167 }
168 }
169
170 // ==================== PRACTICAL EXAMPLE ====================
171
172 println!("\n[TEAM] Practical example: Setting up repository for a team...");
173
174 // Configure repository for team development
175 repo.config().set("user.name", "Team Member")?;
176 repo.config().set("user.email", "team@company.com")?;
177 repo.config().set("core.autocrlf", "input")?;
178 repo.config().set("core.safecrlf", "true")?;
179 repo.config().set("pull.rebase", "true")?;
180 repo.config().set("push.default", "current")?;
181 repo.config().set("init.defaultBranch", "main")?;
182
183 println!("Configured repository for team development");
184
185 // Create another commit with the team configuration
186 fs::write(
187 repo_path.join("team.md"),
188 "# Team Development\n\nThis repository is configured for team development.",
189 )?;
190 repo.add(&["team.md"])?;
191 let team_commit = repo.commit("Add team development documentation")?;
192
193 println!("Created team commit: {}", team_commit.short());
194
195 // Final verification
196 let (final_name, final_email) = repo.config().get_user()?;
197 println!("\n[FINAL] Final repository configuration:");
198 println!(" User: {} <{}>", final_name, final_email);
199 println!(" Repository configured for team development workflow");
200
201 // ==================== CLEANUP ====================
202
203 println!("\n[CLEANUP] Cleaning up...");
204 fs::remove_dir_all(&repo_path).expect("Failed to clean up example");
205 println!("Example completed successfully!");
206
207 Ok(())
208}
Sourcepub fn set(&self, key: &str, value: &str) -> Result<()>
pub fn set(&self, key: &str, value: &str) -> Result<()>
Set a git configuration value for this repository
§Arguments
key
- The configuration key (e.g., “user.name”, “core.autocrlf”)value
- The value to set
§Example
use rustic_git::Repository;
use std::{env, fs};
let test_path = env::temp_dir().join("config_set_test");
if test_path.exists() {
fs::remove_dir_all(&test_path).unwrap();
}
let repo = Repository::init(&test_path, false)?;
repo.config().set("core.autocrlf", "false")?;
repo.config().set("user.name", "Jane Doe")?;
// Clean up
fs::remove_dir_all(&test_path).unwrap();
Examples found in repository?
examples/config_operations.rs (line 48)
14fn main() -> Result<()> {
15 println!("Rustic Git - Repository Configuration Operations Example\n");
16
17 // Use a temporary directory for this example
18 let repo_path = env::temp_dir().join("rustic_git_config_example");
19
20 // Clean up any previous run
21 if repo_path.exists() {
22 fs::remove_dir_all(&repo_path).expect("Failed to clean up previous example");
23 }
24
25 println!("Initializing new repository at: {}", repo_path.display());
26
27 // Initialize a new repository
28 let repo = Repository::init(&repo_path, false)?;
29
30 // ==================== USER CONFIGURATION ====================
31
32 println!("\n[CONFIG] Configuring git user settings...");
33
34 // Set user configuration (convenience method)
35 repo.config()
36 .set_user("Alice Developer", "alice@example.com")?;
37 println!("Set user configuration");
38
39 // Verify user configuration
40 let (name, email) = repo.config().get_user()?;
41 println!("Current user: {} <{}>", name, email);
42
43 // ==================== GENERAL CONFIGURATION ====================
44
45 println!("\n[CONFIG] Setting repository configuration values...");
46
47 // Set various git configuration values
48 repo.config().set("core.autocrlf", "false")?;
49 repo.config().set("core.ignorecase", "true")?;
50 repo.config().set("pull.rebase", "true")?;
51 repo.config().set("push.default", "simple")?;
52 repo.config().set("branch.autosetupmerge", "always")?;
53
54 println!("Set core configuration values");
55
56 // Get and display configuration values
57 println!("\n[CONFIG] Current repository configuration:");
58
59 let configs = [
60 "core.autocrlf",
61 "core.ignorecase",
62 "pull.rebase",
63 "push.default",
64 "branch.autosetupmerge",
65 ];
66
67 for config_key in &configs {
68 match repo.config().get(config_key) {
69 Ok(value) => println!(" {} = {}", config_key, value),
70 Err(_) => println!(" {} = <not set>", config_key),
71 }
72 }
73
74 // ==================== CONFIGURATION WITH COMMITS ====================
75
76 println!("\n[COMMIT] Testing configuration with commit operations...");
77
78 // Create a test file
79 let test_file_path = repo_path.join("test.txt");
80 fs::write(
81 &test_file_path,
82 "Hello from rustic-git configuration example!",
83 )?;
84 println!("Created test file: test.txt");
85
86 // Stage the file
87 repo.add(&["test.txt"])?;
88 println!("Staged test.txt");
89
90 // Create a commit (this will use our configured user)
91 let commit_hash = repo.commit("Add test file with configuration example")?;
92 println!("Created commit: {}", commit_hash.short());
93
94 // ==================== CONFIGURATION MODIFICATION ====================
95
96 println!("\n[UPDATE] Modifying configuration values...");
97
98 // Change some configuration values
99 repo.config().set("core.autocrlf", "true")?;
100 repo.config()
101 .set("user.email", "alice.developer@newcompany.com")?;
102
103 println!("Updated configuration values");
104
105 // Display updated values
106 let autocrlf = repo.config().get("core.autocrlf")?;
107 let (updated_name, updated_email) = repo.config().get_user()?;
108
109 println!("Updated configuration:");
110 println!(" core.autocrlf = {}", autocrlf);
111 println!(" user: {} <{}>", updated_name, updated_email);
112
113 // ==================== CONFIGURATION REMOVAL ====================
114
115 println!("\n[REMOVE] Removing configuration values...");
116
117 // Remove a configuration value
118 repo.config().unset("branch.autosetupmerge")?;
119 println!("Removed branch.autosetupmerge");
120
121 // Try to get the removed value (should fail)
122 match repo.config().get("branch.autosetupmerge") {
123 Ok(value) => println!("Unexpected: branch.autosetupmerge = {}", value),
124 Err(_) => println!("Confirmed: branch.autosetupmerge is not set"),
125 }
126
127 // ==================== ADVANCED CONFIGURATION ====================
128
129 println!("\n[ADVANCED] Setting advanced configuration...");
130
131 // Set some advanced git configuration
132 repo.config().set("diff.tool", "vimdiff")?;
133 repo.config().set("merge.tool", "vimdiff")?;
134 repo.config().set("alias.st", "status")?;
135 repo.config().set("alias.co", "checkout")?;
136 repo.config().set("alias.br", "branch")?;
137 repo.config().set("alias.ci", "commit")?;
138
139 println!("Set advanced configuration (diff/merge tools and aliases)");
140
141 // Display all custom configuration
142 println!("\n[SUMMARY] Complete repository configuration summary:");
143
144 let all_configs = [
145 ("User", vec![("user.name", ""), ("user.email", "")]),
146 ("Core", vec![("core.autocrlf", ""), ("core.ignorecase", "")]),
147 ("Workflow", vec![("pull.rebase", ""), ("push.default", "")]),
148 ("Tools", vec![("diff.tool", ""), ("merge.tool", "")]),
149 (
150 "Aliases",
151 vec![
152 ("alias.st", ""),
153 ("alias.co", ""),
154 ("alias.br", ""),
155 ("alias.ci", ""),
156 ],
157 ),
158 ];
159
160 for (category, configs) in &all_configs {
161 println!("\n {}:", category);
162 for (key, _) in configs {
163 match repo.config().get(key) {
164 Ok(value) => println!(" {} = {}", key, value),
165 Err(_) => println!(" {} = <not set>", key),
166 }
167 }
168 }
169
170 // ==================== PRACTICAL EXAMPLE ====================
171
172 println!("\n[TEAM] Practical example: Setting up repository for a team...");
173
174 // Configure repository for team development
175 repo.config().set("user.name", "Team Member")?;
176 repo.config().set("user.email", "team@company.com")?;
177 repo.config().set("core.autocrlf", "input")?;
178 repo.config().set("core.safecrlf", "true")?;
179 repo.config().set("pull.rebase", "true")?;
180 repo.config().set("push.default", "current")?;
181 repo.config().set("init.defaultBranch", "main")?;
182
183 println!("Configured repository for team development");
184
185 // Create another commit with the team configuration
186 fs::write(
187 repo_path.join("team.md"),
188 "# Team Development\n\nThis repository is configured for team development.",
189 )?;
190 repo.add(&["team.md"])?;
191 let team_commit = repo.commit("Add team development documentation")?;
192
193 println!("Created team commit: {}", team_commit.short());
194
195 // Final verification
196 let (final_name, final_email) = repo.config().get_user()?;
197 println!("\n[FINAL] Final repository configuration:");
198 println!(" User: {} <{}>", final_name, final_email);
199 println!(" Repository configured for team development workflow");
200
201 // ==================== CLEANUP ====================
202
203 println!("\n[CLEANUP] Cleaning up...");
204 fs::remove_dir_all(&repo_path).expect("Failed to clean up example");
205 println!("Example completed successfully!");
206
207 Ok(())
208}
Sourcepub fn get(&self, key: &str) -> Result<String>
pub fn get(&self, key: &str) -> Result<String>
Get a git configuration value from this repository
§Arguments
key
- The configuration key to retrieve
§Returns
The configuration value as a string, or an error if the key is not found.
§Example
use rustic_git::Repository;
use std::{env, fs};
let test_path = env::temp_dir().join("config_get_test");
if test_path.exists() {
fs::remove_dir_all(&test_path).unwrap();
}
let repo = Repository::init(&test_path, false)?;
repo.config().set("user.name", "Jane Doe")?;
let name = repo.config().get("user.name")?;
assert_eq!(name, "Jane Doe");
// Clean up
fs::remove_dir_all(&test_path).unwrap();
Examples found in repository?
examples/config_operations.rs (line 68)
14fn main() -> Result<()> {
15 println!("Rustic Git - Repository Configuration Operations Example\n");
16
17 // Use a temporary directory for this example
18 let repo_path = env::temp_dir().join("rustic_git_config_example");
19
20 // Clean up any previous run
21 if repo_path.exists() {
22 fs::remove_dir_all(&repo_path).expect("Failed to clean up previous example");
23 }
24
25 println!("Initializing new repository at: {}", repo_path.display());
26
27 // Initialize a new repository
28 let repo = Repository::init(&repo_path, false)?;
29
30 // ==================== USER CONFIGURATION ====================
31
32 println!("\n[CONFIG] Configuring git user settings...");
33
34 // Set user configuration (convenience method)
35 repo.config()
36 .set_user("Alice Developer", "alice@example.com")?;
37 println!("Set user configuration");
38
39 // Verify user configuration
40 let (name, email) = repo.config().get_user()?;
41 println!("Current user: {} <{}>", name, email);
42
43 // ==================== GENERAL CONFIGURATION ====================
44
45 println!("\n[CONFIG] Setting repository configuration values...");
46
47 // Set various git configuration values
48 repo.config().set("core.autocrlf", "false")?;
49 repo.config().set("core.ignorecase", "true")?;
50 repo.config().set("pull.rebase", "true")?;
51 repo.config().set("push.default", "simple")?;
52 repo.config().set("branch.autosetupmerge", "always")?;
53
54 println!("Set core configuration values");
55
56 // Get and display configuration values
57 println!("\n[CONFIG] Current repository configuration:");
58
59 let configs = [
60 "core.autocrlf",
61 "core.ignorecase",
62 "pull.rebase",
63 "push.default",
64 "branch.autosetupmerge",
65 ];
66
67 for config_key in &configs {
68 match repo.config().get(config_key) {
69 Ok(value) => println!(" {} = {}", config_key, value),
70 Err(_) => println!(" {} = <not set>", config_key),
71 }
72 }
73
74 // ==================== CONFIGURATION WITH COMMITS ====================
75
76 println!("\n[COMMIT] Testing configuration with commit operations...");
77
78 // Create a test file
79 let test_file_path = repo_path.join("test.txt");
80 fs::write(
81 &test_file_path,
82 "Hello from rustic-git configuration example!",
83 )?;
84 println!("Created test file: test.txt");
85
86 // Stage the file
87 repo.add(&["test.txt"])?;
88 println!("Staged test.txt");
89
90 // Create a commit (this will use our configured user)
91 let commit_hash = repo.commit("Add test file with configuration example")?;
92 println!("Created commit: {}", commit_hash.short());
93
94 // ==================== CONFIGURATION MODIFICATION ====================
95
96 println!("\n[UPDATE] Modifying configuration values...");
97
98 // Change some configuration values
99 repo.config().set("core.autocrlf", "true")?;
100 repo.config()
101 .set("user.email", "alice.developer@newcompany.com")?;
102
103 println!("Updated configuration values");
104
105 // Display updated values
106 let autocrlf = repo.config().get("core.autocrlf")?;
107 let (updated_name, updated_email) = repo.config().get_user()?;
108
109 println!("Updated configuration:");
110 println!(" core.autocrlf = {}", autocrlf);
111 println!(" user: {} <{}>", updated_name, updated_email);
112
113 // ==================== CONFIGURATION REMOVAL ====================
114
115 println!("\n[REMOVE] Removing configuration values...");
116
117 // Remove a configuration value
118 repo.config().unset("branch.autosetupmerge")?;
119 println!("Removed branch.autosetupmerge");
120
121 // Try to get the removed value (should fail)
122 match repo.config().get("branch.autosetupmerge") {
123 Ok(value) => println!("Unexpected: branch.autosetupmerge = {}", value),
124 Err(_) => println!("Confirmed: branch.autosetupmerge is not set"),
125 }
126
127 // ==================== ADVANCED CONFIGURATION ====================
128
129 println!("\n[ADVANCED] Setting advanced configuration...");
130
131 // Set some advanced git configuration
132 repo.config().set("diff.tool", "vimdiff")?;
133 repo.config().set("merge.tool", "vimdiff")?;
134 repo.config().set("alias.st", "status")?;
135 repo.config().set("alias.co", "checkout")?;
136 repo.config().set("alias.br", "branch")?;
137 repo.config().set("alias.ci", "commit")?;
138
139 println!("Set advanced configuration (diff/merge tools and aliases)");
140
141 // Display all custom configuration
142 println!("\n[SUMMARY] Complete repository configuration summary:");
143
144 let all_configs = [
145 ("User", vec![("user.name", ""), ("user.email", "")]),
146 ("Core", vec![("core.autocrlf", ""), ("core.ignorecase", "")]),
147 ("Workflow", vec![("pull.rebase", ""), ("push.default", "")]),
148 ("Tools", vec![("diff.tool", ""), ("merge.tool", "")]),
149 (
150 "Aliases",
151 vec![
152 ("alias.st", ""),
153 ("alias.co", ""),
154 ("alias.br", ""),
155 ("alias.ci", ""),
156 ],
157 ),
158 ];
159
160 for (category, configs) in &all_configs {
161 println!("\n {}:", category);
162 for (key, _) in configs {
163 match repo.config().get(key) {
164 Ok(value) => println!(" {} = {}", key, value),
165 Err(_) => println!(" {} = <not set>", key),
166 }
167 }
168 }
169
170 // ==================== PRACTICAL EXAMPLE ====================
171
172 println!("\n[TEAM] Practical example: Setting up repository for a team...");
173
174 // Configure repository for team development
175 repo.config().set("user.name", "Team Member")?;
176 repo.config().set("user.email", "team@company.com")?;
177 repo.config().set("core.autocrlf", "input")?;
178 repo.config().set("core.safecrlf", "true")?;
179 repo.config().set("pull.rebase", "true")?;
180 repo.config().set("push.default", "current")?;
181 repo.config().set("init.defaultBranch", "main")?;
182
183 println!("Configured repository for team development");
184
185 // Create another commit with the team configuration
186 fs::write(
187 repo_path.join("team.md"),
188 "# Team Development\n\nThis repository is configured for team development.",
189 )?;
190 repo.add(&["team.md"])?;
191 let team_commit = repo.commit("Add team development documentation")?;
192
193 println!("Created team commit: {}", team_commit.short());
194
195 // Final verification
196 let (final_name, final_email) = repo.config().get_user()?;
197 println!("\n[FINAL] Final repository configuration:");
198 println!(" User: {} <{}>", final_name, final_email);
199 println!(" Repository configured for team development workflow");
200
201 // ==================== CLEANUP ====================
202
203 println!("\n[CLEANUP] Cleaning up...");
204 fs::remove_dir_all(&repo_path).expect("Failed to clean up example");
205 println!("Example completed successfully!");
206
207 Ok(())
208}
Sourcepub fn unset(&self, key: &str) -> Result<()>
pub fn unset(&self, key: &str) -> Result<()>
Remove a git configuration value from this repository
§Arguments
key
- The configuration key to remove
§Example
use rustic_git::Repository;
use std::{env, fs};
let test_path = env::temp_dir().join("config_unset_test");
if test_path.exists() {
fs::remove_dir_all(&test_path).unwrap();
}
let repo = Repository::init(&test_path, false)?;
repo.config().set("test.value", "temporary")?;
repo.config().unset("test.value")?;
// Clean up
fs::remove_dir_all(&test_path).unwrap();
Examples found in repository?
examples/config_operations.rs (line 118)
14fn main() -> Result<()> {
15 println!("Rustic Git - Repository Configuration Operations Example\n");
16
17 // Use a temporary directory for this example
18 let repo_path = env::temp_dir().join("rustic_git_config_example");
19
20 // Clean up any previous run
21 if repo_path.exists() {
22 fs::remove_dir_all(&repo_path).expect("Failed to clean up previous example");
23 }
24
25 println!("Initializing new repository at: {}", repo_path.display());
26
27 // Initialize a new repository
28 let repo = Repository::init(&repo_path, false)?;
29
30 // ==================== USER CONFIGURATION ====================
31
32 println!("\n[CONFIG] Configuring git user settings...");
33
34 // Set user configuration (convenience method)
35 repo.config()
36 .set_user("Alice Developer", "alice@example.com")?;
37 println!("Set user configuration");
38
39 // Verify user configuration
40 let (name, email) = repo.config().get_user()?;
41 println!("Current user: {} <{}>", name, email);
42
43 // ==================== GENERAL CONFIGURATION ====================
44
45 println!("\n[CONFIG] Setting repository configuration values...");
46
47 // Set various git configuration values
48 repo.config().set("core.autocrlf", "false")?;
49 repo.config().set("core.ignorecase", "true")?;
50 repo.config().set("pull.rebase", "true")?;
51 repo.config().set("push.default", "simple")?;
52 repo.config().set("branch.autosetupmerge", "always")?;
53
54 println!("Set core configuration values");
55
56 // Get and display configuration values
57 println!("\n[CONFIG] Current repository configuration:");
58
59 let configs = [
60 "core.autocrlf",
61 "core.ignorecase",
62 "pull.rebase",
63 "push.default",
64 "branch.autosetupmerge",
65 ];
66
67 for config_key in &configs {
68 match repo.config().get(config_key) {
69 Ok(value) => println!(" {} = {}", config_key, value),
70 Err(_) => println!(" {} = <not set>", config_key),
71 }
72 }
73
74 // ==================== CONFIGURATION WITH COMMITS ====================
75
76 println!("\n[COMMIT] Testing configuration with commit operations...");
77
78 // Create a test file
79 let test_file_path = repo_path.join("test.txt");
80 fs::write(
81 &test_file_path,
82 "Hello from rustic-git configuration example!",
83 )?;
84 println!("Created test file: test.txt");
85
86 // Stage the file
87 repo.add(&["test.txt"])?;
88 println!("Staged test.txt");
89
90 // Create a commit (this will use our configured user)
91 let commit_hash = repo.commit("Add test file with configuration example")?;
92 println!("Created commit: {}", commit_hash.short());
93
94 // ==================== CONFIGURATION MODIFICATION ====================
95
96 println!("\n[UPDATE] Modifying configuration values...");
97
98 // Change some configuration values
99 repo.config().set("core.autocrlf", "true")?;
100 repo.config()
101 .set("user.email", "alice.developer@newcompany.com")?;
102
103 println!("Updated configuration values");
104
105 // Display updated values
106 let autocrlf = repo.config().get("core.autocrlf")?;
107 let (updated_name, updated_email) = repo.config().get_user()?;
108
109 println!("Updated configuration:");
110 println!(" core.autocrlf = {}", autocrlf);
111 println!(" user: {} <{}>", updated_name, updated_email);
112
113 // ==================== CONFIGURATION REMOVAL ====================
114
115 println!("\n[REMOVE] Removing configuration values...");
116
117 // Remove a configuration value
118 repo.config().unset("branch.autosetupmerge")?;
119 println!("Removed branch.autosetupmerge");
120
121 // Try to get the removed value (should fail)
122 match repo.config().get("branch.autosetupmerge") {
123 Ok(value) => println!("Unexpected: branch.autosetupmerge = {}", value),
124 Err(_) => println!("Confirmed: branch.autosetupmerge is not set"),
125 }
126
127 // ==================== ADVANCED CONFIGURATION ====================
128
129 println!("\n[ADVANCED] Setting advanced configuration...");
130
131 // Set some advanced git configuration
132 repo.config().set("diff.tool", "vimdiff")?;
133 repo.config().set("merge.tool", "vimdiff")?;
134 repo.config().set("alias.st", "status")?;
135 repo.config().set("alias.co", "checkout")?;
136 repo.config().set("alias.br", "branch")?;
137 repo.config().set("alias.ci", "commit")?;
138
139 println!("Set advanced configuration (diff/merge tools and aliases)");
140
141 // Display all custom configuration
142 println!("\n[SUMMARY] Complete repository configuration summary:");
143
144 let all_configs = [
145 ("User", vec![("user.name", ""), ("user.email", "")]),
146 ("Core", vec![("core.autocrlf", ""), ("core.ignorecase", "")]),
147 ("Workflow", vec![("pull.rebase", ""), ("push.default", "")]),
148 ("Tools", vec![("diff.tool", ""), ("merge.tool", "")]),
149 (
150 "Aliases",
151 vec![
152 ("alias.st", ""),
153 ("alias.co", ""),
154 ("alias.br", ""),
155 ("alias.ci", ""),
156 ],
157 ),
158 ];
159
160 for (category, configs) in &all_configs {
161 println!("\n {}:", category);
162 for (key, _) in configs {
163 match repo.config().get(key) {
164 Ok(value) => println!(" {} = {}", key, value),
165 Err(_) => println!(" {} = <not set>", key),
166 }
167 }
168 }
169
170 // ==================== PRACTICAL EXAMPLE ====================
171
172 println!("\n[TEAM] Practical example: Setting up repository for a team...");
173
174 // Configure repository for team development
175 repo.config().set("user.name", "Team Member")?;
176 repo.config().set("user.email", "team@company.com")?;
177 repo.config().set("core.autocrlf", "input")?;
178 repo.config().set("core.safecrlf", "true")?;
179 repo.config().set("pull.rebase", "true")?;
180 repo.config().set("push.default", "current")?;
181 repo.config().set("init.defaultBranch", "main")?;
182
183 println!("Configured repository for team development");
184
185 // Create another commit with the team configuration
186 fs::write(
187 repo_path.join("team.md"),
188 "# Team Development\n\nThis repository is configured for team development.",
189 )?;
190 repo.add(&["team.md"])?;
191 let team_commit = repo.commit("Add team development documentation")?;
192
193 println!("Created team commit: {}", team_commit.short());
194
195 // Final verification
196 let (final_name, final_email) = repo.config().get_user()?;
197 println!("\n[FINAL] Final repository configuration:");
198 println!(" User: {} <{}>", final_name, final_email);
199 println!(" Repository configured for team development workflow");
200
201 // ==================== CLEANUP ====================
202
203 println!("\n[CLEANUP] Cleaning up...");
204 fs::remove_dir_all(&repo_path).expect("Failed to clean up example");
205 println!("Example completed successfully!");
206
207 Ok(())
208}
Auto Trait Implementations§
impl<'a> Freeze for RepoConfig<'a>
impl<'a> RefUnwindSafe for RepoConfig<'a>
impl<'a> Send for RepoConfig<'a>
impl<'a> Sync for RepoConfig<'a>
impl<'a> Unpin for RepoConfig<'a>
impl<'a> UnwindSafe for RepoConfig<'a>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more