// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! While fargo is mainly intended to be a command line tool, this library
//! exposes one function, `run_cargo`, that could be integrated directly into
//! Rust programs that want to cross compile cargo crates on Fuchsia.

#![deny(warnings)]

mod build_rustc;
pub mod command_line;
mod cross;
mod device;
mod linking;
mod manifest;
mod package;
mod sdk;
mod utils;

pub use crate::sdk::{FuchsiaConfig, TargetOptions};

use crate::cross::{pkg_config_path, run_configure};
use crate::device::{enable_networking, ffx, shell};
use crate::package::make_package;
use crate::sdk::{
    cargo_path, clang_archiver_path, clang_c_compiler_path, clang_cpp_compiler_path,
    clang_ranlib_path, clang_resource_dir, rustc_path, rustdoc_path, shared_libraries_path,
    sysroot_path, target_out_dir,
};
use manifest::Manifest;

use failure::{bail, err_msg, Error, ResultExt};
use std::fs;
use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::time::SystemTime;

fn run_program_on_target(
    filename: &str,
    verbose: bool,
    nocapture: bool,
    target_options: &TargetOptions<'_, '_>,
    run_mode: RunMode,
    run_cargo_options: &RunCargoOptions,
    app_dir: &str,
    app_name: &str,
    params: &[&str],
    test_args: Option<&str>,
) -> Result<(), Error> {
    let source_path = PathBuf::from(&filename);

    let target_string =
        make_package(verbose, target_options, &run_cargo_options, &source_path, app_dir, app_name)?;

    let mut command_string = match run_mode {
        RunMode::Tiles => "tiles_ctl add ".to_string(),
        RunMode::SessionControl => {
            format!("session_control add ")
        }
        RunMode::Run => "run ".to_string(),
        RunMode::FfxComponent => "component run ".to_string(),
        RunMode::FfxTest => "test run ".to_string(),
    };
    command_string.push_str(&target_string);

    if nocapture {
        command_string.push_str(" --");
        command_string.push_str(NOCAPTURE);
    }

    for param in params {
        command_string.push(' ');
        command_string.push_str(param);
    }

    if let Some(test_args_str) = test_args {
        command_string.push_str(" -- ");
        command_string.push_str(test_args_str);
    }

    if verbose {
        println!("running {}", command_string);
    }

    match run_mode {
        RunMode::FfxComponent | RunMode::FfxTest => {
            ffx(verbose, &command_string).context("ssh failed")?
        }
        _ => shell(verbose, target_options, &command_string).context("ssh failed")?,
    }
    Ok(())
}

extern crate notify;

use notify::{RecommendedWatcher, RecursiveMode, Watcher};
use std::sync::mpsc::channel;
use std::time::Duration;

fn autotest(
    run_cargo_options: &RunCargoOptions,
    target_options: &TargetOptions<'_, '_>,
) -> Result<(), Error> {
    let (tx, rx) = channel();
    let mut watcher: RecommendedWatcher =
        Watcher::new(tx, Duration::from_secs(1)).context("autotest: watcher creation failed")?;

    let cwd = std::fs::canonicalize(std::env::current_dir()?)
        .context("autotest: canonicalize working directory")?;
    let tgt = cwd.join("target");
    let git = cwd.join(".git");

    watcher.watch(&cwd, RecursiveMode::Recursive).context("autotest: watch failed")?;

    println!("autotest: started");
    loop {
        let event = rx.recv().context("autotest: watch recv failed")?;
        match event {
            notify::DebouncedEvent::Create(path)
            | notify::DebouncedEvent::Write(path)
            | notify::DebouncedEvent::Chmod(path)
            | notify::DebouncedEvent::Remove(path)
            | notify::DebouncedEvent::Rename(path, _) => {
                // TODO(raggi): provide a fuller ignore flag/pattern match solution here.
                if !path.starts_with(&tgt) && !path.starts_with(&git) {
                    println!("autotest: running tests because {:?}", path);
                    run_tests(
                        run_cargo_options,
                        false,
                        false,
                        false,
                        false,
                        target_options,
                        &[],
                        None,
                    )
                    .ok();
                }
            }
            _ => {}
        }
    }
}

