repository_operations/
repository_operations.rs

1//! Repository Operations Example
2//!
3//! This example demonstrates various repository lifecycle operations:
4//! - Initialize regular and bare repositories
5//! - Open existing repositories
6//! - Handle errors when opening non-existent repositories
7//! - Display repository information
8//!
9//! Run with: cargo run --example repository_operations
10
11use rustic_git::{GitError, Repository, Result};
12use std::env;
13use std::fs;
14
15fn main() -> Result<()> {
16    println!("Rustic Git - Repository Operations Example\n");
17
18    let base_path = env::temp_dir().join("rustic_git_repo_example");
19    let regular_repo_path = base_path.join("regular");
20    let bare_repo_path = base_path.join("bare");
21    let nonexistent_path = base_path.join("nonexistent");
22
23    // Clean up any previous runs
24    if base_path.exists() {
25        fs::remove_dir_all(&base_path).expect("Failed to clean up previous example");
26    }
27    fs::create_dir_all(&base_path)?;
28
29    println!("=== Repository Initialization ===\n");
30
31    // 1. Initialize a regular repository
32    println!("Initializing regular repository...");
33    let regular_repo = Repository::init(&regular_repo_path, false)?;
34    println!(
35        "Regular repository created at: {}",
36        regular_repo_path.display()
37    );
38    println!("   Repository path: {:?}", regular_repo.repo_path());
39
40    // Verify it's a git repo by checking for .git directory
41    if regular_repo_path.join(".git").exists() {
42        println!("   .git directory found");
43    }
44    println!();
45
46    // 2. Initialize a bare repository
47    println!("Initializing bare repository...");
48    let bare_repo = Repository::init(&bare_repo_path, true)?;
49    println!("Bare repository created at: {}", bare_repo_path.display());
50    println!("   Repository path: {:?}", bare_repo.repo_path());
51
52    // Verify bare repo structure (has HEAD, objects, etc. directly)
53    if bare_repo_path.join("HEAD").exists() {
54        println!("   HEAD file found (bare repository structure)");
55    }
56    if bare_repo_path.join("objects").exists() {
57        println!("   objects directory found");
58    }
59    println!();
60
61    println!("=== Repository Opening ===\n");
62
63    // 3. Open the existing regular repository
64    println!("Opening existing regular repository...");
65    match Repository::open(&regular_repo_path) {
66        Ok(opened_repo) => {
67            println!("Successfully opened regular repository");
68            println!("   Repository path: {:?}", opened_repo.repo_path());
69
70            // Test that we can perform operations on the opened repo
71            let status = opened_repo.status()?;
72            println!("   Repository status: {} files", status.entries.len());
73        }
74        Err(e) => {
75            println!("Failed to open regular repository: {:?}", e);
76        }
77    }
78    println!();
79
80    // 4. Open the existing bare repository
81    println!("Opening existing bare repository...");
82    match Repository::open(&bare_repo_path) {
83        Ok(opened_bare) => {
84            println!("Successfully opened bare repository");
85            println!("   Repository path: {:?}", opened_bare.repo_path());
86
87            // Note: status operations might behave differently on bare repos
88            match opened_bare.status() {
89                Ok(status) => println!("   Bare repository status: {} files", status.entries.len()),
90                Err(e) => println!(
91                    "   Note: Status check on bare repo failed (expected): {:?}",
92                    e
93                ),
94            }
95        }
96        Err(e) => {
97            println!("Failed to open bare repository: {:?}", e);
98        }
99    }
100    println!();
101
102    println!("=== Error Handling ===\n");
103
104    // 5. Try to open a non-existent repository
105    println!("Attempting to open non-existent repository...");
106    match Repository::open(&nonexistent_path) {
107        Ok(_repo) => {
108            println!("Unexpectedly succeeded opening non-existent repo");
109        }
110        Err(GitError::CommandFailed(msg)) => {
111            println!("Expected error caught: CommandFailed");
112            println!("   Error message: {}", msg);
113        }
114        Err(GitError::IoError(msg)) => {
115            println!("Expected error caught: IoError");
116            println!("   Error message: {}", msg);
117        }
118    }
119    println!();
120
121    // 6. Try to open a regular file as a repository
122    let fake_repo_path = base_path.join("fake.txt");
123    fs::write(&fake_repo_path, "This is not a git repository")?;
124
125    println!("Attempting to open regular file as repository...");
126    match Repository::open(&fake_repo_path) {
127        Ok(_repo) => {
128            println!("Unexpectedly succeeded opening regular file as repo");
129        }
130        Err(GitError::CommandFailed(msg)) => {
131            println!("Expected error caught: CommandFailed");
132            println!("   Error message: {}", msg);
133        }
134        Err(GitError::IoError(msg)) => {
135            println!("Expected error caught: IoError");
136            println!("   Error message: {}", msg);
137        }
138    }
139    println!();
140
141    println!("=== Repository Information ===\n");
142
143    // 7. Compare regular vs bare repository information
144    println!("Comparing repository types:");
145
146    let regular_path = regular_repo.repo_path();
147    let bare_path = bare_repo.repo_path();
148
149    println!("   Regular repo path: {:?}", regular_path);
150    println!("   Bare repo path: {:?}", bare_path);
151
152    // Show directory contents
153    if let Ok(entries) = fs::read_dir(regular_path) {
154        let mut files: Vec<_> = entries.filter_map(|e| e.ok()).collect();
155        files.sort_by_key(|e| e.file_name());
156
157        println!("   Regular repo contents:");
158        for entry in files {
159            if let Some(name) = entry.file_name().to_str() {
160                let is_dir = entry.file_type().map(|t| t.is_dir()).unwrap_or(false);
161                let marker = if is_dir { "[DIR]" } else { "[FILE]" };
162                println!("     {} {}", marker, name);
163            }
164        }
165    }
166
167    if let Ok(entries) = fs::read_dir(bare_path) {
168        let mut files: Vec<_> = entries.filter_map(|e| e.ok()).collect();
169        files.sort_by_key(|e| e.file_name());
170
171        println!("   Bare repo contents:");
172        for entry in files {
173            if let Some(name) = entry.file_name().to_str() {
174                let is_dir = entry.file_type().map(|t| t.is_dir()).unwrap_or(false);
175                let marker = if is_dir { "[DIR]" } else { "[FILE]" };
176                println!("     {} {}", marker, name);
177            }
178        }
179    }
180    println!();
181
182    // Clean up
183    println!("Cleaning up example repositories...");
184    fs::remove_dir_all(&base_path)?;
185    println!("Repository operations example completed!");
186
187    Ok(())
188}