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/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}
More examples
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/file_lifecycle_operations.rs (line 36)
16fn main() -> Result<()> {
17 println!("Rustic Git - File Lifecycle Operations Example\n");
18
19 let base_path = env::temp_dir().join("rustic_git_files_example");
20 let repo_path = base_path.join("main_repo");
21
22 // Clean up any previous runs
23 if base_path.exists() {
24 fs::remove_dir_all(&base_path).expect("Failed to clean up previous example");
25 }
26 fs::create_dir_all(&base_path)?;
27
28 println!("=== Repository Setup ===\n");
29
30 // Initialize repository
31 println!("Initializing repository for file lifecycle demonstrations...");
32 let repo = Repository::init(&repo_path, false)?;
33 println!("Repository initialized at: {}", repo_path.display());
34
35 // Set up git configuration for commits
36 repo.config().set_user("Demo User", "demo@example.com")?;
37
38 // Create initial project structure
39 fs::create_dir_all(repo_path.join("src"))?;
40 fs::create_dir_all(repo_path.join("docs"))?;
41 fs::create_dir_all(repo_path.join("tests"))?;
42
43 let files = [
44 (
45 "README.md",
46 "# File Lifecycle Demo\n\nDemonstrating rustic-git file management capabilities.",
47 ),
48 (
49 "src/main.rs",
50 "fn main() {\n println!(\"Hello, world!\");\n}",
51 ),
52 (
53 "src/lib.rs",
54 "//! Library module\n\npub fn greet() {\n println!(\"Hello from lib!\");\n}",
55 ),
56 ("docs/guide.md", "# User Guide\n\nThis is the user guide."),
57 (
58 "tests/integration.rs",
59 "#[test]\nfn test_basic() {\n assert_eq!(2 + 2, 4);\n}",
60 ),
61 ];
62
63 for (path, content) in &files {
64 fs::write(repo_path.join(path), content)?;
65 }
66
67 repo.add(&files.iter().map(|(path, _)| *path).collect::<Vec<_>>())?;
68 let initial_commit = repo.commit("Initial project setup")?;
69 println!("Created initial commit: {}\n", initial_commit.short());
70
71 println!("=== File Restoration Operations ===\n");
72
73 // Modify some files
74 println!("Modifying files to demonstrate restoration...");
75 fs::write(
76 repo_path.join("README.md"),
77 "# Modified README\n\nThis content has been changed.",
78 )?;
79 fs::write(
80 repo_path.join("src/main.rs"),
81 "fn main() {\n println!(\"Modified main!\");\n println!(\"Added new line!\");\n}",
82 )?;
83
84 println!(" Modified README.md and src/main.rs");
85
86 // Show current status
87 let status = repo.status()?;
88 println!(
89 " Files with modifications: {}",
90 status.unstaged_files().count()
91 );
92 for entry in status.unstaged_files() {
93 println!(" - {}", entry.path.display());
94 }
95 println!();
96
97 // Restore single file with checkout_file
98 println!("Restoring README.md using checkout_file():");
99 repo.checkout_file("README.md")?;
100 let restored_content = fs::read_to_string(repo_path.join("README.md"))?;
101 println!(" ✓ README.md restored to original state");
102 println!(
103 " Content preview: {:?}",
104 restored_content.lines().next().unwrap_or("")
105 );
106 println!();
107
108 // Demonstrate advanced restore with options
109 println!("Creating second commit for restore demonstration...");
110 fs::write(
111 repo_path.join("src/advanced.rs"),
112 "//! Advanced module\n\npub fn advanced_function() {\n println!(\"Advanced functionality\");\n}",
113 )?;
114 repo.add(&["src/advanced.rs"])?;
115 let second_commit = repo.commit("Add advanced module")?;
116 println!(" Second commit: {}", second_commit.short());
117
118 // Modify the advanced file
119 fs::write(
120 repo_path.join("src/advanced.rs"),
121 "//! HEAVILY MODIFIED\n\npub fn broken_function() {\n panic!(\"This is broken!\");\n}",
122 )?;
123 println!(" Modified src/advanced.rs");
124
125 // Restore from specific commit using restore with options
126 println!("Restoring src/advanced.rs from specific commit using restore():");
127 let restore_options = RestoreOptions::new()
128 .with_source(format!("{}", second_commit))
129 .with_worktree();
130 repo.restore(&["src/advanced.rs"], restore_options)?;
131
132 let restored_advanced = fs::read_to_string(repo_path.join("src/advanced.rs"))?;
133 println!(" ✓ File restored from commit {}", second_commit.short());
134 println!(
135 " Content preview: {:?}",
136 restored_advanced.lines().next().unwrap_or("")
137 );
138 println!();
139
140 println!("=== Staging Area Operations ===\n");
141
142 // Modify and stage files
143 println!("Demonstrating staging area manipulation...");
144 fs::write(
145 repo_path.join("src/lib.rs"),
146 "//! STAGED CHANGES\n\npub fn new_function() {\n println!(\"This will be staged\");\n}",
147 )?;
148 repo.add(&["src/lib.rs"])?;
149 println!(" Modified and staged src/lib.rs");
150
151 let status = repo.status()?;
152 println!(" Staged files: {}", status.staged_files().count());
153 for entry in status.staged_files() {
154 println!(" - {}", entry.path.display());
155 }
156
157 // Unstage the file
158 println!("Unstaging src/lib.rs using reset_file():");
159 repo.reset_file("src/lib.rs")?;
160
161 let status_after_reset = repo.status()?;
162 println!(" ✓ File unstaged (now in modified files)");
163 println!(
164 " Staged files: {}",
165 status_after_reset.staged_files().count()
166 );
167 println!(
168 " Modified files: {}",
169 status_after_reset.unstaged_files().count()
170 );
171 println!();
172
173 println!("=== File Removal Operations ===\n");
174
175 // Create files for removal demonstration
176 println!("Creating files for removal demonstration...");
177 fs::write(repo_path.join("temp_file.txt"), "This is a temporary file")?;
178 fs::write(
179 repo_path.join("docs/old_doc.md"),
180 "# Old Documentation\n\nThis document is outdated.",
181 )?;
182 fs::create_dir_all(repo_path.join("old_directory"))?;
183 fs::write(
184 repo_path.join("old_directory/nested_file.txt"),
185 "Nested content",
186 )?;
187
188 // Add and commit these files
189 repo.add(&[
190 "temp_file.txt",
191 "docs/old_doc.md",
192 "old_directory/nested_file.txt",
193 ])?;
194 repo.commit("Add files for removal demo")?;
195 println!(" Created and committed files for removal");
196
197 // Basic file removal
198 println!("Removing temp_file.txt using rm():");
199 repo.rm(&["temp_file.txt"])?;
200 println!(" ✓ temp_file.txt removed from repository and working tree");
201 assert!(!repo_path.join("temp_file.txt").exists());
202
203 // Remove from index only (keep in working tree)
204 println!("Removing docs/old_doc.md from index only using rm_with_options():");
205 let cached_remove_options = RemoveOptions::new().with_cached();
206 repo.rm_with_options(&["docs/old_doc.md"], cached_remove_options)?;
207
208 println!(" ✓ File removed from index but kept in working tree");
209 assert!(repo_path.join("docs/old_doc.md").exists());
210 let content = fs::read_to_string(repo_path.join("docs/old_doc.md"))?;
211 println!(
212 " Working tree content still available: {:?}",
213 content.lines().next().unwrap_or("")
214 );
215
216 // Recursive removal
217 println!("Removing old_directory/ recursively:");
218 let recursive_options = RemoveOptions::new().with_recursive();
219 repo.rm_with_options(&["old_directory/"], recursive_options)?;
220 println!(" ✓ Directory and contents removed recursively");
221 assert!(!repo_path.join("old_directory").exists());
222 println!();
223
224 println!("=== File Move/Rename Operations ===\n");
225
226 // Create files for move demonstration
227 println!("Creating files for move/rename demonstration...");
228 fs::write(repo_path.join("old_name.txt"), "This file will be renamed")?;
229 fs::create_dir_all(repo_path.join("source_dir"))?;
230 fs::write(
231 repo_path.join("source_dir/movable.txt"),
232 "This file will be moved",
233 )?;
234 fs::create_dir_all(repo_path.join("target_dir"))?;
235
236 repo.add(&["old_name.txt", "source_dir/movable.txt"])?;
237 repo.commit("Add files for move demo")?;
238 println!(" Created files for move demonstration");
239
240 // Simple rename
241 println!("Renaming old_name.txt to new_name.txt using mv():");
242 repo.mv("old_name.txt", "new_name.txt")?;
243
244 assert!(!repo_path.join("old_name.txt").exists());
245 assert!(repo_path.join("new_name.txt").exists());
246 let content = fs::read_to_string(repo_path.join("new_name.txt"))?;
247 println!(" ✓ File renamed successfully");
248 println!(" Content preserved: {:?}", content.trim());
249
250 // Move file to different directory
251 println!("Moving source_dir/movable.txt to target_dir/ using mv():");
252 repo.mv("source_dir/movable.txt", "target_dir/movable.txt")?;
253
254 assert!(!repo_path.join("source_dir/movable.txt").exists());
255 assert!(repo_path.join("target_dir/movable.txt").exists());
256 println!(" ✓ File moved to different directory");
257
258 // Demonstrate move with options (dry run)
259 fs::write(repo_path.join("test_move.txt"), "Test content for dry run")?;
260 repo.add(&["test_move.txt"])?;
261 repo.commit("Add test file for dry run demo")?;
262
263 println!("Demonstrating dry run move (won't actually move):");
264 let dry_run_options = MoveOptions::new().with_dry_run().with_verbose();
265 repo.mv_with_options("test_move.txt", "would_be_moved.txt", dry_run_options)?;
266
267 // File should still exist at original location
268 assert!(repo_path.join("test_move.txt").exists());
269 assert!(!repo_path.join("would_be_moved.txt").exists());
270 println!(" ✓ Dry run completed - no actual move performed");
271 println!();
272
273 println!("=== .gitignore Management ===\n");
274
275 // Initially no ignore patterns
276 println!("Checking initial .gitignore state:");
277 let initial_patterns = repo.ignore_list()?;
278 println!(" Initial ignore patterns: {}", initial_patterns.len());
279
280 // Add ignore patterns
281 println!("Adding ignore patterns...");
282 repo.ignore_add(&[
283 "*.tmp",
284 "*.log",
285 "build/",
286 "node_modules/",
287 ".DS_Store",
288 "*.secret",
289 ])?;
290 println!(" Added 6 ignore patterns to .gitignore");
291
292 // List current patterns
293 let patterns = repo.ignore_list()?;
294 println!(" Current ignore patterns: {}", patterns.len());
295 for (i, pattern) in patterns.iter().enumerate() {
296 println!(" {}. {}", i + 1, pattern);
297 }
298
299 // Create test files to check ignore status
300 println!("\nCreating test files to check ignore status...");
301 let test_files = [
302 ("regular_file.txt", false),
303 ("temp_file.tmp", true),
304 ("debug.log", true),
305 ("important.secret", true),
306 ("normal.md", false),
307 ];
308
309 for (filename, _) in &test_files {
310 fs::write(repo_path.join(filename), "test content")?;
311 }
312
313 // Check ignore status for each file
314 println!("Checking ignore status for test files:");
315 for (filename, expected_ignored) in &test_files {
316 let is_ignored = repo.ignore_check(filename)?;
317 let status_symbol = if is_ignored { "🚫" } else { "✅" };
318 println!(
319 " {} {} - {}",
320 status_symbol,
321 filename,
322 if is_ignored { "IGNORED" } else { "TRACKED" }
323 );
324
325 // Verify expectation
326 assert_eq!(
327 is_ignored, *expected_ignored,
328 "Ignore status mismatch for {}",
329 filename
330 );
331 }
332 println!();
333
334 println!("=== Error Handling and Edge Cases ===\n");
335
336 // Test error cases
337 println!("Testing error conditions:");
338
339 // Try to checkout non-existent file
340 println!(" Attempting to checkout non-existent file:");
341 match repo.checkout_file("nonexistent.txt") {
342 Ok(_) => println!(" Unexpected success"),
343 Err(e) => println!(" ✓ Expected error: {}", e),
344 }
345
346 // Try to reset non-existent file
347 println!(" Attempting to reset non-staged file:");
348 match repo.reset_file("new_name.txt") {
349 Ok(_) => println!(" ✓ Reset succeeded (file not staged, no error)"),
350 Err(e) => println!(" Error: {}", e),
351 }
352
353 // Try to remove non-existent file
354 println!(" Attempting to remove non-existent file:");
355 match repo.rm(&["definitely_not_here.txt"]) {
356 Ok(_) => println!(" Unexpected success"),
357 Err(e) => println!(" ✓ Expected error: {}", e),
358 }
359
360 // Try to remove with ignore-unmatch option
361 println!(" Attempting to remove with ignore-unmatch option:");
362 let ignore_unmatch_options = RemoveOptions::new().with_ignore_unmatch();
363 match repo.rm_with_options(&["also_not_here.txt"], ignore_unmatch_options) {
364 Ok(_) => println!(" ✓ Succeeded with ignore-unmatch (no error)"),
365 Err(e) => println!(" Error: {}", e),
366 }
367
368 // Try to move to existing file without force
369 fs::write(repo_path.join("existing_target.txt"), "existing content")?;
370 repo.add(&["existing_target.txt"])?;
371 repo.commit("Add existing target")?;
372
373 println!(" Attempting to move to existing file without force:");
374 match repo.mv("test_move.txt", "existing_target.txt") {
375 Ok(_) => println!(" Unexpected success (git may have overwritten)"),
376 Err(e) => println!(" ✓ Expected error: {}", e),
377 }
378 println!();
379
380 println!("=== Advanced Restore Operations ===\n");
381
382 // Demonstrate restore with staged and worktree options
383 println!("Demonstrating advanced restore with staging area...");
384
385 // Modify file and stage it
386 fs::write(repo_path.join("new_name.txt"), "staged changes")?;
387 repo.add(&["new_name.txt"])?;
388
389 // Modify it again in working tree
390 fs::write(repo_path.join("new_name.txt"), "working tree changes")?;
391
392 println!(" File has both staged and working tree changes");
393
394 // Restore only staged area
395 println!(" Restoring staged changes only:");
396 let staged_restore = RestoreOptions::new().with_staged();
397 repo.restore(&["new_name.txt"], staged_restore)?;
398
399 let content_after_staged_restore = fs::read_to_string(repo_path.join("new_name.txt"))?;
400 println!(" ✓ Staged changes restored, working tree preserved");
401 println!(
402 " Working tree content: {:?}",
403 content_after_staged_restore.trim()
404 );
405
406 // Restore working tree
407 println!(" Restoring working tree:");
408 let worktree_restore = RestoreOptions::new().with_worktree();
409 repo.restore(&["new_name.txt"], worktree_restore)?;
410
411 let final_content = fs::read_to_string(repo_path.join("new_name.txt"))?;
412 println!(" ✓ Working tree restored to committed state");
413 println!(" Final content: {:?}", final_content.trim());
414 println!();
415
416 println!("=== Repository State Summary ===\n");
417
418 let final_status = repo.status()?;
419 println!("Final repository state:");
420 println!(" Clean repository: {}", final_status.is_clean());
421 println!(" Staged files: {}", final_status.staged_files().count());
422 println!(
423 " Modified files: {}",
424 final_status.unstaged_files().count()
425 );
426 println!(
427 " Untracked files: {}",
428 final_status.untracked_entries().count()
429 );
430
431 if !final_status.is_clean() {
432 println!("\n Remaining changes:");
433 for entry in final_status.staged_files() {
434 println!(" Staged: {}", entry.path.display());
435 }
436 for entry in final_status.unstaged_files() {
437 println!(" Modified: {}", entry.path.display());
438 }
439 for entry in final_status.untracked_entries() {
440 println!(" Untracked: {}", entry.path.display());
441 }
442 }
443
444 // Show .gitignore content
445 let final_patterns = repo.ignore_list()?;
446 println!("\n .gitignore patterns: {}", final_patterns.len());
447 for pattern in final_patterns {
448 println!(" - {}", pattern);
449 }
450
451 println!("\n=== Summary ===\n");
452
453 println!("File lifecycle operations demonstration completed!");
454 println!(" Repository: {}", repo_path.display());
455
456 println!("\nOperations demonstrated:");
457 println!(" ✓ File restoration from HEAD (checkout_file)");
458 println!(" ✓ Advanced file restoration with options (restore)");
459 println!(" ✓ Unstaging files (reset_file)");
460 println!(" ✓ File removal with various options (rm, rm_with_options)");
461 println!(" ✓ File moving and renaming (mv, mv_with_options)");
462 println!(" ✓ .gitignore pattern management (ignore_add, ignore_list, ignore_check)");
463 println!(" ✓ Staged vs working tree restoration");
464 println!(" ✓ Error handling for invalid operations");
465 println!(" ✓ Dry run and verbose options");
466 println!(" ✓ Recursive and cached removal options");
467
468 // Clean up
469 println!("\nCleaning up example repositories...");
470 fs::remove_dir_all(&base_path)?;
471 println!("File lifecycle operations example completed!");
472
473 Ok(())
474}
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