fn run_tests(
    run_cargo_options: &RunCargoOptions,
    no_run: bool,
    doc: bool,
    lib: bool,
    bins: bool,
    target_options: &TargetOptions<'_, '_>,
    params: &[&str],
    target_params: Option<&str>,
) -> Result<(), Error> {
    let mut args = vec!["-Zdoctest-xcompile"];

    if no_run {
        args.push("--no-run");
    }

    if doc {
        args.push("--doc");
    }

    if lib {
        args.push("--lib");
    }

    if bins {
        args.push("--bins");
    }

    for param in params {
        args.push(param);
    }

    if let Some(target_params) = target_params {
        let formatted_target_params = format!("--args={}", target_params);
        run_cargo(
            &run_cargo_options,
            TEST,
            &args,
            target_options,
            None,
            Some(&formatted_target_params),
        )?;
    } else {
        run_cargo(&run_cargo_options, "test", &args, target_options, None, None)?;
    }

    Ok(())
}

fn build_binary(
    run_cargo_options: &RunCargoOptions,
    target_options: &TargetOptions<'_, '_>,
    params: &[&str],
) -> Result<(), Error> {
    run_cargo(run_cargo_options, BUILD, params, target_options, None, None)
}

fn check_binary(
    run_cargo_options: &RunCargoOptions,
    target_options: &TargetOptions<'_, '_>,
    params: &[&str],
) -> Result<(), Error> {
    run_cargo(run_cargo_options, "check", params, target_options, None, None)
}

fn run_binary(
    run_cargo_options: &RunCargoOptions,
    target_options: &TargetOptions<'_, '_>,
    params: &[&str],
) -> Result<(), Error> {
    run_cargo(run_cargo_options, RUN, params, target_options, None, None)?;
    Ok(())
}

fn build_doc(
    run_cargo_options: &RunCargoOptions,
    target_options: &TargetOptions<'_, '_>,
    no_deps: bool,
    open: bool,
) -> Result<(), Error> {
    let mut args = vec![];
    if no_deps {
        args.push("--no-deps");
    }
    if open {
        args.push("--open");
    }
    run_cargo(run_cargo_options, "doc", &args, &target_options, None, None)
}

#[derive(Clone, Copy, Debug)]
pub enum RunMode {
    Run,
    FfxComponent,
    FfxTest,
    Tiles,
    SessionControl,
}

impl Default for RunMode {
    fn default() -> Self {
        RunMode::Run
    }
}
fn run_switches_to_mode(
    ffx_component: bool,
    ffx_test: bool,
    tiles: bool,
    session_control: bool,
) -> RunMode {
    if tiles {
        RunMode::Tiles
    } else if session_control {
        RunMode::SessionControl
    } else if ffx_component {
        RunMode::FfxComponent
    } else if ffx_test {
        RunMode::FfxTest
    } else {
        RunMode::Run
    }
}

fn random_story_name() -> String {
    let secs = match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
        Ok(n) => n.as_secs(),
        Err(_) => panic!("SystemTime before UNIX EPOCH!"),
    };
    format!("fargo-story-{}", secs)
}

#[derive(Debug, Clone, Default)]
pub struct RunCargoOptions {
    pub fargo_manifest: Manifest,
    pub verbose: bool,
    pub release: bool,
    pub linking: bool,
    pub run_mode: RunMode,
    pub story_name: Option<String>,
    pub mod_name: Option<String>,
    pub disable_cross: bool,
    pub nocapture: bool,
    pub manifest_path: Option<PathBuf>,
    pub sandbox_file_path: Option<PathBuf>,
    pub app_dir: Option<String>,
    pub app_name: Option<String>,
}

impl RunCargoOptions {
    pub fn new(verbose: bool, release: bool) -> RunCargoOptions {
        Self { verbose, release, ..Self::default() }
    }

    pub fn disable_cross(&self, disable_cross: bool) -> RunCargoOptions {
        Self { disable_cross, ..self.clone() }
    }

    pub fn release(&self, release: bool) -> RunCargoOptions {
        Self { release, ..self.clone() }
    }

    pub fn linking(&self, linking: bool) -> RunCargoOptions {
        Self { linking, ..self.clone() }
    }

    pub fn nocapture(&self, nocapture: bool) -> RunCargoOptions {
        Self { nocapture, ..self.clone() }
    }

