use gpui::{App, Context, WeakEntity, Window};use notifications::status_toast::{StatusToast, ToastIcon};use std::sync::Arc;use ui::{Color, IconName, SharedString};use util::ResultExt;use workspace::{self, Workspace}; pub fn clone_and_open( repo_url: SharedString, workspace: WeakEntity<Workspace>, window: &mut Window, cx: &mut App, on_success: Arc< dyn Fn(&mut Workspace, &mut Window, &mut Context<Workspace>) + Send + Sync + 'static, >,) { let destination_prompt = cx.prompt_for_paths(gpui::PathPromptOptions { files: false, directories: true, multiple: false, prompt: Some("Select as Repository Destination".into()), }); window .spawn(cx, async move |cx| { let mut paths = destination_prompt.await.ok()?.ok()??; let mut destination_dir = paths.pop()?; let repo_name = repo_url .split('/') .next_back() .map(|name| name.strip_suffix(".git").unwrap_or(name)) .unwrap_or("repository") .to_owned(); let clone_task = workspace .update(cx, |workspace, cx| { let fs = workspace.app_state().fs.clone(); let destination_dir = destination_dir.clone(); let repo_url = repo_url.clone(); cx.spawn(async move |_workspace, _cx| { fs.git_clone(&repo_url, destination_dir.as_path()).await }) }) .ok()?; if let Err(error) = clone_task.await { workspace .update(cx, |workspace, cx| { let toast = StatusToast::new(error.to_string(), cx, |this, _| { this.icon(ToastIcon::new(IconName::XCircle).color(Color::Error)) .dismiss_button(true) }); workspace.toggle_status_toast(toast, cx); }) .log_err(); return None; } let has_worktrees = workspace .read_with(cx, |workspace, cx| { workspace.project().read(cx).worktrees(cx).next().is_some() }) .ok()?; let prompt_answer = if has_worktrees { cx.update(|window, cx| { window.prompt( gpui::PromptLevel::Info, &format!("Git Clone: {}", repo_name), None, &["Add repo to project", "Open repo in new project"], cx, ) }) .ok()? .await .ok()? } else { // Don't ask if project is empty 0 }; destination_dir.push(&repo_name); match prompt_answer { 0 => { workspace .update_in(cx, |workspace, window, cx| { let create_task = workspace.project().update(cx, |project, cx| { project.create_worktree(destination_dir.as_path(), true, cx) }); let workspace_weak = cx.weak_entity(); let on_success = on_success.clone(); cx.spawn_in(window, async move |_window, cx| { if create_task.await.log_err().is_some() { workspace_weak .update_in(cx, |workspace, window, cx| { (on_success)(workspace, window, cx); }) .ok(); } }) .detach(); }) .ok()?; } 1 => { workspace .update(cx, move |workspace, cx| { let app_state = workspace.app_state().clone(); let destination_path = destination_dir.clone(); let on_success = on_success.clone(); workspace::open_new( Default::default(), app_state, cx, move |workspace, window, cx| { cx.activate(true); let create_task = workspace.project().update(cx, |project, cx| { project.create_worktree( destination_path.as_path(), true, cx, ) }); let workspace_weak = cx.weak_entity(); cx.spawn_in(window, async move |_window, cx| { if create_task.await.log_err().is_some() { workspace_weak .update_in(cx, |workspace, window, cx| { (on_success)(workspace, window, cx); }) .ok(); } }) .detach(); }, ) .detach(); }) .ok(); } _ => {} } Some(()) }) .detach();}
use gpui::{App, Context, WeakEntity, Window};
use notifications::status_toast::{StatusToast, ToastIcon};
use std::sync::Arc;
use ui::{Color, IconName, SharedString};
use util::ResultExt;
use workspace::{self, Workspace};
pub fn clone_and_open(
repo_url: SharedString,
workspace: WeakEntity<Workspace>,
window: &mut Window,
cx: &mut App,
on_success: Arc<
dyn Fn(&mut Workspace, &mut Window, &mut Context<Workspace>) + Send + Sync + 'static,
>,
) {
let destination_prompt = cx.prompt_for_paths(gpui::PathPromptOptions {
files: false,
directories: true,
multiple: false,
prompt: Some("Select as Repository Destination".into()),
});
window
.spawn(cx, async move |cx| {
let mut paths = destination_prompt.await.ok()?.ok()??;
let mut destination_dir = paths.pop()?;
let repo_name = repo_url
.split('/')
.next_back()
.map(|name| name.strip_suffix(".git").unwrap_or(name))
.unwrap_or("repository")
.to_owned();
let clone_task = workspace
.update(cx, |workspace, cx| {
let fs = workspace.app_state().fs.clone();
let destination_dir = destination_dir.clone();
let repo_url = repo_url.clone();
cx.spawn(async move |_workspace, _cx| {
fs.git_clone(&repo_url, destination_dir.as_path()).await
})
})
.ok()?;
if let Err(error) = clone_task.await {
workspace
.update(cx, |workspace, cx| {
let toast = StatusToast::new(error.to_string(), cx, |this, _| {
this.icon(ToastIcon::new(IconName::XCircle).color(Color::Error))
.dismiss_button(true)
});
workspace.toggle_status_toast(toast, cx);
})
.log_err();
return None;
}
let has_worktrees = workspace
.read_with(cx, |workspace, cx| {
workspace.project().read(cx).worktrees(cx).next().is_some()
})
.ok()?;
let prompt_answer = if has_worktrees {
cx.update(|window, cx| {
window.prompt(
gpui::PromptLevel::Info,
&format!("Git Clone: {}", repo_name),
None,
&["Add repo to project", "Open repo in new project"],
cx,
)
})
.ok()?
.await
.ok()?
} else {
// Don't ask if project is empty
0
};
destination_dir.push(&repo_name);
match prompt_answer {
0 => {
workspace
.update_in(cx, |workspace, window, cx| {
let create_task = workspace.project().update(cx, |project, cx| {
project.create_worktree(destination_dir.as_path(), true, cx)
});
let workspace_weak = cx.weak_entity();
let on_success = on_success.clone();
cx.spawn_in(window, async move |_window, cx| {
if create_task.await.log_err().is_some() {
workspace_weak
.update_in(cx, |workspace, window, cx| {
(on_success)(workspace, window, cx);
})
.ok();
}
})
.detach();
})
.ok()?;
}
1 => {
workspace
.update(cx, move |workspace, cx| {
let app_state = workspace.app_state().clone();
let destination_path = destination_dir.clone();
let on_success = on_success.clone();
workspace::open_new(
Default::default(),
app_state,
cx,
move |workspace, window, cx| {
cx.activate(true);
let create_task =
workspace.project().update(cx, |project, cx| {
project.create_worktree(
destination_path.as_path(),
true,
cx,
)
});
let workspace_weak = cx.weak_entity();
cx.spawn_in(window, async move |_window, cx| {
if create_task.await.log_err().is_some() {
workspace_weak
.update_in(cx, |workspace, window, cx| {
(on_success)(workspace, window, cx);
})
.ok();
}
})
.detach();
},
)
.detach();
})
.ok();
}
_ => {}
}
Some(())
})
.detach();
}