pub struct RemoteList { /* private fields */ }
Expand description
A collection of remotes in a repository
Implementations§
Source§impl RemoteList
impl RemoteList
Sourcepub fn find(&self, name: &str) -> Option<&Remote>
pub fn find(&self, name: &str) -> Option<&Remote>
Find a remote by name
Examples found in repository?
examples/remote_operations.rs (line 96)
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 // Clean up any previous runs
23 if base_path.exists() {
24 fs::remove_dir_all(&base_path).expect("Failed to clean up previous example");
25 }
26 fs::create_dir_all(&base_path)?;
27
28 println!("=== Repository Setup ===\n");
29
30 // Initialize repository
31 println!("Initializing repository for remote demonstrations...");
32 let repo = Repository::init(&repo_path, false)?;
33 println!("Repository initialized at: {}", repo_path.display());
34
35 // Create initial commit so we have something to work with
36 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 // Check initial remote state
47 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 // Add remotes
56 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 // List remotes
68 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 // Get specific remote URLs
81 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 // Rename a remote
90 println!("Renaming 'fork' remote to 'my-fork'...");
91 repo.rename_remote("fork", "my-fork")?;
92 println!(" Remote renamed successfully");
93
94 // Verify rename
95 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 // Verify old name is gone
106 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 // Demonstrate fetch options
114 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 // Demonstrate push options
137 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 // Note: We can't actually clone from the URLs we added since they're fake,
162 // but we can demonstrate the API and show how it would work
163 println!("Clone operation demonstration:");
164 println!(" Attempting to clone a repository...");
165
166 // This will fail since the URL doesn't exist, but demonstrates the API
167 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 // Test error cases
182 println!("Testing error conditions:");
183
184 // Try to get URL for non-existent remote
185 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 // Try to remove non-existent remote
192 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 // Try to add duplicate remote
199 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 // Remove remotes one by one
209 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 // Verify all remotes are gone
221 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 // Re-add a remote for advanced operations demo
237 repo.add_remote("demo", "https://github.com/demo/advanced-repo.git")?;
238
239 // Show comprehensive remote information
240 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 // Validate URL format
249 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 // Clean up
286 println!("\nCleaning up example repositories...");
287 fs::remove_dir_all(&base_path)?;
288 println!("Remote operations example completed!");
289
290 Ok(())
291}
Sourcepub fn iter(&self) -> impl Iterator<Item = &Remote>
pub fn iter(&self) -> impl Iterator<Item = &Remote>
Get an iterator over all remotes
Examples found in repository?
examples/remote_operations.rs (line 72)
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 // Clean up any previous runs
23 if base_path.exists() {
24 fs::remove_dir_all(&base_path).expect("Failed to clean up previous example");
25 }
26 fs::create_dir_all(&base_path)?;
27
28 println!("=== Repository Setup ===\n");
29
30 // Initialize repository
31 println!("Initializing repository for remote demonstrations...");
32 let repo = Repository::init(&repo_path, false)?;
33 println!("Repository initialized at: {}", repo_path.display());
34
35 // Create initial commit so we have something to work with
36 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 // Check initial remote state
47 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 // Add remotes
56 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 // List remotes
68 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 // Get specific remote URLs
81 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 // Rename a remote
90 println!("Renaming 'fork' remote to 'my-fork'...");
91 repo.rename_remote("fork", "my-fork")?;
92 println!(" Remote renamed successfully");
93
94 // Verify rename
95 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 // Verify old name is gone
106 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 // Demonstrate fetch options
114 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 // Demonstrate push options
137 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 // Note: We can't actually clone from the URLs we added since they're fake,
162 // but we can demonstrate the API and show how it would work
163 println!("Clone operation demonstration:");
164 println!(" Attempting to clone a repository...");
165
166 // This will fail since the URL doesn't exist, but demonstrates the API
167 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 // Test error cases
182 println!("Testing error conditions:");
183
184 // Try to get URL for non-existent remote
185 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 // Try to remove non-existent remote
192 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 // Try to add duplicate remote
199 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 // Remove remotes one by one
209 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 // Verify all remotes are gone
221 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 // Re-add a remote for advanced operations demo
237 repo.add_remote("demo", "https://github.com/demo/advanced-repo.git")?;
238
239 // Show comprehensive remote information
240 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 // Validate URL format
249 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 // Clean up
286 println!("\nCleaning up example repositories...");
287 fs::remove_dir_all(&base_path)?;
288 println!("Remote operations example completed!");
289
290 Ok(())
291}
Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Get the number of remotes
Examples found in repository?
examples/remote_operations.rs (line 49)
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 // Clean up any previous runs
23 if base_path.exists() {
24 fs::remove_dir_all(&base_path).expect("Failed to clean up previous example");
25 }
26 fs::create_dir_all(&base_path)?;
27
28 println!("=== Repository Setup ===\n");
29
30 // Initialize repository
31 println!("Initializing repository for remote demonstrations...");
32 let repo = Repository::init(&repo_path, false)?;
33 println!("Repository initialized at: {}", repo_path.display());
34
35 // Create initial commit so we have something to work with
36 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 // Check initial remote state
47 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 // Add remotes
56 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 // List remotes
68 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 // Get specific remote URLs
81 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 // Rename a remote
90 println!("Renaming 'fork' remote to 'my-fork'...");
91 repo.rename_remote("fork", "my-fork")?;
92 println!(" Remote renamed successfully");
93
94 // Verify rename
95 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 // Verify old name is gone
106 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 // Demonstrate fetch options
114 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 // Demonstrate push options
137 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 // Note: We can't actually clone from the URLs we added since they're fake,
162 // but we can demonstrate the API and show how it would work
163 println!("Clone operation demonstration:");
164 println!(" Attempting to clone a repository...");
165
166 // This will fail since the URL doesn't exist, but demonstrates the API
167 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 // Test error cases
182 println!("Testing error conditions:");
183
184 // Try to get URL for non-existent remote
185 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 // Try to remove non-existent remote
192 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 // Try to add duplicate remote
199 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 // Remove remotes one by one
209 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 // Verify all remotes are gone
221 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 // Re-add a remote for advanced operations demo
237 repo.add_remote("demo", "https://github.com/demo/advanced-repo.git")?;
238
239 // Show comprehensive remote information
240 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 // Validate URL format
249 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 // Clean up
286 println!("\nCleaning up example repositories...");
287 fs::remove_dir_all(&base_path)?;
288 println!("Remote operations example completed!");
289
290 Ok(())
291}
Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Check if the remote list is empty
Examples found in repository?
examples/remote_operations.rs (line 50)
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 // Clean up any previous runs
23 if base_path.exists() {
24 fs::remove_dir_all(&base_path).expect("Failed to clean up previous example");
25 }
26 fs::create_dir_all(&base_path)?;
27
28 println!("=== Repository Setup ===\n");
29
30 // Initialize repository
31 println!("Initializing repository for remote demonstrations...");
32 let repo = Repository::init(&repo_path, false)?;
33 println!("Repository initialized at: {}", repo_path.display());
34
35 // Create initial commit so we have something to work with
36 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 // Check initial remote state
47 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 // Add remotes
56 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 // List remotes
68 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 // Get specific remote URLs
81 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 // Rename a remote
90 println!("Renaming 'fork' remote to 'my-fork'...");
91 repo.rename_remote("fork", "my-fork")?;
92 println!(" Remote renamed successfully");
93
94 // Verify rename
95 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 // Verify old name is gone
106 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 // Demonstrate fetch options
114 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 // Demonstrate push options
137 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 // Note: We can't actually clone from the URLs we added since they're fake,
162 // but we can demonstrate the API and show how it would work
163 println!("Clone operation demonstration:");
164 println!(" Attempting to clone a repository...");
165
166 // This will fail since the URL doesn't exist, but demonstrates the API
167 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 // Test error cases
182 println!("Testing error conditions:");
183
184 // Try to get URL for non-existent remote
185 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 // Try to remove non-existent remote
192 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 // Try to add duplicate remote
199 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 // Remove remotes one by one
209 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 // Verify all remotes are gone
221 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 // Re-add a remote for advanced operations demo
237 repo.add_remote("demo", "https://github.com/demo/advanced-repo.git")?;
238
239 // Show comprehensive remote information
240 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 // Validate URL format
249 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 // Clean up
286 println!("\nCleaning up example repositories...");
287 fs::remove_dir_all(&base_path)?;
288 println!("Remote operations example completed!");
289
290 Ok(())
291}
Trait Implementations§
Auto Trait Implementations§
impl Freeze for RemoteList
impl RefUnwindSafe for RemoteList
impl Send for RemoteList
impl Sync for RemoteList
impl Unpin for RemoteList
impl UnwindSafe for RemoteList
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more