diff --git a/crates/project/src/project_settings.rs b/crates/project/src/project_settings.rs index 787efa20ff013cd034595800cb6a1ed6a18fe479..27c55f6fc04a3fe2c51e425cfeb089d6515f2794 100644 --- a/crates/project/src/project_settings.rs +++ b/crates/project/src/project_settings.rs @@ -24,7 +24,7 @@ use util::ResultExt; use worktree::{PathChange, UpdatedEntriesSet, Worktree, WorktreeId}; use crate::{ - task_store::TaskStore, + task_store::{TaskSettingsLocation, TaskStore}, worktree_store::{WorktreeStore, WorktreeStoreEvent}, }; @@ -642,7 +642,7 @@ impl SettingsObserver { LocalSettingsKind::Tasks(task_kind) => task_store.update(cx, |task_store, cx| { task_store .update_user_tasks( - Some(SettingsLocation { + TaskSettingsLocation::Worktree(SettingsLocation { worktree_id, path: directory.as_ref(), }), diff --git a/crates/project/src/project_tests.rs b/crates/project/src/project_tests.rs index 8647b3e821ab86b456f27abbc365a88a57f001ba..f989736b333e195faf5566d592ae95a9dd71b3b3 100644 --- a/crates/project/src/project_tests.rs +++ b/crates/project/src/project_tests.rs @@ -1,6 +1,6 @@ #![allow(clippy::format_collect)] -use crate::{task_inventory::TaskContexts, Event, *}; +use crate::{task_inventory::TaskContexts, task_store::TaskSettingsLocation, Event, *}; use buffer_diff::{ assert_hunks, BufferDiffEvent, DiffHunkSecondaryStatus, DiffHunkStatus, DiffHunkStatusKind, }; @@ -19,6 +19,7 @@ use lsp::{ NumberOrString, TextDocumentEdit, WillRenameFiles, }; use parking_lot::Mutex; +use paths::tasks_file; use pretty_assertions::{assert_eq, assert_matches}; use serde_json::json; #[cfg(not(windows))] @@ -327,7 +328,7 @@ async fn test_managing_project_specific_settings(cx: &mut gpui::TestAppContext) inventory.task_scheduled(topmost_local_task_source_kind.clone(), resolved_task); inventory .update_file_based_tasks( - None, + TaskSettingsLocation::Global(tasks_file()), Some( &json!([{ "label": "cargo check unstable", diff --git a/crates/project/src/task_inventory.rs b/crates/project/src/task_inventory.rs index 57ca5484795fd1cd4eb3f73a97d2d573e8b1bc22..ada33430ae192d6492dcd7092b6d519c8f5cd33d 100644 --- a/crates/project/src/task_inventory.rs +++ b/crates/project/src/task_inventory.rs @@ -13,7 +13,7 @@ use collections::{HashMap, HashSet, VecDeque}; use gpui::{App, AppContext as _, Entity, SharedString, Task}; use itertools::Itertools; use language::{ContextProvider, File, Language, LanguageToolchainStore, Location}; -use settings::{parse_json_with_comments, SettingsLocation, TaskKind}; +use settings::{parse_json_with_comments, TaskKind}; use task::{ DebugTaskDefinition, ResolvedTask, TaskContext, TaskId, TaskTemplate, TaskTemplates, TaskVariables, VariableName, @@ -22,7 +22,7 @@ use text::{Point, ToPoint}; use util::{paths::PathExt as _, post_inc, NumericPrefixWithSuffix, ResultExt as _}; use worktree::WorktreeId; -use crate::worktree_store::WorktreeStore; +use crate::{task_store::TaskSettingsLocation, worktree_store::WorktreeStore}; /// Inventory tracks available tasks for a given project. #[derive(Debug, Default)] @@ -33,7 +33,7 @@ pub struct Inventory { #[derive(Debug, Default)] struct ParsedTemplates { - global: Vec, + global: HashMap>, worktree: HashMap, TaskKind), Vec>>, } @@ -324,22 +324,20 @@ impl Inventory { ) -> impl '_ + Iterator { self.templates_from_settings .global - .clone() - .into_iter() - .map(|template| { - ( - TaskSourceKind::AbsPath { - id_base: match template.task_type { - task::TaskType::Script => Cow::Borrowed("global tasks.json"), - task::TaskType::Debug(_) => Cow::Borrowed("global debug.json"), - }, - abs_path: match template.task_type { - task::TaskType::Script => paths::tasks_file().clone(), - task::TaskType::Debug(_) => paths::debug_tasks_file().clone(), + .iter() + .flat_map(|(file_path, templates)| { + templates.into_iter().map(|template| { + ( + TaskSourceKind::AbsPath { + id_base: match template.task_type { + task::TaskType::Script => Cow::Borrowed("global tasks.json"), + task::TaskType::Debug(_) => Cow::Borrowed("global debug.json"), + }, + abs_path: file_path.clone(), }, - }, - template, - ) + template.clone(), + ) + }) }) } @@ -377,7 +375,7 @@ impl Inventory { /// Global tasks are updated for no worktree provided, otherwise the worktree metadata for a given path will be updated. pub(crate) fn update_file_based_tasks( &mut self, - location: Option>, + location: TaskSettingsLocation<'_>, raw_tasks_json: Option<&str>, task_kind: TaskKind, ) -> anyhow::Result<()> { @@ -395,7 +393,13 @@ impl Inventory { let parsed_templates = &mut self.templates_from_settings; match location { - Some(location) => { + TaskSettingsLocation::Global(path) => { + parsed_templates + .global + .entry(path.to_owned()) + .insert_entry(new_templates.collect()); + } + TaskSettingsLocation::Worktree(location) => { let new_templates = new_templates.collect::>(); if new_templates.is_empty() { if let Some(worktree_tasks) = @@ -411,8 +415,8 @@ impl Inventory { .insert((Arc::from(location.path), task_kind), new_templates); } } - None => parsed_templates.global = new_templates.collect(), } + Ok(()) } } @@ -651,8 +655,10 @@ impl ContextProvider for ContextProviderWithTasks { #[cfg(test)] mod tests { use gpui::TestAppContext; + use paths::tasks_file; use pretty_assertions::assert_eq; use serde_json::json; + use settings::SettingsLocation; use crate::task_store::TaskStore; @@ -684,7 +690,7 @@ mod tests { inventory.update(cx, |inventory, _| { inventory .update_file_based_tasks( - None, + TaskSettingsLocation::Global(tasks_file()), Some(&mock_tasks_from_names( expected_initial_state.iter().map(|name| name.as_str()), )), @@ -738,7 +744,7 @@ mod tests { inventory.update(cx, |inventory, _| { inventory .update_file_based_tasks( - None, + TaskSettingsLocation::Global(tasks_file()), Some(&mock_tasks_from_names( ["10_hello", "11_hello"] .into_iter() @@ -863,7 +869,7 @@ mod tests { inventory.update(cx, |inventory, _| { inventory .update_file_based_tasks( - None, + TaskSettingsLocation::Global(tasks_file()), Some(&mock_tasks_from_names( worktree_independent_tasks .iter() @@ -874,7 +880,7 @@ mod tests { .unwrap(); inventory .update_file_based_tasks( - Some(SettingsLocation { + TaskSettingsLocation::Worktree(SettingsLocation { worktree_id: worktree_1, path: Path::new(".zed"), }), @@ -886,7 +892,7 @@ mod tests { .unwrap(); inventory .update_file_based_tasks( - Some(SettingsLocation { + TaskSettingsLocation::Worktree(SettingsLocation { worktree_id: worktree_2, path: Path::new(".zed"), }), diff --git a/crates/project/src/task_store.rs b/crates/project/src/task_store.rs index 359d100abe6e3d0df5afa0fd415e93a933f5d83a..c24ad9c050c99abd171e4ed314957054faef3d4f 100644 --- a/crates/project/src/task_store.rs +++ b/crates/project/src/task_store.rs @@ -1,4 +1,7 @@ -use std::{path::PathBuf, sync::Arc}; +use std::{ + path::{Path, PathBuf}, + sync::Arc, +}; use anyhow::Context as _; use collections::HashMap; @@ -48,6 +51,12 @@ enum StoreMode { impl EventEmitter for TaskStore {} +#[derive(Debug)] +pub enum TaskSettingsLocation<'a> { + Global(&'a Path), + Worktree(SettingsLocation<'a>), +} + impl TaskStore { pub fn init(client: Option<&AnyProtoClient>) { if let Some(client) = client { @@ -286,7 +295,7 @@ impl TaskStore { pub(super) fn update_user_tasks( &self, - location: Option>, + location: TaskSettingsLocation<'_>, raw_tasks_json: Option<&str>, task_type: TaskKind, cx: &mut Context<'_, Self>, @@ -310,13 +319,19 @@ impl TaskStore { file_path: PathBuf, cx: &mut Context<'_, Self>, ) -> Task<()> { - let mut user_tasks_file_rx = watch_config_file(&cx.background_executor(), fs, file_path); + let mut user_tasks_file_rx = + watch_config_file(&cx.background_executor(), fs, file_path.clone()); let user_tasks_content = cx.background_executor().block(user_tasks_file_rx.next()); cx.spawn(async move |task_store, cx| { if let Some(user_tasks_content) = user_tasks_content { let Ok(_) = task_store.update(cx, |task_store, cx| { task_store - .update_user_tasks(None, Some(&user_tasks_content), task_kind, cx) + .update_user_tasks( + TaskSettingsLocation::Global(&file_path), + Some(&user_tasks_content), + task_kind, + cx, + ) .log_err(); }) else { return; @@ -325,7 +340,7 @@ impl TaskStore { while let Some(user_tasks_content) = user_tasks_file_rx.next().await { let Ok(()) = task_store.update(cx, |task_store, cx| { let result = task_store.update_user_tasks( - None, + TaskSettingsLocation::Global(&file_path), Some(&user_tasks_content), task_kind, cx,