    pub fn run_mode(&self, run_mode: RunMode) -> RunCargoOptions {
        Self { run_mode, ..self.clone() }
    }

    pub fn story_name(&self, story_name: &Option<&str>) -> RunCargoOptions {
        Self { story_name: story_name.map(|name| name.to_string()), ..self.clone() }
    }

    pub fn mod_name(&self, mod_name: &Option<&str>) -> RunCargoOptions {
        Self { mod_name: mod_name.map(|name| name.to_string()), ..self.clone() }
    }

    pub fn manifest_path(&self, manifest_path: Option<PathBuf>) -> RunCargoOptions {
        Self { manifest_path, ..self.clone() }
    }

    pub fn sandbox_file_path(&self, sandbox_file_path: Option<PathBuf>) -> RunCargoOptions {
        Self { sandbox_file_path, ..self.clone() }
    }

    pub fn app_dir(&self, app_dir: &Option<&str>) -> RunCargoOptions {
        Self { app_dir: app_dir.map(|name| name.to_string()), ..self.clone() }
    }

    pub fn app_name(&self, app_name: &Option<&str>) -> RunCargoOptions {
        Self { app_name: app_name.map(|name| name.to_string()), ..self.clone() }
    }

    pub fn get_story_name(&self) -> String {
        if let Some(ref name) = self.story_name {
            name.clone()
        } else {
            random_story_name()
        }
    }

    pub fn get_mod_name(&self) -> String {
        if let Some(ref name) = self.mod_name {
            name.clone()
        } else {
            DEFAULT_MOD_NAME.to_string()
        }
    }
}

pub fn get_triple_cpu(target_options: &TargetOptions<'_, '_>) -> String {
    if (target_options.config.fuchsia_arch) == X64 { "x86_64" } else { "aarch64" }.to_string()
}

pub fn get_target_triple(target_options: &TargetOptions<'_, '_>) -> String {
    let triple_cpu = get_triple_cpu(target_options);

    format!("{}-fuchsia", triple_cpu)
}

pub fn get_vdso_path(target_options: &TargetOptions<'_, '_>) -> Result<PathBuf, Error> {
    let vdso_name =
        if target_options.config.fuchsia_arch == X64 { "user.vdso_x64" } else { "user.vdso_arm64" }
            .to_string();
    Ok(target_out_dir(target_options.config)?.join(vdso_name))
}

pub fn get_user_libc_path(target_options: &TargetOptions<'_, '_>) -> Result<PathBuf, Error> {
    let libc_name =
        if target_options.config.fuchsia_arch == X64 { "user.libc_x64" } else { "user.libc_arm64" }
            .to_string();
    Ok(target_out_dir(target_options.config)?.join(libc_name))
}

fn get_rustflags(
    run_cargo_options: &RunCargoOptions,
    target_options: &TargetOptions<'_, '_>,
    sysroot_as_path: &PathBuf,
    linking: bool,
) -> Result<String, Error> {
    let target_triple = get_target_triple(target_options);
    let sysroot_lib_pathbuf = sysroot_as_path.join("lib");
    let sysroot_lib = sysroot_lib_pathbuf.to_string_lossy();
    let shared_lib_path = shared_libraries_path(target_options)?;
    let clang_resource_lib = clang_resource_dir(&target_triple)?.join(&target_triple).join("lib");

    let mut rust_flags = vec![
        "-L".to_string(),
        sysroot_lib.to_string(),
        "-Cpanic=abort".to_string(),
        "-Zpanic_abort_tests".to_string(),
        // Add an extra config to let crates like scoped_task know we're compiling with
        // panic=abort. This matches
        // http://fuchsia.googlesource.com/fuchsia/+/08dce526941ac5be23cec1b50f841aad5ed37ea1/build/config/BUILD.gn#547
        "--cfg=rust_panic=\"abort\"".to_string(),
        "-Clink-arg=--pack-dyn-relocs=relr".to_string(),
        "-Clink-args=-zstack-size=0x200000".to_string(),
        format!("-Clink-arg=-L{}", sysroot_lib),
        format!("-Clink-arg=-L{}/gen/zircon/public/lib/fdio", shared_lib_path.to_string_lossy(),),
        format!("-Clink-arg=-L{}/gen/zircon/public/lib/syslog", shared_lib_path.to_string_lossy(),),
        format!(
            "-Clink-arg=-L{}/gen/zircon/public/lib/trace-engine",
            shared_lib_path.to_string_lossy(),
        ),
        format!("-Clink-arg=-L{}", clang_resource_lib.to_string_lossy()),
        format!("-Clink-arg=-L{}", target_out_dir(target_options.config)?.to_string_lossy()),
        format!("-Clink-arg=-L{}", get_vdso_path(target_options)?.to_string_lossy()),
        format!("-Clink-arg=--sysroot={}", sysroot_as_path.to_string_lossy()),
        format!(
            "-Clink-arg={}/obj/zircon/system/ulib/c/crt1.Scrt1.cc.o",
            get_user_libc_path(target_options)?.to_string_lossy()
        ),
        format!("-Lnative={}", shared_libraries_path(target_options)?.to_string_lossy()),
    ];

    if get_triple_cpu(target_options) == "aarch64" {
        rust_flags.push("-Clink-arg=--fix-cortex-a53-843419".to_string());
    }

    for search_path in &run_cargo_options.fargo_manifest.library_search_paths {
        let full_search_path = target_out_dir(&target_options.config)?.join(search_path);
        let arg = format!("-Lnative={}", full_search_path.to_string_lossy());
        rust_flags.push(arg);
    }

    if linking {
        for additional_lib in &run_cargo_options.fargo_manifest.additional_static_libraries {
            let arg = format!("-l{}", additional_lib);
            rust_flags.push(arg);
        }
    }

    Ok(rust_flags.join(" "))
}

