@@ -586,6 +586,13 @@ impl Inventory {
.global
.entry(path.to_owned())
.insert_entry(new_templates.collect());
+ self.last_scheduled_tasks.retain(|(kind, _)| {
+ if let TaskSourceKind::AbsPath { abs_path, .. } = kind {
+ abs_path != path
+ } else {
+ true
+ }
+ });
}
TaskSettingsLocation::Worktree(location) => {
let new_templates = new_templates.collect::<Vec<_>>();
@@ -602,6 +609,18 @@ impl Inventory {
.or_default()
.insert(Arc::from(location.path), new_templates);
}
+ self.last_scheduled_tasks.retain(|(kind, _)| {
+ if let TaskSourceKind::Worktree {
+ directory_in_worktree,
+ id,
+ ..
+ } = kind
+ {
+ *id != location.worktree_id || directory_in_worktree != location.path
+ } else {
+ true
+ }
+ });
}
}
@@ -756,6 +775,27 @@ mod test_inventory {
});
}
+ pub(super) fn register_worktree_task_used(
+ inventory: &Entity<Inventory>,
+ worktree_id: WorktreeId,
+ task_name: &str,
+ cx: &mut TestAppContext,
+ ) {
+ inventory.update(cx, |inventory, cx| {
+ let (task_source_kind, task) = inventory
+ .list_tasks(None, None, Some(worktree_id), cx)
+ .into_iter()
+ .find(|(_, task)| task.label == task_name)
+ .unwrap_or_else(|| panic!("Failed to find task with name {task_name}"));
+ let id_base = task_source_kind.to_id_base();
+ inventory.task_scheduled(
+ task_source_kind.clone(),
+ task.resolve_task(&id_base, &TaskContext::default())
+ .unwrap_or_else(|| panic!("Failed to resolve task with name {task_name}")),
+ );
+ });
+ }
+
pub(super) async fn list_tasks(
inventory: &Entity<Inventory>,
worktree: Option<WorktreeId>,
@@ -997,6 +1037,53 @@ mod tests {
"2_task".to_string(),
"1_a_task".to_string(),
],
+ "Most recently used task should be at the top"
+ );
+
+ let worktree_id = WorktreeId::from_usize(0);
+ let local_worktree_location = SettingsLocation {
+ worktree_id,
+ path: Path::new("foo"),
+ };
+ inventory.update(cx, |inventory, _| {
+ inventory
+ .update_file_based_tasks(
+ TaskSettingsLocation::Worktree(local_worktree_location),
+ Some(&mock_tasks_from_names(["worktree_task_1"])),
+ )
+ .unwrap();
+ });
+ assert_eq!(
+ resolved_task_names(&inventory, None, cx),
+ vec![
+ "3_task".to_string(),
+ "1_task".to_string(),
+ "2_task".to_string(),
+ "1_a_task".to_string(),
+ ],
+ "Most recently used task should be at the top"
+ );
+ assert_eq!(
+ resolved_task_names(&inventory, Some(worktree_id), cx),
+ vec![
+ "3_task".to_string(),
+ "1_task".to_string(),
+ "2_task".to_string(),
+ "worktree_task_1".to_string(),
+ "1_a_task".to_string(),
+ ],
+ );
+ register_worktree_task_used(&inventory, worktree_id, "worktree_task_1", cx);
+ assert_eq!(
+ resolved_task_names(&inventory, Some(worktree_id), cx),
+ vec![
+ "worktree_task_1".to_string(),
+ "3_task".to_string(),
+ "1_task".to_string(),
+ "2_task".to_string(),
+ "1_a_task".to_string(),
+ ],
+ "Most recently used worktree task should be at the top"
);
inventory.update(cx, |inventory, _| {
@@ -1027,13 +1114,15 @@ mod tests {
assert_eq!(
resolved_task_names(&inventory, None, cx),
vec![
- "3_task".to_string(),
+ "worktree_task_1".to_string(),
+ "1_a_task".to_string(),
"1_task".to_string(),
"2_task".to_string(),
- "1_a_task".to_string(),
+ "3_task".to_string(),
"10_hello".to_string(),
"11_hello".to_string(),
],
+ "After global tasks update, worktree task usage is not erased and it's the first still; global task is back to regular order as its file was updated"
);
register_task_used(&inventory, "11_hello", cx);
@@ -1045,10 +1134,11 @@ mod tests {
resolved_task_names(&inventory, None, cx),
vec![
"11_hello".to_string(),
- "3_task".to_string(),
+ "worktree_task_1".to_string(),
+ "1_a_task".to_string(),
"1_task".to_string(),
"2_task".to_string(),
- "1_a_task".to_string(),
+ "3_task".to_string(),
"10_hello".to_string(),
],
);
@@ -1227,9 +1317,10 @@ mod tests {
})
}
- fn mock_tasks_from_names<'a>(task_names: impl Iterator<Item = &'a str> + 'a) -> String {
+ fn mock_tasks_from_names<'a>(task_names: impl IntoIterator<Item = &'a str> + 'a) -> String {
serde_json::to_string(&serde_json::Value::Array(
task_names
+ .into_iter()
.map(|task_name| {
json!({
"label": task_name,