1use std::path::Path;
8use std::process::Command;
9
10use ready_set_sdk::OutputMode;
11use ready_set_sdk::context::{ColorMode, LogLevel};
12
13#[derive(Debug, Clone)]
15pub struct EnvContract {
16 pub dispatcher_version: semver::Version,
18 pub project_root: Option<std::path::PathBuf>,
20 pub config_path: Option<std::path::PathBuf>,
22 pub output: OutputMode,
24 pub log: LogLevel,
26 pub color: ColorMode,
28}
29
30const KNOWN_VARS: &[&str] = &[
32 "READY_SET_DISPATCHER_VERSION",
33 "READY_SET_PROJECT_ROOT",
34 "READY_SET_CONFIG_PATH",
35 "READY_SET_OUTPUT",
36 "READY_SET_LOG",
37 "READY_SET_COLOR",
38];
39
40pub fn export_contract(cmd: &mut Command, contract: &EnvContract) {
44 for (key, _) in std::env::vars_os().filter(|(k, _)| {
46 k.to_string_lossy().starts_with("READY_SET_")
47 && !KNOWN_VARS.contains(&k.to_string_lossy().as_ref())
48 }) {
49 cmd.env_remove(&key);
50 }
51
52 cmd.env(
53 "READY_SET_DISPATCHER_VERSION",
54 contract.dispatcher_version.to_string(),
55 );
56 if let Some(root) = &contract.project_root {
57 cmd.env("READY_SET_PROJECT_ROOT", absolute_or_self(root));
58 } else {
59 cmd.env_remove("READY_SET_PROJECT_ROOT");
60 }
61 if let Some(path) = &contract.config_path {
62 cmd.env("READY_SET_CONFIG_PATH", absolute_or_self(path));
63 } else {
64 cmd.env_remove("READY_SET_CONFIG_PATH");
65 }
66 cmd.env(
67 "READY_SET_OUTPUT",
68 match contract.output {
69 OutputMode::Human => "human",
70 OutputMode::Json => "json",
71 },
72 );
73 cmd.env(
74 "READY_SET_LOG",
75 match contract.log {
76 LogLevel::Quiet => "quiet",
77 LogLevel::Normal => "normal",
78 LogLevel::Verbose => "verbose",
79 },
80 );
81 cmd.env(
82 "READY_SET_COLOR",
83 match contract.color {
84 ColorMode::Auto => "auto",
85 ColorMode::Always => "always",
86 ColorMode::Never => "never",
87 },
88 );
89}
90
91fn absolute_or_self(path: &Path) -> std::path::PathBuf {
92 std::fs::canonicalize(path).unwrap_or_else(|_| path.to_path_buf())
93}