remote_operations/
remote_operations.rs1use rustic_git::{FetchOptions, PushOptions, Repository, Result};
13use std::{env, fs};
14
15fn main() -> Result<()> {
16 println!("Rustic Git - Remote Operations Example\n");
17
18 let base_path = env::temp_dir().join("rustic_git_remote_example");
19 let repo_path = base_path.join("main_repo");
20 let clone_path = base_path.join("cloned_repo");
21
22 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 println!("Initializing repository for remote demonstrations...");
32 let repo = Repository::init(&repo_path, false)?;
33 println!("Repository initialized at: {}", repo_path.display());
34
35 fs::write(
37 repo_path.join("README.md"),
38 "# Remote Operations Demo\n\nDemonstrating rustic-git remote management capabilities.",
39 )?;
40 repo.add(&["README.md"])?;
41 repo.commit("Initial commit for remote operations demo")?;
42 println!("Created initial commit\n");
43
44 println!("=== Basic Remote Management ===\n");
45
46 println!("Checking initial remote state:");
48 let remotes = repo.list_remotes()?;
49 println!(" Initial remotes count: {}", remotes.len());
50 if remotes.is_empty() {
51 println!(" No remotes configured (as expected)");
52 }
53 println!();
54
55 println!("Adding remotes...");
57 repo.add_remote("origin", "https://github.com/user/demo-repo.git")?;
58 println!(" Added 'origin' remote");
59
60 repo.add_remote("upstream", "https://github.com/original/demo-repo.git")?;
61 println!(" Added 'upstream' remote");
62
63 repo.add_remote("fork", "git@github.com:user/fork-repo.git")?;
64 println!(" Added 'fork' remote (SSH URL)");
65 println!();
66
67 println!("Listing all remotes:");
69 let remotes = repo.list_remotes()?;
70 println!(" Total remotes: {}", remotes.len());
71
72 for remote in remotes.iter() {
73 println!(" {} -> {}", remote.name, remote.fetch_url);
74 if let Some(push_url) = &remote.push_url {
75 println!(" Push URL: {}", push_url);
76 }
77 }
78 println!();
79
80 println!("Getting specific remote URLs:");
82 let origin_url = repo.get_remote_url("origin")?;
83 println!(" Origin URL: {}", origin_url);
84
85 let upstream_url = repo.get_remote_url("upstream")?;
86 println!(" Upstream URL: {}", upstream_url);
87 println!();
88
89 println!("Renaming 'fork' remote to 'my-fork'...");
91 repo.rename_remote("fork", "my-fork")?;
92 println!(" Remote renamed successfully");
93
94 let remotes = repo.list_remotes()?;
96 let renamed_remote = remotes.find("my-fork");
97 match renamed_remote {
98 Some(remote) => println!(
99 " Found renamed remote: {} -> {}",
100 remote.name, remote.fetch_url
101 ),
102 None => println!(" Error: Could not find renamed remote"),
103 }
104
105 if remotes.find("fork").is_none() {
107 println!(" Confirmed: old 'fork' remote no longer exists");
108 }
109 println!();
110
111 println!("=== Remote Operations with Options ===\n");
112
113 println!("Fetch operations (simulated - no actual network calls):");
115 println!(" Basic fetch from origin:");
116 match repo.fetch("origin") {
117 Ok(_) => println!(" ✓ Fetch completed successfully"),
118 Err(e) => println!(" ⚠ Fetch failed (expected): {}", e),
119 }
120
121 println!(" Fetch with options (prune + tags):");
122 let fetch_options = FetchOptions::new().with_prune().with_tags();
123 match repo.fetch_with_options("origin", fetch_options) {
124 Ok(_) => println!(" ✓ Fetch with options completed successfully"),
125 Err(e) => println!(" ⚠ Fetch with options failed (expected): {}", e),
126 }
127
128 println!(" Fetch all remotes:");
129 let fetch_all_options = FetchOptions::new().with_all_remotes();
130 match repo.fetch_with_options("", fetch_all_options) {
131 Ok(_) => println!(" ✓ Fetch all completed successfully"),
132 Err(e) => println!(" ⚠ Fetch all failed (expected): {}", e),
133 }
134 println!();
135
136 println!("Push operations (simulated - no actual network calls):");
138 println!(" Basic push to origin:");
139 match repo.push("origin", "main") {
140 Ok(_) => println!(" ✓ Push completed successfully"),
141 Err(e) => println!(" ⚠ Push failed (expected): {}", e),
142 }
143
144 println!(" Push with upstream tracking:");
145 let push_options = PushOptions::new().with_set_upstream();
146 match repo.push_with_options("origin", "main", push_options) {
147 Ok(_) => println!(" ✓ Push with upstream completed successfully"),
148 Err(e) => println!(" ⚠ Push with upstream failed (expected): {}", e),
149 }
150
151 println!(" Force push with tags:");
152 let force_push_options = PushOptions::new().with_force().with_tags();
153 match repo.push_with_options("my-fork", "feature-branch", force_push_options) {
154 Ok(_) => println!(" ✓ Force push with tags completed successfully"),
155 Err(e) => println!(" ⚠ Force push with tags failed (expected): {}", e),
156 }
157 println!();
158
159 println!("=== Clone Operations ===\n");
160
161 println!("Clone operation demonstration:");
164 println!(" Attempting to clone a repository...");
165
166 match Repository::clone("https://github.com/nonexistent/fake-repo.git", &clone_path) {
168 Ok(_repo) => {
169 println!(" ✓ Clone completed successfully");
170 println!(" Cloned repository location: {}", clone_path.display());
171 }
172 Err(e) => {
173 println!(" ⚠ Clone failed (expected for demo): {}", e);
174 println!(" In real usage, provide a valid repository URL");
175 }
176 }
177 println!();
178
179 println!("=== Error Handling and Edge Cases ===\n");
180
181 println!("Testing error conditions:");
183
184 println!(" Getting URL for non-existent remote:");
186 match repo.get_remote_url("nonexistent") {
187 Ok(url) => println!(" Unexpected success: {}", url),
188 Err(e) => println!(" ✓ Expected error: {}", e),
189 }
190
191 println!(" Removing non-existent remote:");
193 match repo.remove_remote("nonexistent") {
194 Ok(_) => println!(" Unexpected success"),
195 Err(e) => println!(" ✓ Expected error: {}", e),
196 }
197
198 println!(" Adding duplicate remote:");
200 match repo.add_remote("origin", "https://github.com/duplicate/repo.git") {
201 Ok(_) => println!(" Unexpected success (git allows URL changes)"),
202 Err(e) => println!(" Error: {}", e),
203 }
204 println!();
205
206 println!("=== Remote Cleanup Operations ===\n");
207
208 println!("Removing remotes:");
210
211 println!(" Removing 'upstream' remote...");
212 repo.remove_remote("upstream")?;
213
214 println!(" Removing 'my-fork' remote...");
215 repo.remove_remote("my-fork")?;
216
217 println!(" Removing 'origin' remote...");
218 repo.remove_remote("origin")?;
219
220 let final_remotes = repo.list_remotes()?;
222 println!(" Final remote count: {}", final_remotes.len());
223
224 if final_remotes.is_empty() {
225 println!(" ✓ All remotes successfully removed");
226 } else {
227 println!(" ⚠ Some remotes still remain:");
228 for remote in final_remotes.iter() {
229 println!(" - {}", remote.name);
230 }
231 }
232 println!();
233
234 println!("=== Advanced Remote Information ===\n");
235
236 repo.add_remote("demo", "https://github.com/demo/advanced-repo.git")?;
238
239 let remotes = repo.list_remotes()?;
241 for remote in remotes.iter() {
242 println!("Remote Details:");
243 println!(" Name: {}", remote.name);
244 println!(" Fetch URL: {}", remote.fetch_url);
245 println!(" Push URL: {}", remote.push_url());
246 println!(" Uses separate push URL: {}", remote.push_url.is_some());
247
248 if remote.fetch_url.starts_with("https://") {
250 println!(" Protocol: HTTPS");
251 } else if remote.fetch_url.starts_with("git@") {
252 println!(" Protocol: SSH");
253 } else if remote.fetch_url.starts_with("git://") {
254 println!(" Protocol: Git");
255 } else {
256 println!(" Protocol: Other/Local");
257 }
258 }
259 println!();
260
261 println!("=== Summary ===\n");
262
263 println!("Remote operations demonstration completed!");
264 println!(" Repository: {}", repo_path.display());
265
266 let final_remotes = repo.list_remotes()?;
267 println!(" Final remotes configured: {}", final_remotes.len());
268
269 for remote in final_remotes.iter() {
270 println!(" - {} ({})", remote.name, remote.fetch_url);
271 }
272
273 println!("\nOperations demonstrated:");
274 println!(" ✓ Adding remotes with different URL formats");
275 println!(" ✓ Listing and inspecting remotes");
276 println!(" ✓ Getting specific remote URLs");
277 println!(" ✓ Renaming remotes");
278 println!(" ✓ Removing remotes");
279 println!(" ✓ Fetch operations with options");
280 println!(" ✓ Push operations with options");
281 println!(" ✓ Clone API demonstration");
282 println!(" ✓ Error handling for invalid operations");
283 println!(" ✓ Remote information analysis");
284
285 println!("\nCleaning up example repositories...");
287 fs::remove_dir_all(&base_path)?;
288 println!("Remote operations example completed!");
289
290 Ok(())
291}