From 37e5a99d53702ae3d4931f15035d36b6ef0021bd Mon Sep 17 00:00:00 2001 From: Jeff Dickey <216188+jdxcode@users.noreply.github.com> Date: Sat, 28 Jan 2023 03:01:41 -0600 Subject: [PATCH] use exec method for direnv --- .tool-versions | 1 - Cargo.lock | 18 ++++++++++++ Cargo.toml | 1 + e2e/test_local | 2 -- src/cli/direnv/activate.rs | 3 +- src/cli/direnv/envrc.rs | 8 +++--- src/cli/direnv/exec.rs | 56 ++++++++++++++++++++++++++++++++++++++ src/cli/direnv/mod.rs | 3 ++ src/env.rs | 1 + 9 files changed, 85 insertions(+), 8 deletions(-) create mode 100644 src/cli/direnv/exec.rs diff --git a/.tool-versions b/.tool-versions index a775f9b91..c638108e3 100644 --- a/.tool-versions +++ b/.tool-versions @@ -2,5 +2,4 @@ shellcheck 0.9.0 shfmt 3.6.0 # test comment #nodejs 18.13.0 -nodejs system jq latest diff --git a/Cargo.lock b/Cargo.lock index d8f3fbc4e..7932e5d17 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1028,6 +1028,7 @@ dependencies = [ "rmp-serde", "serde", "serde_derive", + "serde_json", "shell-escape", "simplelog", "tempfile", @@ -1058,6 +1059,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "ryu" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" + [[package]] name = "scopeguard" version = "1.1.0" @@ -1087,6 +1094,17 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_json" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" +dependencies = [ + "itoa", + "ryu", + "serde", +] + [[package]] name = "serde_spanned" version = "0.6.0" diff --git a/Cargo.toml b/Cargo.toml index 4758dfbc6..3824fd981 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,6 +55,7 @@ toml_edit = "0.18.0" url = "2.3.1" versions = "4.1.0" build-time = "0.1.2" +serde_json = "1.0.91" [target.'cfg(unix)'.dependencies] exec = "0.3.1" diff --git a/e2e/test_local b/e2e/test_local index 983c877b6..7db1c2893 100755 --- a/e2e/test_local +++ b/e2e/test_local @@ -11,7 +11,6 @@ assert "rtx local -p" "#python 3.11.1 3.10.9 # foo shellcheck 0.9.0 shfmt 3.6.0 # test comment #nodejs 18.13.0 -nodejs system jq latest " @@ -19,7 +18,6 @@ assert "rtx local -p shfmt@3.5.0" "#python 3.11.1 3.10.9 # foo shellcheck 0.9.0 shfmt 3.5.0 # test comment #nodejs 18.13.0 -nodejs system jq latest " diff --git a/src/cli/direnv/activate.rs b/src/cli/direnv/activate.rs index 8f0ff10bc..d3ea81ef3 100644 --- a/src/cli/direnv/activate.rs +++ b/src/cli/direnv/activate.rs @@ -20,10 +20,11 @@ impl Command for DirenvActivate { fn run(self, _config: Config, out: &mut Output) -> Result<()> { rtxprintln!( out, + // source_env "$(rtx direnv envrc "$@")" indoc! {r#" ### Do not edit. This was autogenerated by 'rtx direnv' ### use_rtx() {{ - source_env "$(rtx direnv envrc "$@")" + direnv_load rtx direnv exec }} "#} ); diff --git a/src/cli/direnv/envrc.rs b/src/cli/direnv/envrc.rs index 20d33271d..41d1df913 100644 --- a/src/cli/direnv/envrc.rs +++ b/src/cli/direnv/envrc.rs @@ -5,11 +5,11 @@ use std::ops::Deref; use color_eyre::eyre::Result; use crate::cli::command::Command; -use crate::config::settings::MissingRuntimeBehavior::{AutoInstall, Warn}; +use crate::config::settings::MissingRuntimeBehavior::{Prompt, Warn}; use crate::config::Config; -use crate::dirs; use crate::hash::hash_to_str; use crate::output::Output; +use crate::{dirs, env}; /// [internal] This is an internal command that writes an envrc file /// for direnv to consume. @@ -19,11 +19,11 @@ pub struct Envrc {} impl Command for Envrc { fn run(self, mut config: Config, out: &mut Output) -> Result<()> { - if config.settings.missing_runtime_behavior == AutoInstall { + if config.settings.missing_runtime_behavior == Prompt { config.settings.missing_runtime_behavior = Warn; } config.ensure_installed()?; - let envrc_path = dirs::ROOT + let envrc_path = env::RTX_TMP_DIR .join("direnv") .join(hash_to_str(dirs::CURRENT.deref()) + ".envrc"); diff --git a/src/cli/direnv/exec.rs b/src/cli/direnv/exec.rs new file mode 100644 index 000000000..95cbda2df --- /dev/null +++ b/src/cli/direnv/exec.rs @@ -0,0 +1,56 @@ +use color_eyre::eyre::Result; +use serde_derive::Deserialize; + +use crate::cli::command::Command; +use crate::cmd; +use crate::config::settings::MissingRuntimeBehavior::{Prompt, Warn}; +use crate::config::Config; +use crate::output::Output; + +/// [internal] This is an internal command that writes an envrc file +/// for direnv to consume. +#[derive(Debug, clap::Args)] +#[clap(verbatim_doc_comment, hide = true)] +pub struct DirenvExec {} + +#[derive(Debug, Default, Deserialize)] +struct DirenvWatches { + #[serde(rename(deserialize = "DIRENV_WATCHES"))] + watches: String, +} + +impl Command for DirenvExec { + fn run(self, mut config: Config, _out: &mut Output) -> Result<()> { + if config.settings.missing_runtime_behavior == Prompt { + config.settings.missing_runtime_behavior = Warn; + } + config.ensure_installed()?; + let mut cmd = cmd!("direnv", "dump"); + + for (k, v) in config.env()? { + cmd = cmd.env(k, v); + } + cmd = cmd.env("PATH", config.path_env()?); + + let json = cmd!("direnv", "watch", "json", ".tool-versions").read()?; + let w: DirenvWatches = serde_json::from_str(&json)?; + cmd = cmd.env("DIRENV_WATCHES", w.watches); + + cmd.run()?; + Ok(()) + } +} + +#[cfg(test)] +mod test { + + use crate::assert_cli; + + use super::*; + + #[test] + #[ignore] + fn test_direnv_exec() { + let Output { .. } = assert_cli!("direnv", "exec"); + } +} diff --git a/src/cli/direnv/mod.rs b/src/cli/direnv/mod.rs index 57343bd0e..54115c3f1 100644 --- a/src/cli/direnv/mod.rs +++ b/src/cli/direnv/mod.rs @@ -7,6 +7,7 @@ use crate::output::Output; mod activate; mod envrc; +mod exec; /// Output direnv function to use rtx inside direnv /// @@ -25,6 +26,7 @@ pub struct Direnv { #[derive(Debug, Subcommand)] enum Commands { Envrc(envrc::Envrc), + Exec(exec::DirenvExec), Activate(activate::DirenvActivate), } @@ -33,6 +35,7 @@ impl Commands { match self { Self::Activate(cmd) => cmd.run(config, out), Self::Envrc(cmd) => cmd.run(config, out), + Self::Exec(cmd) => cmd.run(config, out), } } } diff --git a/src/env.rs b/src/env.rs index c0997fd6a..29bf6f73b 100644 --- a/src/env.rs +++ b/src/env.rs @@ -48,6 +48,7 @@ lazy_static! { .map(PathBuf::from) .unwrap_or_else(|| XDG_DATA_HOME.join("rtx")) }; + pub static ref RTX_TMP_DIR: PathBuf = temp_dir().join("rtx"); pub static ref PATH: OsString = var_os("PATH").unwrap_or_default(); pub static ref SHELL: String = var("SHELL").unwrap_or_else(|_| "sh".into()); pub static ref RTX_EXE: PathBuf = current_exe().unwrap_or_else(|_| "rtx".into());