Fix parsing of direnv export json
to support unset of environment variables + better logging (#32559)
Release Notes: - Fixed parsing of `direnv export json` output to support unset of environment variables.
This commit is contained in:
parent
65a1d09d24
commit
027ce6889c
2 changed files with 26 additions and 12 deletions
|
@ -9,7 +9,6 @@ pub enum DirenvError {
|
||||||
NotFound,
|
NotFound,
|
||||||
FailedRun,
|
FailedRun,
|
||||||
NonZeroExit(ExitStatus, Vec<u8>),
|
NonZeroExit(ExitStatus, Vec<u8>),
|
||||||
EmptyOutput,
|
|
||||||
InvalidJson,
|
InvalidJson,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +21,6 @@ impl From<DirenvError> for Option<EnvironmentErrorMessage> {
|
||||||
"Failed to run direnv. See logs for more info",
|
"Failed to run direnv. See logs for more info",
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
DirenvError::EmptyOutput => None,
|
|
||||||
DirenvError::InvalidJson => Some(EnvironmentErrorMessage(String::from(
|
DirenvError::InvalidJson => Some(EnvironmentErrorMessage(String::from(
|
||||||
"Direnv returned invalid json. See logs for more info",
|
"Direnv returned invalid json. See logs for more info",
|
||||||
))),
|
))),
|
||||||
|
@ -34,13 +32,14 @@ impl From<DirenvError> for Option<EnvironmentErrorMessage> {
|
||||||
pub async fn load_direnv_environment(
|
pub async fn load_direnv_environment(
|
||||||
env: &HashMap<String, String>,
|
env: &HashMap<String, String>,
|
||||||
dir: &Path,
|
dir: &Path,
|
||||||
) -> Result<HashMap<String, String>, DirenvError> {
|
) -> Result<HashMap<String, Option<String>>, DirenvError> {
|
||||||
let Ok(direnv_path) = which::which("direnv") else {
|
let Ok(direnv_path) = which::which("direnv") else {
|
||||||
return Err(DirenvError::NotFound);
|
return Err(DirenvError::NotFound);
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(direnv_output) = smol::process::Command::new(direnv_path)
|
let args = &["export", "json"];
|
||||||
.args(["export", "json"])
|
let Some(direnv_output) = smol::process::Command::new(&direnv_path)
|
||||||
|
.args(args)
|
||||||
.envs(env)
|
.envs(env)
|
||||||
.env("TERM", "dumb")
|
.env("TERM", "dumb")
|
||||||
.current_dir(dir)
|
.current_dir(dir)
|
||||||
|
@ -65,12 +64,21 @@ pub async fn load_direnv_environment(
|
||||||
|
|
||||||
let output = String::from_utf8_lossy(&direnv_output.stdout);
|
let output = String::from_utf8_lossy(&direnv_output.stdout);
|
||||||
if output.is_empty() {
|
if output.is_empty() {
|
||||||
return Err(DirenvError::EmptyOutput);
|
// direnv outputs nothing when it has no changes to apply to environment variables
|
||||||
|
return Ok(HashMap::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(env) = serde_json::from_str(&output).log_err() else {
|
match serde_json::from_str(&output) {
|
||||||
return Err(DirenvError::InvalidJson);
|
Ok(env) => Ok(env),
|
||||||
};
|
Err(err) => {
|
||||||
|
log::error!(
|
||||||
Ok(env)
|
"json parse error {}, while parsing output of `{} {}`:\n{}",
|
||||||
|
err,
|
||||||
|
direnv_path.display(),
|
||||||
|
args.join(" "),
|
||||||
|
output
|
||||||
|
);
|
||||||
|
Err(DirenvError::InvalidJson)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -274,7 +274,13 @@ async fn load_shell_environment(
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
if let Some(direnv_environment) = direnv_environment {
|
if let Some(direnv_environment) = direnv_environment {
|
||||||
envs.extend(direnv_environment);
|
for (key, value) in direnv_environment {
|
||||||
|
if let Some(value) = value {
|
||||||
|
envs.insert(key, value);
|
||||||
|
} else {
|
||||||
|
envs.remove(&key);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(Some(envs), direnv_error)
|
(Some(envs), direnv_error)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue