clone.rs

  1use gpui::{App, Context, Window};
  2use notifications::status_toast::{StatusToast, ToastIcon};
  3use std::sync::Arc;
  4use ui::{Color, IconName};
  5use util::ResultExt;
  6use workspace::{self, AppState};
  7
  8pub fn clone_and_open(
  9    repo_url: String,
 10    app_state: Arc<AppState>,
 11    cx: &mut App,
 12    on_success: Arc<
 13        dyn Fn(&mut workspace::Workspace, &mut Window, &mut Context<workspace::Workspace>)
 14            + Send
 15            + Sync
 16            + 'static,
 17    >,
 18) {
 19    workspace::with_active_or_new_workspace(cx, |_workspace, window, cx| {
 20        let path_prompt = cx.prompt_for_paths(gpui::PathPromptOptions {
 21            files: false,
 22            directories: true,
 23            multiple: false,
 24            prompt: Some("Select directory for cloned repository".into()),
 25        });
 26
 27        cx.spawn_in(window, async move |workspace, cx| {
 28            let mut paths = path_prompt.await.ok()?.ok()??;
 29            let mut path = paths.pop()?;
 30
 31            let repo_name = repo_url
 32                .split('/')
 33                .next_back()
 34                .and_then(|name| name.strip_suffix(".git"))
 35                .unwrap_or("repository")
 36                .to_owned();
 37
 38            let fs = workspace
 39                .read_with(cx, |workspace, _| workspace.app_state().fs.clone())
 40                .ok()?;
 41
 42            let prompt_answer = match fs.git_clone(&repo_url, path.as_path()).await {
 43                Ok(_) => cx.update(|window, cx| {
 44                    window.prompt(
 45                        gpui::PromptLevel::Info,
 46                        &format!("Git Clone: \"{}\"", repo_name),
 47                        None,
 48                        &["Add to current project", "Open in new window"],
 49                        cx,
 50                    )
 51                }),
 52                Err(e) => {
 53                    workspace
 54                        .update(cx, |workspace, cx| {
 55                            let toast = StatusToast::new(e.to_string(), cx, |this, _| {
 56                                this.icon(ToastIcon::new(IconName::XCircle).color(Color::Error))
 57                                    .dismiss_button(true)
 58                            });
 59                            workspace.toggle_status_toast(toast, cx);
 60                        })
 61                        .ok()?;
 62
 63                    return None;
 64                }
 65            }
 66            .ok()?;
 67
 68            path.push(&repo_name);
 69
 70            match prompt_answer.await.ok()? {
 71                0 => {
 72                    workspace
 73                        .update_in(cx, |workspace, window, cx| {
 74                            let worktree_task = workspace.project().update(cx, |project, cx| {
 75                                project.create_worktree(path.as_path(), true, cx)
 76                            });
 77                            let workspace_weak = cx.weak_entity();
 78                            cx.spawn_in(window, async move |_window, cx| {
 79                                if worktree_task.await.log_err().is_some() {
 80                                    workspace_weak
 81                                        .update_in(cx, |workspace, window, cx| {
 82                                            (on_success)(workspace, window, cx);
 83                                        })
 84                                        .ok();
 85                                }
 86                            })
 87                            .detach();
 88                        })
 89                        .ok()?;
 90                }
 91                1 => {
 92                    workspace
 93                        .update(cx, move |_workspace, cx| {
 94                            workspace::open_new(
 95                                Default::default(),
 96                                app_state,
 97                                cx,
 98                                move |workspace, window, cx| {
 99                                    cx.activate(true);
100                                    let worktree_task =
101                                        workspace.project().update(cx, |project, cx| {
102                                            project.create_worktree(&path, true, cx)
103                                        });
104                                    let workspace_weak = cx.weak_entity();
105                                    cx.spawn_in(window, async move |_window, cx| {
106                                        if worktree_task.await.log_err().is_some() {
107                                            workspace_weak
108                                                .update_in(cx, |workspace, window, cx| {
109                                                    (on_success)(workspace, window, cx);
110                                                })
111                                                .ok();
112                                        }
113                                    })
114                                    .detach();
115                                },
116                            )
117                            .detach();
118                        })
119                        .ok();
120                }
121                _ => {}
122            }
123
124            Some(())
125        })
126        .detach();
127    });
128}