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)
| 837 | /// This is the main entry point for the clone operation. It coordinates |
| 838 | /// all the steps required to create a local copy of a remote repository. |
| 839 | async fn run_async(&self) -> CliResult<()> { |
| 840 | // Resolve target path |
| 841 | let target_path = resolve_target_path(&self.url, self.path.clone()); |
| 842 | let display_name = self.get_display_name(); |
| 843 | |
| 844 | // Print header |
| 845 | println!( |
| 846 | "Cloning from {} into {}...", |
| 847 | hint(&self.url), |
| 848 | style_view(&display_name) |
| 849 | ); |
| 850 | print_blank(); |
| 851 | |
| 852 | let guard = if self.into_existing { |
| 853 | validate_existing_git_checkout(&target_path)?; |
| 854 | None |
| 855 | } else { |
| 856 | validate_target_path(&target_path)?; |
| 857 | std::fs::create_dir_all(&target_path).map_err(|e| CliError::InvalidPath { |
| 858 | path: target_path.clone(), |
| 859 | source: Some(e), |
| 860 | })?; |
| 861 | Some(CleanupGuard::new(target_path.clone())) |
| 862 | }; |
| 863 | |
| 864 | // Initialize repository |
| 865 | let spinner = create_spinner("Initializing repository..."); |
| 866 | let mut repo = Repository::init(&target_path).map_err(|e| { |
| 867 | finish_error(&spinner, "Failed to initialize"); |
| 868 | CliError::Repository(e) |
| 869 | })?; |
| 870 | finish_success(&spinner, "Repository initialized"); |
| 871 | |
| 872 | // The requested view is NOT pre-created here: its manifest declares |
| 873 | // its identity (scope + parent), and `apply_view_manifest` creates it |
| 874 | // accordingly. Pre-creating it as a shared root would clash with a |
| 875 | // remote draft or child view. |
| 876 | |
| 877 | // Connect to remote |
| 878 | let spinner = create_spinner("Connecting to remote..."); |
| 879 | let config = self.build_remote_config().await; |
| 880 | let remote = HttpRemote::with_config(&self.url, config).map_err(|e| { |
| 881 | finish_error(&spinner, "Failed to connect"); |
| 882 | convert_remote_error(e, &self.url) |
| 883 | })?; |
| 884 | finish_success(&spinner, "Connected"); |
| 885 | |
| 886 | // One `/code` pull for the whole clone: request the view (every view |
| 887 | // with `--all-views`) and take the response — view snapshots + change |
| 888 | // bodies. A fresh clone holds nothing, so it declares no `haves`. |
| 889 | let spinner = create_spinner("Fetching from remote..."); |
| 890 | let wants = if self.all_views { |
| 891 | SyncWants::all(Vec::new()) |
| 892 | } else { |
| 893 | SyncWants { |
| 894 | refs: vec![self.view.clone()], |
| 895 | haves: Vec::new(), |
| 896 | refs_only: false, |
no test coverage detected