summaryrefslogtreecommitdiff
path: root/cli/tools/task.rs
blob: 39d493492fa81f95b7197f55c1d2b25febb9cc75 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.

use crate::args::Flags;
use crate::args::TaskFlags;
use crate::colors;
use crate::proc_state::ProcState;
use crate::util::fs::canonicalize_path;
use deno_core::anyhow::bail;
use deno_core::anyhow::Context;
use deno_core::error::AnyError;
use std::collections::BTreeMap;
use std::collections::HashMap;
use std::path::PathBuf;

fn print_available_tasks(tasks_config: BTreeMap<String, String>) {
  eprintln!("{}", colors::green("Available tasks:"));

  for name in tasks_config.keys() {
    eprintln!("- {}", colors::cyan(name));
    eprintln!("    {}", tasks_config[name])
  }
}

pub async fn execute_script(
  flags: Flags,
  task_flags: TaskFlags,
) -> Result<i32, AnyError> {
  let ps = ProcState::build(flags).await?;
  let tasks_config = ps.options.resolve_tasks_config()?;
  let config_file_url = ps.options.maybe_config_file_specifier().unwrap();
  let config_file_path = if config_file_url.scheme() == "file" {
    config_file_url.to_file_path().unwrap()
  } else {
    bail!("Only local configuration files are supported")
  };

  if task_flags.task.is_empty() {
    print_available_tasks(tasks_config);
    return Ok(1);
  }

  let cwd = match task_flags.cwd {
    Some(path) => canonicalize_path(&PathBuf::from(path))?,
    None => config_file_path.parent().unwrap().to_owned(),
  };
  let task_name = task_flags.task;
  let maybe_script = tasks_config.get(&task_name);

  if let Some(script) = maybe_script {
    let additional_args = ps
      .options
      .argv()
      .iter()
      // surround all the additional arguments in double quotes
      // and santize any command substition
      .map(|a| format!("\"{}\"", a.replace('"', "\\\"").replace('$', "\\$")))
      .collect::<Vec<_>>()
      .join(" ");
    let script = format!("{} {}", script, additional_args);
    let script = script.trim();
    log::info!(
      "{} {} {}",
      colors::green("Task"),
      colors::cyan(&task_name),
      script,
    );
    let seq_list = deno_task_shell::parser::parse(script)
      .with_context(|| format!("Error parsing script '{}'.", task_name))?;

    // get the starting env vars (the PWD env var will be set by deno_task_shell)
    let mut env_vars = std::env::vars().collect::<HashMap<String, String>>();
    const INIT_CWD_NAME: &str = "INIT_CWD";
    if !env_vars.contains_key(INIT_CWD_NAME) {
      if let Ok(cwd) = std::env::current_dir() {
        // if not set, set an INIT_CWD env var that has the cwd
        env_vars
          .insert(INIT_CWD_NAME.to_string(), cwd.to_string_lossy().to_string());
      }
    }

    let exit_code = deno_task_shell::execute(seq_list, env_vars, &cwd).await;
    Ok(exit_code)
  } else {
    eprintln!("Task not found: {}", task_name);
    print_available_tasks(tasks_config);
    Ok(1)
  }
}