fn make_absolute(path: &Path) -> Result<PathBuf, Error> {
    if path.is_absolute() {
        Ok(path.to_path_buf())
    } else {
        Ok(std::env::current_dir()?.join(path))
    }
}

fn make_fargo_command(
    runner: Option<PathBuf>,
    options: &RunCargoOptions,
    nocapture: bool,
    target_options: &TargetOptions<'_, '_>,
    additional_target_args: Option<&str>,
) -> Result<String, Error> {
    let sandbox_file_path;
    let tiles_arg = format!("--{}", RUN_WITH_TILES);
    let session_control_arg = format!("--{}", RUN_WITH_SESSION_CONTROL,);
    let manifest_path_absolute;
    let manifest_path_string;
    let sandbox_file_arg = format!("--{}", SANDBOX_FILE_PATH);
    let app_dir_arg = format!("--{}", APP_DIR);
    let app_name_arg = format!("--{}", APP_NAME);
    let run_arg = format!("--{}", RUN_WITH_RUN);
    let run_with_ffx_component_arg = format!("--{}", RUN_WITH_FFX_COMP);
    let run_with_ffx_test_arg = format!("--{}", RUN_WITH_FFX_TEST);
    let nocapture_arg = format!("--{}", NOCAPTURE);

    let fargo_path = if let Some(runner) = runner {
        runner
    } else {
        fs::canonicalize(std::env::current_exe()?)?
    };

    let mut runner_args = vec![fargo_path
        .to_str()
        .ok_or_else(|| err_msg("unable to convert path to utf8 encoding"))?];

    if options.verbose {
        runner_args.push("-v");
    }

    if let Some(manifest_path) = options.manifest_path.as_ref() {
        manifest_path_absolute = make_absolute(manifest_path)?;
        manifest_path_string = manifest_path_absolute.to_string_lossy();
        runner_args.push("--manifest-path");
        runner_args.push(&manifest_path_string);
    }

    if let Some(device_name) = target_options.device_name {
        runner_args.push("--device-name");
        runner_args.push(device_name);
    }

    runner_args.push(RUN_ON_TARGET);

    if let Some(ref passed_path) = options.sandbox_file_path {
        sandbox_file_path = passed_path.to_string_lossy().to_string();
        runner_args.push(&sandbox_file_arg);
        runner_args.push(&sandbox_file_path);
    }

    if nocapture {
        runner_args.push(&nocapture_arg);
    }

    match options.run_mode {
        RunMode::Tiles => runner_args.push(&tiles_arg),
        RunMode::SessionControl => runner_args.push(&session_control_arg),
        RunMode::Run => runner_args.push(&run_arg),
        RunMode::FfxComponent => runner_args.push(&run_with_ffx_component_arg),
        RunMode::FfxTest => runner_args.push(&run_with_ffx_test_arg),
    }

    if let Some(args_for_target) = additional_target_args {
        runner_args.push(&args_for_target);
    }

    if let Some(app_dir) = options.app_dir.as_ref() {
        runner_args.push(&app_dir_arg);
        runner_args.push(&app_dir);
    }

    if let Some(app_name) = options.app_name.as_ref() {
        runner_args.push(&app_name_arg);
        runner_args.push(&app_name);
    }

    Ok(runner_args.join(" "))
}

