Skip to content

Commit

Permalink
fix task loading
Browse files Browse the repository at this point in the history
Fixes #1593
  • Loading branch information
jdx committed Feb 7, 2024
1 parent 521c31e commit 09faaad
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 79 deletions.
2 changes: 1 addition & 1 deletion .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion src/cli/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,12 @@ impl Run {
})
.flat_map(|args| args.split_first().map(|(t, a)| (t.clone(), a.to_vec())))
.map(|(t, args)| {
let tasks = config.tasks_with_aliases()?.get_matching(&t)?;
let tasks = config
.tasks_with_aliases()?
.get_matching(&t)?
.into_iter()
.cloned()
.collect_vec();
if tasks.is_empty() {
ensure!(t == "default", "no tasks {} found", style::ered(t));

Expand Down
9 changes: 6 additions & 3 deletions src/cli/tasks/deps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl TasksDeps {
fn get_all_tasks(&self, config: &Config) -> Result<Vec<Task>> {
Ok(config
.tasks()?
.into_values()
.values()
.filter(|t| !t.hide)
.cloned()
.collect())
Expand Down Expand Up @@ -132,8 +132,11 @@ impl TasksDeps {
}

fn err_no_task(&self, config: &Config, t: &str) -> eyre::Report {
let tasks = config.tasks().unwrap_or_default();
let task_names = tasks.keys().sorted().map(style::ecyan).join(", ");
let tasks = config
.tasks()
.map(|t| t.keys().collect::<Vec<_>>())
.unwrap_or_default();
let task_names = tasks.into_iter().map(style::ecyan).join(", ");
let t = style(&t).yellow().for_stderr();
eyre!("no tasks named `{t}` found. Available tasks: {task_names}")
}
Expand Down
2 changes: 1 addition & 1 deletion src/cli/tasks/edit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ impl TasksEdit {

let task = config
.tasks_with_aliases()?
.get(&self.task)
.remove(&self.task)
.cloned()
.map_or_else(
|| {
Expand Down
2 changes: 1 addition & 1 deletion src/cli/tasks/ls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ impl TasksLs {
settings.ensure_experimental("`mise tasks ls`")?;
let rows = config
.tasks()?
.into_values()
.values()
.filter(|t| self.hidden || !t.hide)
.map(|t| t.into())
.collect::<Vec<Row>>();
Expand Down
136 changes: 67 additions & 69 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ use std::iter::once;
use std::path::{Path, PathBuf};
use std::sync::{Arc, OnceLock, RwLock};

use either::Either;
use eyre::{Context, Result};
use indexmap::IndexMap;
use itertools::Itertools;
use once_cell::sync::{Lazy, OnceCell};
use path_absolutize::Absolutize;
use rayon::prelude::*;

pub use settings::Settings;
Expand Down Expand Up @@ -47,7 +45,7 @@ pub struct Config {
all_aliases: OnceLock<AliasMap>,
repo_urls: HashMap<String, String>,
shorthands: OnceLock<HashMap<String, String>>,
tasks_with_aliases: OnceCell<BTreeMap<String, Task>>,
tasks: OnceCell<BTreeMap<String, Task>>,
}

static CONFIG: RwLock<Option<Arc<Config>>> = RwLock::new(None);
Expand Down Expand Up @@ -85,7 +83,7 @@ impl Config {
aliases: load_aliases(&config_files),
all_aliases: OnceLock::new(),
shorthands: OnceLock::new(),
tasks_with_aliases: OnceCell::new(),
tasks: OnceCell::new(),
project_root: get_project_root(&config_files),
config_files,
repo_urls,
Expand Down Expand Up @@ -148,19 +146,24 @@ impl Config {
self.all_aliases.get_or_init(|| self.load_all_aliases())
}

pub fn tasks(&self) -> Result<BTreeMap<&String, &Task>> {
pub fn tasks(&self) -> Result<&BTreeMap<String, Task>> {
self.tasks.get_or_try_init(|| self.load_all_tasks())
}

pub fn tasks_with_aliases(&self) -> Result<BTreeMap<String, &Task>> {
Ok(self
.tasks_with_aliases()?
.tasks()?
.iter()
.filter(|(n, t)| **n == *t.name)
.flat_map(|(_, t)| {
t.aliases
.iter()
.map(|a| (a.to_string(), t))
.chain(once((t.name.clone(), t)))
.collect::<Vec<_>>()
})
.collect())
}

pub fn tasks_with_aliases(&self) -> Result<&BTreeMap<String, Task>> {
self.tasks_with_aliases
.get_or_try_init(|| self.load_all_tasks())
}

pub fn is_activated(&self) -> bool {
env::var("__MISE_DIFF").is_ok()
}
Expand Down Expand Up @@ -208,66 +211,64 @@ impl Config {
}

pub fn load_all_tasks(&self) -> Result<BTreeMap<String, Task>> {
Ok(self
.config_files
.values()
Ok(file::all_dirs()?
.into_iter()
.collect_vec()
.into_par_iter()
.map(|cf| {
Ok(cf
.task_config()
.includes
.clone()
.unwrap_or_else(|| default_task_includes(cf.as_ref()))
.iter()
.map(|p| {
if let Some(pr) = cf.project_root() {
if p.is_relative() {
return Ok(file::replace_path(p)
.absolutize_from(pr)
.map(|p| p.to_path_buf())?);
}
}
Ok(p.to_path_buf())
})
.collect::<Result<Vec<PathBuf>>>()?
.into_par_iter()
.flat_map(|dir| {
file::recursive_ls(&dir).map_err(|err| warn!("load_all_tasks: {err}"))
})
.flatten()
.map(Either::Right)
.chain(rayon::iter::once(Either::Left(cf)))
.collect::<Vec<Either<_, _>>>())
})
.map(|d| self.load_tasks_in_dir(&d))
.collect::<Result<Vec<_>>>()?
.into_iter()
.flatten()
.chain(self.load_global_tasks())
.rev()
.unique()
.collect_vec()
.into_par_iter()
.flat_map(|either| match either {
Either::Left(cf) => cf.tasks().into_iter().cloned().collect(),
Either::Right(path) => match Task::from_path(&path) {
Ok(task) => vec![task],
Err(err) => {
warn!("Error loading task {}: {err:#}", display_path(&path));
vec![]
}
},
.inspect(|t| {
trace!(
"loading task {} from {}",
t.name,
display_path(&t.config_source)
)
})
.flat_map(|t| {
t.aliases
.iter()
.map(|a| (a.to_string(), t.clone()))
.chain(once((t.name.clone(), t.clone())))
.collect::<Vec<_>>()
.map(|t| (t.name.clone(), t))
.collect())
}

fn load_tasks_in_dir(&self, dir: &Path) -> Result<Vec<Task>> {
let configs = self.configs_at_root(dir);
let config_tasks = configs.iter().flat_map(|cf| cf.tasks()).cloned();
let includes = configs
.iter()
.find_map(|cf| cf.task_config().includes.clone())
.unwrap_or_else(default_task_includes);
let file_tasks = includes
.iter()
.map(|p| match p.is_absolute() {
true => file::recursive_ls(p),
false => file::recursive_ls(&dir.join(p)),
})
.collect::<Vec<_>>()
.flatten_ok()
.map_ok(|path| Task::from_path(&path))
.flatten_ok()
.collect::<Result<Vec<_>>>()?;
Ok(file_tasks.into_iter().chain(config_tasks).collect())
}

fn load_global_tasks(&self) -> Vec<Task> {
// TODO: add global file tasks
self.config_files
.get(&*env::MISE_GLOBAL_CONFIG_FILE)
.map(|cf| cf.tasks())
.unwrap_or_default()
.into_iter()
.rev()
.collect())
.cloned()
.collect()
}

fn configs_at_root(&self, dir: &Path) -> Vec<&dyn ConfigFile> {
DEFAULT_CONFIG_FILENAMES
.iter()
.map(|f| dir.join(f))
.filter_map(|f| self.config_files.get(&f).map(|cf| cf.as_ref()))
.collect()
}

pub fn get_tracked_config_files(&self) -> Result<ConfigMap> {
Expand Down Expand Up @@ -548,7 +549,7 @@ impl Debug for Config {
.collect::<Vec<_>>();
let mut s = f.debug_struct("Config");
s.field("Config Files", &config_files);
if let Some(tasks) = self.tasks_with_aliases.get() {
if let Some(tasks) = self.tasks.get() {
s.field(
"Tasks",
&tasks.values().map(|t| t.to_string()).collect_vec(),
Expand All @@ -571,11 +572,8 @@ impl Debug for Config {
}
}

fn default_task_includes(cf: &dyn ConfigFile) -> Vec<PathBuf> {
match cf.project_root() {
Some(pr) => vec![pr.join(".mise/tasks"), pr.join(".config/mise/tasks")],
None => vec![],
}
fn default_task_includes() -> Vec<PathBuf> {
vec![".mise/tasks".into(), ".config/mise/tasks".into()]
}

#[cfg(test)]
Expand Down
10 changes: 10 additions & 0 deletions src/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,16 @@ pub fn make_executable(path: &Path) -> Result<()> {
Ok(())
}

pub fn all_dirs() -> Result<Vec<PathBuf>> {
let mut output = vec![];
let mut cwd = dirs::CWD.as_ref().map(|p| p.as_path());
while let Some(dir) = cwd {
output.push(dir.to_path_buf());
cwd = dir.parent();
}
Ok(output)
}

fn is_empty_dir(path: &Path) -> Result<bool> {
path.read_dir()
.map(|mut i| i.next().is_none())
Expand Down
6 changes: 3 additions & 3 deletions src/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ impl Task {
let tasks = config.tasks_with_aliases()?;
self.depends
.iter()
.map(|pat| match_tasks(tasks, pat))
.map(|pat| match_tasks(tasks.clone(), pat))
.flatten_ok()
.filter_ok(|t| t.name != self.name)
.collect()
Expand All @@ -177,8 +177,8 @@ fn name_from_path(root: impl AsRef<Path>, path: impl AsRef<Path>) -> Result<Stri
.join(":"))
}

fn match_tasks<'a>(tasks: &'a BTreeMap<String, Task>, pat: &str) -> Result<Vec<&'a Task>> {
let matches = tasks.get_matching(pat)?;
fn match_tasks<'a>(tasks: BTreeMap<String, &'a Task>, pat: &str) -> Result<Vec<&'a Task>> {
let matches = tasks.get_matching(pat)?.into_iter().cloned().collect_vec();
if matches.is_empty() {
return Err(eyre!("task not found: {pat}"));
};
Expand Down

0 comments on commit 09faaad

Please sign in to comment.