Enqueue default prettier installations

This commit is contained in:
Kirill Bulatov 2023-10-31 11:54:40 +02:00
parent fd6f6cc9f8
commit 6ee9beed73

View File

@ -162,13 +162,20 @@ pub struct Project {
copilot_log_subscription: Option<lsp::Subscription>, copilot_log_subscription: Option<lsp::Subscription>,
current_lsp_settings: HashMap<Arc<str>, LspSettings>, current_lsp_settings: HashMap<Arc<str>, LspSettings>,
node: Option<Arc<dyn NodeRuntime>>, node: Option<Arc<dyn NodeRuntime>>,
default_prettier_plugins: Option<HashSet<&'static str>>, #[cfg(not(any(test, feature = "test-support")))]
default_prettier: Option<DefaultPrettier>,
prettier_instances: HashMap< prettier_instances: HashMap<
(Option<WorktreeId>, PathBuf), (Option<WorktreeId>, PathBuf),
Shared<Task<Result<Arc<Prettier>, Arc<anyhow::Error>>>>, Shared<Task<Result<Arc<Prettier>, Arc<anyhow::Error>>>>,
>, >,
} }
#[cfg(not(any(test, feature = "test-support")))]
struct DefaultPrettier {
installation_process: Option<Shared<Task<()>>>,
installed_plugins: HashSet<&'static str>,
}
struct DelayedDebounced { struct DelayedDebounced {
task: Option<Task<()>>, task: Option<Task<()>>,
cancel_channel: Option<oneshot::Sender<()>>, cancel_channel: Option<oneshot::Sender<()>>,
@ -678,7 +685,8 @@ impl Project {
copilot_log_subscription: None, copilot_log_subscription: None,
current_lsp_settings: settings::get::<ProjectSettings>(cx).lsp.clone(), current_lsp_settings: settings::get::<ProjectSettings>(cx).lsp.clone(),
node: Some(node), node: Some(node),
default_prettier_plugins: None, #[cfg(not(any(test, feature = "test-support")))]
default_prettier: None,
prettier_instances: HashMap::default(), prettier_instances: HashMap::default(),
} }
}) })
@ -778,7 +786,8 @@ impl Project {
copilot_log_subscription: None, copilot_log_subscription: None,
current_lsp_settings: settings::get::<ProjectSettings>(cx).lsp.clone(), current_lsp_settings: settings::get::<ProjectSettings>(cx).lsp.clone(),
node: None, node: None,
default_prettier_plugins: None, #[cfg(not(any(test, feature = "test-support")))]
default_prettier: None,
prettier_instances: HashMap::default(), prettier_instances: HashMap::default(),
}; };
for worktree in worktrees { for worktree in worktrees {
@ -8541,36 +8550,66 @@ impl Project {
}; };
let mut plugins_to_install = prettier_plugins; let mut plugins_to_install = prettier_plugins;
if let Some(already_installed) = &self.default_prettier_plugins { let (mut install_success_tx, mut install_success_rx) =
plugins_to_install.retain(|plugin| !already_installed.contains(plugin)); futures::channel::mpsc::channel::<HashSet<&'static str>>(1);
let new_installation_process = cx
.spawn(|this, mut cx| async move {
if let Some(installed_plugins) = install_success_rx.next().await {
this.update(&mut cx, |this, _| {
let default_prettier =
this.default_prettier
.get_or_insert_with(|| DefaultPrettier {
installation_process: None,
installed_plugins: HashSet::default(),
});
if !installed_plugins.is_empty() {
log::info!("Installed new prettier plugins: {installed_plugins:?}");
default_prettier.installed_plugins.extend(installed_plugins);
} }
if plugins_to_install.is_empty() && self.default_prettier_plugins.is_some() { })
}
})
.shared();
let previous_installation_process =
if let Some(default_prettier) = &mut self.default_prettier {
plugins_to_install
.retain(|plugin| !default_prettier.installed_plugins.contains(plugin));
if plugins_to_install.is_empty() {
return Task::ready(Ok(())); return Task::ready(Ok(()));
} }
std::mem::replace(
let previous_plugins = self.default_prettier_plugins.clone(); &mut default_prettier.installation_process,
self.default_prettier_plugins Some(new_installation_process.clone()),
.get_or_insert_with(HashSet::default) )
.extend(plugins_to_install.iter()); } else {
let (mut install_success_tx, mut install_success_rx) = None
futures::channel::mpsc::channel::<()>(1); };
cx.spawn(|this, mut cx| async move {
if install_success_rx.next().await.is_none() {
this.update(&mut cx, |this, _| {
log::warn!("Prettier plugin installation did not finish successfully, restoring previous installed plugins {previous_plugins:?}");
this.default_prettier_plugins = previous_plugins;
})
}
})
.detach();
let default_prettier_dir = util::paths::DEFAULT_PRETTIER_DIR.as_path(); let default_prettier_dir = util::paths::DEFAULT_PRETTIER_DIR.as_path();
let already_running_prettier = self let already_running_prettier = self
.prettier_instances .prettier_instances
.get(&(worktree, default_prettier_dir.to_path_buf())) .get(&(worktree, default_prettier_dir.to_path_buf()))
.cloned(); .cloned();
let fs = Arc::clone(&self.fs); let fs = Arc::clone(&self.fs);
cx.spawn(|this, mut cx| async move {
if let Some(previous_installation_process) = previous_installation_process {
previous_installation_process.await;
}
let mut everything_was_installed = false;
this.update(&mut cx, |this, _| {
match &mut this.default_prettier {
Some(default_prettier) => {
plugins_to_install
.retain(|plugin| !default_prettier.installed_plugins.contains(plugin));
everything_was_installed = plugins_to_install.is_empty();
},
None => this.default_prettier = Some(DefaultPrettier { installation_process: Some(new_installation_process), installed_plugins: HashSet::default() }),
}
});
if everything_was_installed {
return Ok(());
}
cx.background() cx.background()
.spawn(async move { .spawn(async move {
let prettier_wrapper_path = default_prettier_dir.join(prettier::PRETTIER_SERVER_FILE); let prettier_wrapper_path = default_prettier_dir.join(prettier::PRETTIER_SERVER_FILE);
@ -8601,7 +8640,7 @@ impl Project {
}).collect::<Vec<_>>(); }).collect::<Vec<_>>();
node.npm_install_packages(default_prettier_dir, &borrowed_packages).await.context("fetching formatter packages")?; node.npm_install_packages(default_prettier_dir, &borrowed_packages).await.context("fetching formatter packages")?;
let installed_packages = !plugins_to_install.is_empty(); let installed_packages = !plugins_to_install.is_empty();
install_success_tx.try_send(()).ok(); install_success_tx.try_send(plugins_to_install).ok();
if !installed_packages { if !installed_packages {
if let Some(prettier) = already_running_prettier { if let Some(prettier) = already_running_prettier {
@ -8610,6 +8649,7 @@ impl Project {
} }
anyhow::Ok(()) anyhow::Ok(())
}).await
}) })
} }
} }