Skip to content

Commit

Permalink
feat: task shell (#2709)
Browse files Browse the repository at this point in the history
  • Loading branch information
roele authored Oct 7, 2024
1 parent a2dbcf8 commit d31569c
Show file tree
Hide file tree
Showing 12 changed files with 141 additions and 16 deletions.
2 changes: 2 additions & 0 deletions docs/tasks/toml-tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ dir = "{{cwd}}" # run in user's cwd, default is the project's base directory
[tasks.lint]
description = 'Lint with clippy'
env = {RUST_BACKTRACE = '1'} # env vars for the script
# specify a shell command to run the script with (default is 'sh -c')
shell = 'bash -c'
# you can specify a multiline script instead of individual commands
run = """
#!/usr/bin/env bash
Expand Down
4 changes: 4 additions & 0 deletions schema/mise.json
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,10 @@
}
]
},
"shell": {
"description": "shell command to run script with (e.g. sh -c)",
"type": "string"
},
"sources": {
"description": "files that this task depends on",
"items": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,17 @@ run = 'echo "configtask:"'
[tasks.lint]
run = 'echo "linting!"'

[tasks.shell]
run = '''
#MISE outputs=["$MISE_PROJECT_ROOT/test/test-build-output.txt"]
cd "$MISE_PROJECT_ROOT" || exit 1
echo "using shell $0" > test-build-output.txt
'''
shell = "bash -c"

[tasks."shell invalid"]
run = 'echo "invalid shell"'
shell = "bash"

[tasks.test]
run = 'echo "testing!"'
54 changes: 50 additions & 4 deletions src/cli/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,21 +297,44 @@ impl Run {
let filename = file.display().to_string();
self.exec(&filename, args, task, env, prefix)
} else {
let shell = self.get_shell(task);
trace!("using shell: {} {}", shell.0, shell.1);
#[cfg(windows)]
{
let script = format!("{} {}", script, args.join(" "));
let args = vec!["/c".to_string(), script];
self.exec("cmd", &args, task, env, prefix)
let args = vec![shell.1, script];
self.exec(shell.0.as_str(), &args, task, env, prefix)
}
#[cfg(unix)]
{
let script = format!("{} {}", script, shell_words::join(args));
let args = vec!["-c".to_string(), script];
self.exec("sh", &args, task, env, prefix)
let args = vec![shell.1, script];
self.exec(shell.0.as_str(), &args, task, env, prefix)
}
}
}

fn get_shell(&self, task: &Task) -> (String, String) {
let default_shell = if cfg!(windows) {
("cmd".to_string(), "/c".to_string())
} else {
("sh".to_string(), "-c".to_string())
};

if let Some(shell) = task.shell.clone() {
let shell_cmd = shell
.split_whitespace()
.map(|s| s.to_string())
.collect_tuple()
.unwrap_or_else(|| {
warn!("invalid shell '{shell}', expected '<program> <argument>' (e.g. sh -c)");
default_shell
});
return shell_cmd;
}
default_shell
}

fn exec_file(
&self,
file: &Path,
Expand Down Expand Up @@ -660,4 +683,27 @@ mod tests {
TEST_BUILDSCRIPT_ENV_VAR: VALID
"###);
}

#[test]
fn test_task_custom_shell() {
reset();
file::remove_all("test-build-output.txt").unwrap();
assert_cli_snapshot!(
"r",
"shell",
@"");
let body = file::read_to_string("test-build-output.txt").unwrap();
assert_snapshot!(body, @r###"
using shell bash
"###);
}

#[test]
fn test_task_custom_shell_invalid() {
reset();
assert_cli_snapshot!(
"r",
"shell invalid",
@"mise invalid shell 'bash', expected '<program> <argument>' (e.g. sh -c)");
}
}
16 changes: 10 additions & 6 deletions src/cli/tasks/deps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,14 +166,16 @@ mod tests {
#[test]
fn test_tasks_deps_tree() {
reset();
assert_cli_snapshot!("tasks", "deps", @r###"
assert_cli_snapshot!("tasks", "deps", @r#"
configtask
filetask
├── test
└── lint
lint
shell
shell invalid
test
"###
"#
);
}

Expand All @@ -193,16 +195,18 @@ mod tests {
#[test]
fn test_tasks_deps_dot() {
reset();
assert_cli_snapshot!("tasks", "deps", "--dot", @r###"
assert_cli_snapshot!("tasks", "deps", "--dot", @r#"
digraph {
0 [ label = "configtask"]
1 [ label = "filetask"]
2 [ label = "lint"]
3 [ label = "test"]
3 [ label = "shell"]
4 [ label = "shell invalid"]
5 [ label = "test"]
1 -> 2 [ ]
1 -> 3 [ ]
1 -> 5 [ ]
}
"###
"#
);
}
}
10 changes: 6 additions & 4 deletions src/cli/tasks/ls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,10 +194,12 @@ mod tests {
fn test_task_ls() {
reset();
assert_cli_snapshot!("t", "--no-headers", @r#"
configtask ~/config/config.toml
filetask This is a test build script ~/cwd/.mise/tasks/filetask
lint ~/config/config.toml
test ~/config/config.toml
configtask ~/config/config.toml
filetask This is a test build script ~/cwd/.mise/tasks/filetask
lint ~/config/config.toml
shell ~/config/config.toml
shell invalid ~/config/config.toml
test ~/config/config.toml
"#);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ expression: output
"name": "lint",
"source": "~/config/config.toml"
},
{
"description": "",
"name": "shell",
"source": "~/config/config.toml"
},
{
"description": "",
"name": "shell invalid",
"source": "~/config/config.toml"
},
{
"description": "",
"name": "test",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@ expression: output
"name": "lint",
"source": "~/config/config.toml"
},
{
"alias": "",
"description": "",
"name": "shell",
"source": "~/config/config.toml"
},
{
"alias": "",
"description": "",
"name": "shell invalid",
"source": "~/config/config.toml"
},
{
"alias": "",
"description": "",
Expand Down
14 changes: 12 additions & 2 deletions src/cli/use.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ mod tests {
mise ~/config/config.toml tools: [email protected]
mise tiny is defined in ~/cwd/.test-tool-versions which overrides the global config (~/config/config.toml)
"###);
assert_snapshot!(file::read_to_string(&cf_path).unwrap(), @r###"
assert_snapshot!(file::read_to_string(&cf_path).unwrap(), @r##"
[env]
TEST_ENV_VAR = 'test-123'
Expand All @@ -360,6 +360,16 @@ mod tests {
run = 'echo "linting!"'
[tasks.test]
run = 'echo "testing!"'
[tasks."shell invalid"]
shell = 'bash'
run = 'echo "invalid shell"'
[tasks.shell]
shell = 'bash -c'
run = '''
#MISE outputs=["$MISE_PROJECT_ROOT/test/test-build-output.txt"]
cd "$MISE_PROJECT_ROOT" || exit 1
echo "using shell $0" > test-build-output.txt
'''
[settings]
always_keep_download= true
always_keep_install= true
Expand All @@ -369,7 +379,7 @@ mod tests {
[tools]
tiny = "2"
"###);
"##);

file::write(&cf_path, orig).unwrap();
}
Expand Down
3 changes: 3 additions & 0 deletions src/task/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ pub struct Task {
pub sources: Vec<String>,
#[serde(default)]
pub outputs: Vec<String>,
#[serde(default)]
pub shell: Option<String>,

// normal type
#[serde(default, deserialize_with = "deserialize_arr")]
Expand Down Expand Up @@ -136,6 +138,7 @@ impl Task {
dir: p.parse_str("dir")?,
env: p.parse_env("env")?.unwrap_or_default(),
file: Some(path.to_path_buf()),
shell: p.parse_str("shell")?,
..Task::new(name_from_path(config_root, path)?, path.to_path_buf())
};
Ok(task)
Expand Down
10 changes: 10 additions & 0 deletions src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,16 @@ pub fn reset() {
run = 'echo "linting!"'
[tasks.test]
run = 'echo "testing!"'
[tasks."shell invalid"]
shell = 'bash'
run = 'echo "invalid shell"'
[tasks.shell]
shell = 'bash -c'
run = '''
#MISE outputs=["$MISE_PROJECT_ROOT/test/test-build-output.txt"]
cd "$MISE_PROJECT_ROOT" || exit 1
echo "using shell $0" > test-build-output.txt
'''
[settings]
always_keep_download= true
always_keep_install= true
Expand Down
10 changes: 10 additions & 0 deletions test/config/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@ run = 'echo "configtask:"'
run = 'echo "linting!"'
[tasks.test]
run = 'echo "testing!"'
[tasks."shell invalid"]
shell = 'bash'
run = 'echo "invalid shell"'
[tasks.shell]
shell = 'bash -c'
run = '''
#MISE outputs=["$MISE_PROJECT_ROOT/test/test-build-output.txt"]
cd "$MISE_PROJECT_ROOT" || exit 1
echo "using shell $0" > test-build-output.txt
'''
[settings]
always_keep_download= true
always_keep_install= true
Expand Down

0 comments on commit d31569c

Please sign in to comment.