diff --git a/.gitignore b/.gitignore index 8e9330d0e..8506e7506 100644 --- a/.gitignore +++ b/.gitignore @@ -49,3 +49,5 @@ book/ .env* run-build.sh +# Amazon Q CLI files +.amazonq/ diff --git a/Cargo.lock b/Cargo.lock index 101afc77b..b638bf581 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -66,6 +66,7 @@ version = "1.19.3" dependencies = [ "bitflags 2.10.0", "camino", + "fig_os_shim", "serde", "serde_json", "serde_yaml", @@ -367,13 +368,12 @@ dependencies = [ [[package]] name = "assert_cmd" -version = "2.0.17" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bd389a4b2970a01282ee455294913c0a43724daedcd1a24c3eb0ec1c1320b66" +checksum = "bcbb6924530aa9e0432442af08bbcafdad182db80d2e560da42a6d442535bf85" dependencies = [ "anstyle", "bstr", - "doc-comment", "libc", "predicates", "predicates-core", @@ -2872,6 +2872,7 @@ dependencies = [ "bytes", "fig_auth", "fig_aws_common", + "fig_os_shim", "fig_request", "fig_settings", "fig_util", @@ -3206,6 +3207,7 @@ dependencies = [ name = "fig_log" version = "1.19.3" dependencies = [ + "fig_os_shim", "fig_util", "parking_lot", "tempfile", @@ -3276,6 +3278,7 @@ dependencies = [ "bytes", "cfg-if", "cookie", + "fig_os_shim", "fig_settings", "fig_util", "mockito", diff --git a/crates/alacritty_terminal/Cargo.toml b/crates/alacritty_terminal/Cargo.toml index c5233535b..87ed4568d 100644 --- a/crates/alacritty_terminal/Cargo.toml +++ b/crates/alacritty_terminal/Cargo.toml @@ -18,6 +18,7 @@ workspace = true [dependencies] bitflags.workspace = true camino.workspace = true +fig_os_shim.workspace = true serde.workspace = true serde_yaml = "0.9" shell-color.workspace = true diff --git a/crates/alacritty_terminal/src/term/mod.rs b/crates/alacritty_terminal/src/term/mod.rs index b4d6f4f43..97060521f 100644 --- a/crates/alacritty_terminal/src/term/mod.rs +++ b/crates/alacritty_terminal/src/term/mod.rs @@ -833,7 +833,7 @@ impl Term { trace!("New command cursor: {:?}", self.shell_state.cmd_cursor); // Add work around for emojis - if let Ok(cursor_offset) = std::env::var("Q_PROMPT_OFFSET_WORKAROUND") { + if let Ok(cursor_offset) = fig_os_shim::Env::new().q_prompt_offset_workaround() { if let Ok(offset) = cursor_offset.parse::() { self.shell_state.cmd_cursor = self.shell_state.cmd_cursor.map(|cursor| Point { column: Column((cursor.column.0 as i32 - offset).max(0) as usize), diff --git a/crates/fig_api_client/Cargo.toml b/crates/fig_api_client/Cargo.toml index c9d096857..77f3d11d8 100644 --- a/crates/fig_api_client/Cargo.toml +++ b/crates/fig_api_client/Cargo.toml @@ -27,6 +27,7 @@ aws-types.workspace = true bytes.workspace = true fig_auth.workspace = true fig_aws_common.workspace = true +fig_os_shim.workspace = true fig_request.workspace = true fig_settings.workspace = true fig_util.workspace = true diff --git a/crates/fig_api_client/src/clients/streaming_client.rs b/crates/fig_api_client/src/clients/streaming_client.rs index 341a28772..e648ada61 100644 --- a/crates/fig_api_client/src/clients/streaming_client.rs +++ b/crates/fig_api_client/src/clients/streaming_client.rs @@ -58,9 +58,7 @@ pub struct StreamingClient { impl StreamingClient { pub async fn new() -> Result { - let client = if fig_util::system_info::in_cloudshell() - || std::env::var("Q_USE_SENDMESSAGE").is_ok_and(|v| !v.is_empty()) - { + let client = if fig_util::system_info::in_cloudshell() || fig_os_shim::Env::new().q_use_sendmessage() { Self::new_qdeveloper_client(&Endpoint::load_q()).await? } else { Self::new_codewhisperer_client(&Endpoint::load_codewhisperer()).await diff --git a/crates/fig_desktop/src/main.rs b/crates/fig_desktop/src/main.rs index d488759e2..e2fd904d2 100644 --- a/crates/fig_desktop/src/main.rs +++ b/crates/fig_desktop/src/main.rs @@ -149,7 +149,7 @@ async fn main() -> ExitCode { #[cfg(target_os = "linux")] { - match std::env::var("Q_BACKEND").ok().as_deref() { + match fig_os_shim::Env::new().q_backend().ok().as_deref() { Some("default") => {}, // SAFETY: we are calling set_var in a single-threaded context. Some(backend) => unsafe { std::env::set_var("GDK_BACKEND", backend) }, diff --git a/crates/fig_install/src/index.rs b/crates/fig_install/src/index.rs index bf3d430a6..91ac3c5ac 100644 --- a/crates/fig_install/src/index.rs +++ b/crates/fig_install/src/index.rs @@ -45,7 +45,7 @@ const DEFAULT_RELEASE_URL: &str = "https://desktop-release.q.us-east-1.amazonaws /// - The setting `install.releaseUrl` /// - Falls back to the default or the build time env var `Q_BUILD_DESKTOP_RELEASE_URL` static RELEASE_URL: LazyLock = LazyLock::new(|| { - match std::env::var("Q_DESKTOP_RELEASE_URL") { + match fig_os_shim::Env::new().q_desktop_release_url() { Ok(s) => Url::parse(&s), Err(_) => match fig_settings::settings::get_string("install.releaseUrl") { Ok(Some(s)) => Url::parse(&s), diff --git a/crates/fig_log/Cargo.toml b/crates/fig_log/Cargo.toml index 2d1914a11..762598992 100644 --- a/crates/fig_log/Cargo.toml +++ b/crates/fig_log/Cargo.toml @@ -16,6 +16,7 @@ default = [] # sentry = ["dep:sentry-tracing"] [dependencies] +fig_os_shim.workspace = true fig_util.workspace = true parking_lot.workspace = true thiserror.workspace = true diff --git a/crates/fig_log/src/lib.rs b/crates/fig_log/src/lib.rs index 1a1bab561..00d380773 100644 --- a/crates/fig_log/src/lib.rs +++ b/crates/fig_log/src/lib.rs @@ -3,7 +3,6 @@ use std::path::Path; use std::sync::Mutex; use fig_util::CHAT_BINARY_NAME; -use fig_util::env_var::Q_LOG_LEVEL; use thiserror::Error; use tracing::info; use tracing::level_filters::LevelFilter; @@ -192,11 +191,11 @@ pub fn initialize_logging>(args: LogArgs) -> Result String { - Q_LOG_LEVEL_GLOBAL - .lock() - .unwrap() - .clone() - .unwrap_or_else(|| std::env::var(Q_LOG_LEVEL).unwrap_or_else(|_| DEFAULT_FILTER.to_string())) + Q_LOG_LEVEL_GLOBAL.lock().unwrap().clone().unwrap_or_else(|| { + fig_os_shim::Env::new() + .q_log_level() + .unwrap_or_else(|_| DEFAULT_FILTER.to_string()) + }) } /// Set the log level to the given level. @@ -247,7 +246,7 @@ fn create_filter_layer() -> EnvFilter { .lock() .unwrap() .clone() - .or_else(|| std::env::var(Q_LOG_LEVEL).ok()); + .or_else(|| fig_os_shim::Env::new().q_log_level().ok()); match log_level { Some(level) => EnvFilter::builder() diff --git a/crates/fig_os_shim/src/env.rs b/crates/fig_os_shim/src/env.rs index 8cdb696d0..810f40a84 100644 --- a/crates/fig_os_shim/src/env.rs +++ b/crates/fig_os_shim/src/env.rs @@ -165,6 +165,83 @@ impl Env { pub fn in_appimage(&self) -> bool { self.get_os("APPIMAGE").is_some() } + + // Q-specific environment variable methods + pub fn q_fake_is_remote(&self) -> bool { + self.get_os("Q_FAKE_IS_REMOTE").is_some() + } + + pub fn q_log_level(&self) -> Result { + self.get("Q_LOG_LEVEL") + } + + pub fn q_log_stdout(&self) -> bool { + self.get_os("Q_LOG_STDOUT").is_some() + } + + pub fn amazon_q_sigv4(&self) -> bool { + self.get("AMAZON_Q_SIGV4").is_ok_and(|v| !v.is_empty()) + } + + pub fn amazon_q_chat_shell(&self) -> String { + self.get("AMAZON_Q_CHAT_SHELL").unwrap_or_else(|_| "bash".to_string()) + } + + pub fn q_cli_client_application(&self) -> Result { + self.get("Q_CLI_CLIENT_APPLICATION") + } + + pub fn q_parent(&self) -> Result { + self.get("Q_PARENT") + } + + pub fn q_term(&self) -> Result { + self.get("Q_TERM") + } + + pub fn q_using_zsh_autosuggestions(&self) -> bool { + self.get_os("Q_USING_ZSH_AUTOSUGGESTIONS").is_some() + } + + pub fn q_init_snapshot_test(&self) -> bool { + self.get_os("Q_INIT_SNAPSHOT_TEST").is_some() + } + + pub fn q_desktop_release_url(&self) -> Result { + self.get("Q_DESKTOP_RELEASE_URL") + } + + pub fn q_inline_shell_completion_cache_enabled(&self) -> bool { + self.get_os("Q_INLINE_SHELL_COMPLETION_CACHE_DISABLE").is_none() + } + + pub fn q_inline_shell_completion_history_count(&self) -> Result { + self.get("Q_INLINE_SHELL_COMPLETION_HISTORY_COUNT") + } + + pub fn q_inline_shell_completion_debounce_ms(&self) -> Result { + self.get("Q_INLINE_SHELL_COMPLETION_DEBOUNCE_MS") + } + + pub fn q_backend(&self) -> Result { + self.get("Q_BACKEND") + } + + pub fn q_prompt_offset_workaround(&self) -> Result { + self.get("Q_PROMPT_OFFSET_WORKAROUND") + } + + pub fn q_use_sendmessage(&self) -> bool { + self.get("Q_USE_SENDMESSAGE").is_ok_and(|v| !v.is_empty()) + } + + pub fn q_custom_cert(&self) -> Result { + self.get("Q_CUSTOM_CERT") + } + + pub fn has_q_parent(&self) -> bool { + self.q_parent().is_ok() + } } impl Shim for Env { diff --git a/crates/fig_request/Cargo.toml b/crates/fig_request/Cargo.toml index 38206e1e7..2d1a24a09 100644 --- a/crates/fig_request/Cargo.toml +++ b/crates/fig_request/Cargo.toml @@ -18,6 +18,7 @@ workspace = true bytes.workspace = true cfg-if.workspace = true cookie = "0.18.0" +fig_os_shim.workspace = true fig_settings.workspace = true fig_util.workspace = true reqwest_cookie_store = "0.8.0" diff --git a/crates/fig_request/src/reqwest_client.rs b/crates/fig_request/src/reqwest_client.rs index 66cf346d3..04e9b1f44 100644 --- a/crates/fig_request/src/reqwest_client.rs +++ b/crates/fig_request/src/reqwest_client.rs @@ -23,7 +23,8 @@ pub fn create_default_root_cert_store() -> RootCertStore { let _ = root_cert_store.add(cert); } - let custom_cert = std::env::var("Q_CUSTOM_CERT") + let custom_cert = fig_os_shim::Env::new() + .q_custom_cert() .ok() .or_else(|| fig_settings::state::get_string("Q_CUSTOM_CERT").ok().flatten()); diff --git a/crates/fig_util/src/directories.rs b/crates/fig_util/src/directories.rs index db02361cf..3eb978190 100644 --- a/crates/fig_util/src/directories.rs +++ b/crates/fig_util/src/directories.rs @@ -354,7 +354,7 @@ pub fn remote_socket_path() -> Result { // Normal implementation for non-test code // TODO(grant): This is only enabled on Linux for now to prevent public dist if is_remote() && !in_cloudshell() && cfg!(target_os = "linux") { - if let Some(parent_socket) = std::env::var_os(Q_PARENT) { + if let Some(parent_socket) = fig_os_shim::Env::new().get_os(Q_PARENT) { Ok(PathBuf::from(parent_socket)) } else { Err(DirectoryError::QParentNotSet) diff --git a/crates/fig_util/src/system_info/mod.rs b/crates/fig_util/src/system_info/mod.rs index cbe728f9f..0a7158dce 100644 --- a/crates/fig_util/src/system_info/mod.rs +++ b/crates/fig_util/src/system_info/mod.rs @@ -15,7 +15,6 @@ use sha2::{ }; use crate::Error; -use crate::env_var::Q_PARENT; use crate::manifest::is_minimal; /// The support level for different platforms @@ -266,13 +265,13 @@ pub fn in_wsl() -> bool { /// Is the calling binary running on a remote instance pub fn is_remote() -> bool { // TODO(chay): Add detection for inside docker container - in_ssh() || in_cloudshell() || in_wsl() || std::env::var_os("Q_FAKE_IS_REMOTE").is_some() + in_ssh() || in_cloudshell() || in_wsl() || fig_os_shim::Env::new().q_fake_is_remote() } /// Determines if we have an IPC path to a Desktop app from a remote environment pub fn has_parent() -> bool { static HAS_PARENT: OnceLock = OnceLock::new(); - *HAS_PARENT.get_or_init(|| std::env::var_os(Q_PARENT).is_some()) + *HAS_PARENT.get_or_init(|| fig_os_shim::Env::new().has_q_parent()) } /// This true if the env var `AWS_EXECUTION_ENV=CloudShell` @@ -283,13 +282,12 @@ pub fn in_cloudshell() -> bool { pub fn in_codespaces() -> bool { static IN_CODESPACES: OnceLock = OnceLock::new(); - *IN_CODESPACES - .get_or_init(|| std::env::var_os("CODESPACES").is_some() || std::env::var_os("Q_CODESPACES").is_some()) + *IN_CODESPACES.get_or_init(|| fig_os_shim::Env::new().in_codespaces()) } pub fn in_ci() -> bool { static IN_CI: OnceLock = OnceLock::new(); - *IN_CI.get_or_init(|| std::env::var_os("CI").is_some() || std::env::var_os("Q_CI").is_some()) + *IN_CI.get_or_init(|| fig_os_shim::Env::new().in_ci()) } #[cfg(target_os = "macos")] diff --git a/crates/figterm/src/inline/mod.rs b/crates/figterm/src/inline/mod.rs index 62acc3b7b..f7d807fde 100644 --- a/crates/figterm/src/inline/mod.rs +++ b/crates/figterm/src/inline/mod.rs @@ -60,19 +60,21 @@ static INLINE_ENABLED: Mutex = Mutex::const_new(true); static LAST_RECEIVED: Mutex> = Mutex::const_new(None); static CACHE_ENABLED: LazyLock = - LazyLock::new(|| std::env::var_os("Q_INLINE_SHELL_COMPLETION_CACHE_DISABLE").is_none()); + LazyLock::new(|| fig_os_shim::Env::new().q_inline_shell_completion_cache_enabled()); static COMPLETION_CACHE: LazyLock> = LazyLock::new(|| Mutex::new(CompletionCache::new())); static TELEMETRY_QUEUE: Mutex = Mutex::const_new(TelemetryQueue::new()); static HISTORY_COUNT: LazyLock = LazyLock::new(|| { - std::env::var("Q_INLINE_SHELL_COMPLETION_HISTORY_COUNT") + fig_os_shim::Env::new() + .q_inline_shell_completion_history_count() .ok() .and_then(|s| s.parse().ok()) .unwrap_or(HISTORY_COUNT_DEFAULT) }); static DEBOUNCE_DURATION: LazyLock = LazyLock::new(|| { - std::env::var("Q_INLINE_SHELL_COMPLETION_DEBOUNCE_MS") + fig_os_shim::Env::new() + .q_inline_shell_completion_debounce_ms() .ok() .and_then(|s| s.parse().ok()) .map_or(DEBOUNCE_DURATION_DEFAULT, Duration::from_millis) diff --git a/crates/figterm/src/main.rs b/crates/figterm/src/main.rs index 573a71e26..dcdbbb799 100644 --- a/crates/figterm/src/main.rs +++ b/crates/figterm/src/main.rs @@ -69,7 +69,6 @@ use fig_settings::state; use fig_util::consts::CLI_BINARY_NAME; use fig_util::env_var::{ Q_LOG_LEVEL, - Q_PARENT, Q_SHELL, Q_TERM, QTERM_SESSION_ID, @@ -491,7 +490,7 @@ fn figterm_main(command: Option<&[String]>) -> Result<()> { std::env::set_var(QTERM_SESSION_ID, &session_id); } - let parent_id = std::env::var(Q_PARENT).ok(); + let parent_id = fig_os_shim::Env::new().q_parent().ok(); let mut terminal = SystemTerminal::new_from_stdio()?; let screen_size = terminal.get_screen_size()?; diff --git a/crates/figterm/tests/cli.rs b/crates/figterm/tests/cli.rs index a0f170286..30df49b54 100644 --- a/crates/figterm/tests/cli.rs +++ b/crates/figterm/tests/cli.rs @@ -5,7 +5,7 @@ use predicates::prelude::*; #[test] fn version_flag_has_status_code_zero() { - let mut cmd = Command::cargo_bin("figterm").unwrap(); + let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("figterm")); cmd.arg("--version"); cmd.assert() diff --git a/crates/q_cli/src/cli/doctor/checks/sshd_config.rs b/crates/q_cli/src/cli/doctor/checks/sshd_config.rs index 9a095ad85..5c6c8096a 100644 --- a/crates/q_cli/src/cli/doctor/checks/sshd_config.rs +++ b/crates/q_cli/src/cli/doctor/checks/sshd_config.rs @@ -4,7 +4,6 @@ use async_trait::async_trait; use eyre::Context; use fig_auth::is_amzn_user; use fig_util::CLI_BINARY_NAME; -use fig_util::env_var::Q_PARENT; use fig_util::url::AUTOCOMPLETE_SSH_WIKI; use owo_colors::OwoColorize; use regex::Regex; @@ -55,7 +54,7 @@ impl DoctorCheck<()> for SshdConfigCheck { let sshd_config = match std::fs::read_to_string(sshd_config_path).context("Could not read sshd_config") { Ok(config) => config, - Err(_err) if std::env::var_os(Q_PARENT).is_some() => { + Err(_err) if fig_os_shim::Env::new().q_parent().is_ok() => { // We will assume amzn users have this configured correctly and warn other users. if is_amzn_user().await.unwrap_or_default() { return Ok(()); diff --git a/crates/q_cli/src/cli/doctor/mod.rs b/crates/q_cli/src/cli/doctor/mod.rs index f8034c619..1a85f3228 100644 --- a/crates/q_cli/src/cli/doctor/mod.rs +++ b/crates/q_cli/src/cli/doctor/mod.rs @@ -77,7 +77,6 @@ use fig_util::env_var::{ PROCESS_LAUNCHED_BY_Q, Q_PARENT, Q_TERM, - Q_USING_ZSH_AUTOSUGGESTIONS, QTERM_SESSION_ID, }; use fig_util::macos::BUNDLE_CONTENTS_INFO_PLIST_PATH; @@ -522,7 +521,7 @@ impl DoctorCheck for RemoteSocketCheck { } async fn check(&self, _: &()) -> Result<(), DoctorError> { - let q_parent = std::env::var(Q_PARENT).ok(); + let q_parent = fig_os_shim::Env::new().q_parent().ok(); let remote_socket = remote_socket_path().map_err(|err| DoctorError::Error { reason: "Unable to get remote socket path".into(), info: vec![ @@ -688,14 +687,14 @@ impl DoctorCheck for FigIntegrationsCheck { // }); //} - match std::env::var(Q_TERM).as_deref() { + match fig_os_shim::Env::new().q_term().as_deref() { Ok(env!("CARGO_PKG_VERSION")) => Ok(()), Ok(ver) if env!("CARGO_PKG_VERSION").ends_with("-dev") || ver.ends_with("-dev") => Err(doctor_warning!( "{PTY_BINARY_NAME} is running with a different version than {PRODUCT_NAME} CLI, it looks like you are running a development version of {PRODUCT_NAME} however" )), Ok(_) => Err(DoctorError::Error { reason: "This terminal is not running with the latest integration, please restart your terminal".into(), - info: vec![format!("{Q_TERM}={}", std::env::var(Q_TERM).unwrap_or_default()).into()], + info: vec![format!("{Q_TERM}={}", fig_os_shim::Env::new().q_term().unwrap_or_default()).into()], fix: None, error: None, }), @@ -704,7 +703,7 @@ impl DoctorCheck for FigIntegrationsCheck { "{PTY_BINARY_NAME} is not running in this terminal, please try restarting your terminal" ) .into(), - info: vec![format!("{Q_TERM}={}", std::env::var(Q_TERM).unwrap_or_default()).into()], + info: vec![format!("{Q_TERM}={}", fig_os_shim::Env::new().q_term().unwrap_or_default()).into()], fix: None, error: None, }), @@ -745,7 +744,7 @@ impl DoctorCheck for InlineCheck { )); } - if std::env::var_os(Q_USING_ZSH_AUTOSUGGESTIONS).is_some() { + if fig_os_shim::Env::new().q_using_zsh_autosuggestions() { return Err(DoctorError::Error { reason: "Using zsh-autosuggestions is not supported at the same time as Inline".into(), info: vec![ diff --git a/crates/q_cli/src/cli/init.rs b/crates/q_cli/src/cli/init.rs index cb8f64583..0cac7d398 100644 --- a/crates/q_cli/src/cli/init.rs +++ b/crates/q_cli/src/cli/init.rs @@ -33,7 +33,7 @@ use crate::util::app_path_from_bundle_id; const INLINE_ENABLED_SETTINGS_KEY: &str = "inline.enabled"; const SHELL_INTEGRATIONS_ENABLED_STATE_KEY: &str = "shell-integrations.enabled"; -static IS_SNAPSHOT_TEST: LazyLock = LazyLock::new(|| std::env::var_os("Q_INIT_SNAPSHOT_TEST").is_some()); +static IS_SNAPSHOT_TEST: LazyLock = LazyLock::new(|| fig_os_shim::Env::new().q_init_snapshot_test()); #[derive(Debug, Args, PartialEq, Eq)] pub struct InitArgs { diff --git a/crates/q_cli/src/cli/mod.rs b/crates/q_cli/src/cli/mod.rs index 685f3a775..92447661a 100644 --- a/crates/q_cli/src/cli/mod.rs +++ b/crates/q_cli/src/cli/mod.rs @@ -310,7 +310,7 @@ impl Cli { ), false => None, }, - log_to_stdout: std::env::var_os("Q_LOG_STDOUT").is_some() || self.verbose > 0, + log_to_stdout: fig_os_shim::Env::new().q_log_stdout() || self.verbose > 0, log_file_path: match self.subcommand { Some(CliRootCommands::Chat { .. }) => Some("chat.log".to_owned()), Some(CliRootCommands::Translate(..)) => Some("translate.log".to_owned()), diff --git a/crates/q_cli/src/util/mod.rs b/crates/q_cli/src/util/mod.rs index 652064704..7db8da9b3 100644 --- a/crates/q_cli/src/util/mod.rs +++ b/crates/q_cli/src/util/mod.rs @@ -321,7 +321,7 @@ pub fn dialoguer_theme() -> ColorfulTheme { } pub async fn assert_logged_in() -> Result<(), Error> { - if !(std::env::var("AMAZON_Q_SIGV4").is_ok_and(|v| !v.is_empty()) || fig_auth::is_logged_in().await) { + if !(fig_os_shim::Env::new().amazon_q_sigv4() || fig_auth::is_logged_in().await) { bail!( "You are not logged in, please log in with {}", format!("{CLI_BINARY_NAME} login",).bold() diff --git a/crates/q_cli/tests/common/mod.rs b/crates/q_cli/tests/common/mod.rs index 92c1c3666..db4064daa 100644 --- a/crates/q_cli/tests/common/mod.rs +++ b/crates/q_cli/tests/common/mod.rs @@ -10,7 +10,7 @@ pub use predicates::prelude::*; pub type Result> = std::result::Result; pub fn cli() -> Command { - Command::cargo_bin(CLI_CRATE_NAME).unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("q_cli")) } pub fn is_json() -> FnPredicate bool, str> { diff --git a/crates/q_cli/tests/init.rs b/crates/q_cli/tests/init.rs index 6a57528c2..cf5de660b 100644 --- a/crates/q_cli/tests/init.rs +++ b/crates/q_cli/tests/init.rs @@ -22,7 +22,7 @@ macro_rules! init_test { paste! { #[cfg(not(windows))] fn []() -> Result> { - let mut cmd = Command::cargo_bin(CLI_CRATE_NAME)?; + let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("q_cli")); cmd.arg("init").arg($shell).arg($stage).arg("--rcfile").arg($file); cmd.env("Q_INIT_SNAPSHOT_TEST", "1"); let out = cmd.assert().success().get_output().stdout.clone();