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}