Skip to content

Commit

Permalink
allow using templates in task files
Browse files Browse the repository at this point in the history
Fixes #1469
  • Loading branch information
jdx committed Jan 16, 2024
1 parent ec609a2 commit 814f9bb
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 39 deletions.
1 change: 1 addition & 0 deletions .mise/tasks/filetask
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# mise sources=[".test-tool-versions"]
# mise outputs=["$MISE_PROJECT_ROOT/test/test-build-output.txt"]
# mise env={TEST_BUILDSCRIPT_ENV_VAR = "VALID"}
# mise dir="{{config_root}}"

set -euxo pipefail
cd "$MISE_PROJECT_ROOT" || exit 1
Expand Down
2 changes: 1 addition & 1 deletion src/cli/task/edit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl TaskEdit {
.join(".mise")
.join("tasks")
.join(&self.task);
Task::from_path(path)
Task::from_path(&path)
},
Ok,
)?;
Expand Down
41 changes: 30 additions & 11 deletions src/config/config_file/toml.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,33 @@
use std::collections::HashMap;

use tera::{Context, Tera};

pub struct TomlParser<'a> {
pub table: &'a toml::Value,
table: &'a toml::Value,
tera: Tera,
tera_ctx: Context,
}

impl<'a> TomlParser<'a> {
pub fn new(table: &'a toml::Value) -> Self {
Self { table }
pub fn new(table: &'a toml::Value, tera: Tera, tera_ctx: Context) -> Self {
Self {
table,
tera,
tera_ctx,
}
}

pub fn parse_str(&self, key: &str) -> Option<String> {
pub fn parse_str(&self, key: &str) -> eyre::Result<Option<String>> {
self.table
.get(key)
.and_then(|value| value.as_str())
.map(|value| value.to_string())
.map(|s| self.render_tmpl(s))
.transpose()
}
pub fn parse_bool(&self, key: &str) -> Option<bool> {
self.table.get(key).and_then(|value| value.as_bool())
}
pub fn parse_array<T>(&self, key: &str) -> Option<Vec<T>>
pub fn parse_array<T>(&self, key: &str) -> eyre::Result<Option<Vec<T>>>
where
T: Default + From<String>,
{
Expand All @@ -28,11 +37,12 @@ impl<'a> TomlParser<'a> {
.map(|array| {
array
.iter()
.filter_map(|value| value.as_str().map(|v| v.to_string().into()))
.collect::<Vec<T>>()
.filter_map(|value| value.as_str().map(|v| self.render_tmpl(v)))
.collect::<eyre::Result<Vec<T>>>()
})
.transpose()
}
pub fn parse_hashmap<T>(&self, key: &str) -> Option<HashMap<String, T>>
pub fn parse_hashmap<T>(&self, key: &str) -> eyre::Result<Option<HashMap<String, T>>>
where
T: From<String>,
{
Expand All @@ -45,9 +55,18 @@ impl<'a> TomlParser<'a> {
.filter_map(|(key, value)| {
value
.as_str()
.map(|v| (key.to_string(), v.to_string().into()))
.map(|v| Ok((self.render_tmpl(key)?, self.render_tmpl(v)?)))
})
.collect::<HashMap<String, T>>()
.collect::<eyre::Result<HashMap<String, T>>>()
})
.transpose()
}

fn render_tmpl<T>(&self, tmpl: &str) -> eyre::Result<T>
where
T: From<String>,
{
let tmpl = self.tera.clone().render_str(tmpl, &self.tera_ctx)?;
Ok(tmpl.into())
}
}
4 changes: 2 additions & 2 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,10 +199,10 @@ impl Config {
.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) {
Either::Right(path) => match Task::from_path(&path) {
Ok(task) => vec![task],
Err(err) => {
warn!("Error loading task: {:#}", err);
warn!("Error loading task {}: {err:#}", display_path(&path));
vec![]
}
},
Expand Down
50 changes: 25 additions & 25 deletions src/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::collections::{HashMap, HashSet};
use std::fmt;
use std::fmt::{Display, Formatter};
use std::hash::{Hash, Hasher};
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use std::sync::mpsc;

use console::truncate_str;
Expand All @@ -17,6 +17,7 @@ use itertools::Itertools;
use crate::config::config_file::toml::TomlParser;
use crate::config::Config;
use crate::file;
use crate::tera::{get_tera, BASE_CONTEXT};
use crate::ui::tree::TreeItem;

#[derive(Debug, Default, Clone, Eq, PartialEq)]
Expand Down Expand Up @@ -55,8 +56,8 @@ impl Task {
..Default::default()
}
}
pub fn from_path(path: PathBuf) -> Result<Task> {
let info = file::read_to_string(&path)?
pub fn from_path(path: &Path) -> Result<Task> {
let info = file::read_to_string(path)?
.lines()
.filter_map(|line| regex!(r"^# mise ([a-z]+=.+)$").captures(line))
.map(|captures| captures.extract())
Expand All @@ -71,20 +72,23 @@ impl Task {
map
});
let info = toml::Value::Table(info);
let p = TomlParser::new(&info);
let config_root = project_root(path);
let mut tera_ctx = BASE_CONTEXT.clone();
tera_ctx.insert("config_root", &config_root);
let p = TomlParser::new(&info, get_tera(config_root), tera_ctx);
// trace!("task info: {:#?}", info);

let name = path.file_name().unwrap().to_str().unwrap().to_string();
let task = Task {
hide: !file::is_executable(&path) || p.parse_bool("hide").unwrap_or_default(),
description: p.parse_str("description").unwrap_or_default(),
sources: p.parse_array("sources").unwrap_or_default(),
outputs: p.parse_array("outputs").unwrap_or_default(),
depends: p.parse_array("depends").unwrap_or_default(),
dir: p.parse_str("dir").map(PathBuf::from),
env: p.parse_hashmap("env").unwrap_or_default(),
file: Some(path.clone()),
..Task::new(name, path)
hide: !file::is_executable(path) || p.parse_bool("hide").unwrap_or_default(),
description: p.parse_str("description")?.unwrap_or_default(),
sources: p.parse_array("sources")?.unwrap_or_default(),
outputs: p.parse_array("outputs")?.unwrap_or_default(),
depends: p.parse_array("depends")?.unwrap_or_default(),
dir: p.parse_str("dir")?.map(PathBuf::from),
env: p.parse_hashmap("env")?.unwrap_or_default(),
file: Some(path.to_path_buf()),
..Task::new(name, path.to_path_buf())
};
Ok(task)
}
Expand Down Expand Up @@ -145,18 +149,6 @@ impl Task {
.collect();
Ok(depends)
}

// pub fn project_root(&self) -> &Path {
// match self
// .config_source
// .parent()
// .expect("task source has no parent")
// {
// dir if dir.ends_with(".mise/tasks") => dir.parent().unwrap(),
// dir if dir.ends_with(".config/mise/tasks") => dir.parent().unwrap().parent().unwrap(),
// dir => dir,
// }
// }
}

impl Display for Task {
Expand Down Expand Up @@ -301,3 +293,11 @@ impl TreeItem for (&Graph<Task, ()>, NodeIndex) {
Cow::from(v)
}
}

fn project_root(config_source: &Path) -> &Path {
match config_source.parent().expect("task source has no parent") {
dir if dir.ends_with(".mise/tasks") => dir.parent().unwrap(),
dir if dir.ends_with(".config/mise/tasks") => dir.parent().unwrap().parent().unwrap(),
dir => dir,
}
}

0 comments on commit 814f9bb

Please sign in to comment.