fn format_project(manifest_path: Option<PathBuf>) -> Result<(), Error> {
    let mut cmd = Command::new(cargo_path()?);
    if let Some(ref manifest_path) = manifest_path {
        let parent =
            manifest_path.parent().expect(&format!("Can't get parent of {:#?}", manifest_path));
        cmd.current_dir(parent);
    }
    cmd.arg(FORMAT);
    let cargo_status = cmd.status()?;
    if !cargo_status.success() {
        bail!("cargo exited with status {:?}", cargo_status,);
    }
    Ok(())
}

/// Runs the cargo tool configured to target Fuchsia. When used as a library,
/// the runner options must contain the path to fargo or some other program
/// that implements the `run-on-target` subcommand in a way compatible with
/// fargo.
///
/// # Examples
///
/// ```
/// use fargo::{run_cargo, FuchsiaConfig, RunCargoOptions, RunMode, TargetOptions};
///
/// let config = FuchsiaConfig::default();
/// let target_options = TargetOptions::new(&config, None);
/// run_cargo(
///     &RunCargoOptions {
///         verbose: false,
///         release: true,
///         nocapture: false,
///         run_mode: RunMode::Run,
///         ..RunCargoOptions::default()
///     },
///     "help",
///     &[],
///     &target_options,
///     None,
///     None,
/// );
/// ```
pub fn run_cargo(
    options: &RunCargoOptions,
    subcommand: &str,
    args: &[&str],
    target_options: &TargetOptions<'_, '_>,
    runner: Option<PathBuf>,
    additional_target_args: Option<&str>,
) -> Result<(), Error> {
    if options.verbose {
        println!("target_options = {:?}", target_options);
    }

    let triple_cpu = get_triple_cpu(target_options);
    let target_triple = get_target_triple(target_options);
    let mut target_args = vec!["--target", &target_triple];

    if options.release {
        target_args.push("--release");
    }

    if options.verbose {
        println!("target_options.target_cpu = {:?}", target_options.config.fuchsia_arch);
        println!("triple_cpu = {:?}", triple_cpu);
        println!("target_triple = {:?}", target_triple);
        println!("target_args = {:?}", target_args);
        println!("options = {:?}", options);
    }

    let target_triple_uc = format!("{}_fuchsia", triple_cpu).to_uppercase();

    let fargo_command = make_fargo_command(
        runner,
        &options,
        options.nocapture,
        target_options,
        additional_target_args,
    )?;

    if options.verbose {
        println!("fargo_command: {:?}", fargo_command);
    }

    let pkg_path = pkg_config_path(target_options)?;
    let mut cmd = Command::new(cargo_path()?);

    if options.verbose {
        cmd.arg("-v");
    }

    let sysroot_as_path = sysroot_path(target_options)?;
    let sysroot_as_str = sysroot_as_path.to_string_lossy();

    let args: Vec<&str> = args.iter().map(|a| if *a == "++" { "--" } else { *a }).collect();

    let runner_env_name = format!("CARGO_TARGET_{}_RUNNER", target_triple_uc);
    let rustflags_env_name = format!("CARGO_TARGET_{}_RUSTFLAGS", target_triple_uc);
    let rustflags = get_rustflags(options, target_options, &sysroot_as_path, options.linking)?;

    if options.verbose {
        println!("runner_env_name: {:?}", runner_env_name);
        println!("rustflags_env_name: {:?}", rustflags_env_name);
        println!("rustc_path: {:?}", rustc_path()?.to_string_lossy());
        println!("cargo_path: {:?}", cargo_path()?.to_string_lossy());
        println!("rustdoc_path: {:?}", rustdoc_path()?);
        println!("rustflags: {:?}", &rustflags);
    }

    cmd.env(runner_env_name, fargo_command)
        .env(rustflags_env_name, &rustflags)
        .env("RUSTC", rustc_path()?.to_string_lossy().as_ref())
        .env("RUSTDOC", rustdoc_path()?.to_string_lossy().as_ref())
        .env("RUSTDOCFLAGS", &rustflags)
        .env("FUCHSIA_SHARED_ROOT", shared_libraries_path(target_options)?)
        .arg(subcommand)
        .args(target_args)
        .args(args);

    if let Some(ref manifest_path) = options.manifest_path {
        let manifest_args: Vec<&str> = vec![
            "--manifest-path",
            manifest_path.to_str().expect("path to string failed for manifest_path"),
        ];
        cmd.args(manifest_args);
    }

    if !options.disable_cross {
        let cc_env_name = format!("CC_{}", target_triple_uc);
        let cxx_env_name = format!("CXX_{}", target_triple_uc);
        let cflags_env_name = format!("CFLAGS_{}", target_triple_uc);
        let ar_env_name = format!("AR_{}", target_triple_uc);
        cmd.env(cc_env_name, clang_c_compiler_path()?.to_string_lossy().as_ref())
            .env(cxx_env_name, clang_cpp_compiler_path()?.to_string_lossy().as_ref())
            .env(cflags_env_name, format!("--sysroot={}", sysroot_as_str))
            .env(ar_env_name, clang_archiver_path()?.to_string_lossy().as_ref())
            .env("RANLIB", clang_ranlib_path()?.to_string_lossy().as_ref())
            .env("PKG_CONFIG_ALL_STATIC", "1")
            .env("PKG_CONFIG_ALLOW_CROSS", "1")
            .env("PKG_CONFIG_PATH", "")
            .env("PKG_CONFIG_LIBDIR", pkg_path);
    }

    if options.verbose {
        println!("cargo cmd: {:?}", cmd);
    }

    let cargo_status = cmd.status()?;
    if !cargo_status.success() {
        bail!("cargo exited with status {:?}", cargo_status,);
    }

    Ok(())
}

