Async implementation of the clone command. This is the main entry point for the clone operation. It coordinates all the steps required to create a local copy of a remote repository.
(&self)
| 224 | /// This is the main entry point for the clone operation. It coordinates |
| 225 | /// all the steps required to create a local copy of a remote repository. |
| 226 | async fn run_async(&self) -> CliResult<()> { |
| 227 | // Resolve target path |
| 228 | let target_path = resolve_target_path(&self.url, self.path.clone()); |
| 229 | let display_name = self.get_display_name(); |
| 230 | |
| 231 | // Print header |
| 232 | println!( |
| 233 | "Cloning from {} into {}...", |
| 234 | hint(&self.url), |
| 235 | style_view(&display_name) |
| 236 | ); |
| 237 | print_blank(); |
| 238 | |
| 239 | // Validate target doesn't exist |
| 240 | validate_target_path(&target_path)?; |
| 241 | |
| 242 | // Create cleanup guard - will remove directory if we fail |
| 243 | let guard = CleanupGuard::new(target_path.clone()); |
| 244 | |
| 245 | // Create target directory |
| 246 | std::fs::create_dir_all(&target_path).map_err(|e| CliError::InvalidPath { |
| 247 | path: target_path.clone(), |
| 248 | source: Some(e), |
| 249 | })?; |
| 250 | |
| 251 | // Initialize repository |
| 252 | let spinner = create_spinner("Initializing repository..."); |
| 253 | let repo = Repository::init(&target_path).map_err(|e| { |
| 254 | finish_error(&spinner, "Failed to initialize"); |
| 255 | CliError::Repository(e) |
| 256 | })?; |
| 257 | finish_success(&spinner, "Repository initialized"); |
| 258 | |
| 259 | // Connect to remote |
| 260 | let spinner = create_spinner("Connecting to remote..."); |
| 261 | let config = self.build_remote_config().await; |
| 262 | let remote = HttpRemote::with_config(&self.url, config).map_err(|e| { |
| 263 | finish_error(&spinner, "Failed to connect"); |
| 264 | convert_remote_error(e, &self.url) |
| 265 | })?; |
| 266 | finish_success(&spinner, "Connected"); |
| 267 | |
| 268 | // Query remote state |
| 269 | let spinner = create_spinner("Querying remote state..."); |
| 270 | let remote_state = remote.get_state(&self.view).await.map_err(|e| { |
| 271 | finish_error(&spinner, "Failed to query state"); |
| 272 | convert_remote_error(e, &self.url) |
| 273 | })?; |
| 274 | |
| 275 | if remote_state.is_empty() { |
| 276 | finish_success(&spinner, &format!("View '{}' is empty", self.view)); |
| 277 | |
| 278 | // Configure remote as "origin" even for empty repositories |
| 279 | let spinner = create_spinner("Configuring remote..."); |
| 280 | if let Err(e) = repo.add_remote_default("origin", &self.url) { |
| 281 | finish_error(&spinner, "Failed to configure remote"); |
| 282 | print_warning(&format!("Could not save remote configuration: {}", e)); |
| 283 | print_hint( |
no test coverage detected