RepoConfig

Struct RepoConfig 

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

Source

pub const USER_NAME_KEY: &'static str = "user.name"

Source

pub const USER_EMAIL_KEY: &'static str = "user.email"

Source

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 name
  • email - 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
Hide additional 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}
Source

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

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

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

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> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

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

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

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

Source§

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

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

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

Source§

fn into(self) -> U

Calls U::from(self).

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

Source§

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

Source§

type Error = Infallible

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

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

Performs the conversion.
Source§

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

Source§

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

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

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

Performs the conversion.