fn write_config(
    options: &RunCargoOptions,
    target_options: &TargetOptions<'_, '_>,
) -> Result<(), Error> {
    let cargo_dir_path = Path::new(".cargo");
    if cargo_dir_path.exists() {
        if !cargo_dir_path.is_dir() {
            bail!(
                "fargo wants to create a directory {:#?}, but there is an existing file in the way",
                cargo_dir_path
            );
        }
    } else {
        fs::create_dir(cargo_dir_path)?;
    }

    let mut config = File::create(".cargo/config")?;

    let sysroot_as_path = sysroot_path(target_options)?;
    writeln!(config, "[target.{}]", get_target_triple(target_options))?;
    writeln!(
        config,
        "rustflags = {}",
        toml::ser::to_string(&get_rustflags(options, target_options, &sysroot_as_path, false)?)?
    )?;
    writeln!(
        config,
        "runner = \"{}\"",
        make_fargo_command(None, options, true, target_options, None)?
    )?;
    writeln!(config, "")?;
    writeln!(config, "[build]")?;
    writeln!(config, "rustc = \"{}\"", rustc_path()?.to_string_lossy())?;
    writeln!(config, "rustdoc = \"{}\"", rustdoc_path()?.to_string_lossy())?;
    writeln!(config, "target = \"{}\"", get_target_triple(target_options))?;
    Ok(())
}

const RUN: &str = "run";
const RUN_WITH_TILES: &str = "run-with-tiles";
const RUN_WITH_RUN: &str = "run-with-run";
const RUN_WITH_FFX_COMP: &str = "run-with-ffx-component";
const RUN_WITH_FFX_TEST: &str = "run-with-ffx-test";
const RUN_WITH_SESSION_CONTROL: &str = "run-with-session-control";
const DEFAULT_MOD_NAME: &str = "fargo";
const APP_DIR: &str = "app-dir";
const APP_NAME: &str = "app-name";

const BUILD: &str = "build";
const TEST: &str = "test";

const NOCAPTURE: &str = "nocapture";

const X64: &str = "x64";

const SANDBOX_FILE_PATH: &str = "sandbox-file-path";

const RUN_ON_TARGET: &str = "run-on-target";

const FORMAT: &str = "fmt";
