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)
| 743 | /// This is the main entry point for the clone operation. It coordinates |
| 744 | /// all the steps required to create a local copy of a remote repository. |
| 745 | async fn run_async(&self) -> CliResult<()> { |
| 746 | // Resolve target path |
| 747 | let target_path = resolve_target_path(&self.url, self.path.clone()); |
| 748 | let display_name = self.get_display_name(); |
| 749 | |
| 750 | // Print header |
| 751 | println!( |
| 752 | "Cloning from {} into {}...", |
| 753 | hint(&self.url), |
| 754 | style_view(&display_name) |
| 755 | ); |
| 756 | print_blank(); |
| 757 | |
| 758 | let guard = if self.into_existing { |
| 759 | validate_existing_git_checkout(&target_path)?; |
| 760 | None |
| 761 | } else { |
| 762 | validate_target_path(&target_path)?; |
| 763 | std::fs::create_dir_all(&target_path).map_err(|e| CliError::InvalidPath { |
| 764 | path: target_path.clone(), |
| 765 | source: Some(e), |
| 766 | })?; |
| 767 | Some(CleanupGuard::new(target_path.clone())) |
| 768 | }; |
| 769 | |
| 770 | // Initialize repository |
| 771 | let spinner = create_spinner("Initializing repository..."); |
| 772 | let mut repo = Repository::init(&target_path).map_err(|e| { |
| 773 | finish_error(&spinner, "Failed to initialize"); |
| 774 | CliError::Repository(e) |
| 775 | })?; |
| 776 | finish_success(&spinner, "Repository initialized"); |
| 777 | |
| 778 | // The requested view is NOT pre-created here: its manifest declares |
| 779 | // its identity (scope + parent), and `apply_view_manifest` creates it |
| 780 | // accordingly. Pre-creating it as a shared root would clash with a |
| 781 | // remote draft or child view. |
| 782 | |
| 783 | // Connect to remote |
| 784 | let spinner = create_spinner("Connecting to remote..."); |
| 785 | let config = self.build_remote_config().await; |
| 786 | let remote = HttpRemote::with_config(&self.url, config).map_err(|e| { |
| 787 | finish_error(&spinner, "Failed to connect"); |
| 788 | convert_remote_error(e, &self.url) |
| 789 | })?; |
| 790 | finish_success(&spinner, "Connected"); |
| 791 | |
| 792 | // Fetch the requested view's manifest chain (view → ... → root). |
| 793 | // The manifests carry each view's identity, so clone reconstructs |
| 794 | // scope and parent exactly. An old server without manifest support |
| 795 | // is a hard error — there is no identity-losing fallback. |
| 796 | let spinner = create_spinner("Fetching view manifests..."); |
| 797 | let manifests = match self.fetch_manifest_chain(&remote).await { |
| 798 | Ok(m) => m, |
| 799 | Err(e) => { |
| 800 | finish_error(&spinner, "Failed to fetch view manifests"); |
| 801 | return Err(e); |
| 802 | } |
no test coverage detected