From 51a7db4b61e1e040196bd420a4cf59250693b08e Mon Sep 17 00:00:00 2001 From: Channing Conger Date: Tue, 7 Jul 2026 16:12:20 -0700 Subject: [PATCH 1/7] Enable code mode host by default --- codex-rs/core/tests/common/test_codex.rs | 6 ++++++ codex-rs/features/src/lib.rs | 4 ++-- codex-rs/features/src/tests.rs | 10 ++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/codex-rs/core/tests/common/test_codex.rs b/codex-rs/core/tests/common/test_codex.rs index e0e82c37fd70..8e565ff34670 100644 --- a/codex-rs/core/tests/common/test_codex.rs +++ b/codex-rs/core/tests/common/test_codex.rs @@ -708,6 +708,12 @@ impl TestCodexBuilder { } else { load_default_config_for_test(home).await }; + // Core tests run without an installed sibling code-mode host binary. Tests that exercise + // the process host opt in explicitly after this default test-harness override. + config + .features + .disable(Feature::CodeModeHost) + .expect("test config should allow disabling the code-mode host"); config.cwd = cwd_override; config.model_provider = model_provider; if let Ok(path) = codex_utils_cargo_bin::cargo_bin("codex") { diff --git a/codex-rs/features/src/lib.rs b/codex-rs/features/src/lib.rs index 166dc912fdaa..bc6cffe2bf1c 100644 --- a/codex-rs/features/src/lib.rs +++ b/codex-rs/features/src/lib.rs @@ -857,8 +857,8 @@ pub const FEATURES: &[FeatureSpec] = &[ FeatureSpec { id: Feature::CodeModeHost, key: "code_mode_host", - stage: Stage::UnderDevelopment, - default_enabled: false, + stage: Stage::Stable, + default_enabled: true, }, FeatureSpec { id: Feature::CodeModeOnly, diff --git a/codex-rs/features/src/tests.rs b/codex-rs/features/src/tests.rs index 7291c4e1b1af..3a627a3f81a3 100644 --- a/codex-rs/features/src/tests.rs +++ b/codex-rs/features/src/tests.rs @@ -123,6 +123,16 @@ fn code_mode_only_requires_code_mode() { assert_eq!(features.enabled(Feature::CodeMode), true); } +#[test] +fn code_mode_host_is_stable_and_enabled_by_default() { + assert_eq!(Feature::CodeModeHost.stage(), Stage::Stable); + assert_eq!(Feature::CodeModeHost.default_enabled(), true); + assert_eq!( + feature_for_key("code_mode_host"), + Some(Feature::CodeModeHost) + ); +} + #[test] fn guardian_approval_is_stable_and_enabled_by_default() { let spec = Feature::GuardianApproval.info(); From ad91ea20530f337d7b60e2416b5dabfbd24c6cc7 Mon Sep 17 00:00:00 2001 From: Channing Conger Date: Tue, 7 Jul 2026 16:19:31 -0700 Subject: [PATCH 2/7] Run core code mode tests through host --- codex-rs/core/BUILD.bazel | 1 + codex-rs/core/src/test_support.rs | 7 ++++++ codex-rs/core/src/thread_manager.rs | 10 +++++++++ codex-rs/core/tests/common/test_codex.rs | 27 ++++++++++++++++++----- codex-rs/core/tests/suite/code_mode.rs | 28 ++++++++++++++++++------ 5 files changed, 60 insertions(+), 13 deletions(-) diff --git a/codex-rs/core/BUILD.bazel b/codex-rs/core/BUILD.bazel index a55a98e1862d..f9307e8dc004 100644 --- a/codex-rs/core/BUILD.bazel +++ b/codex-rs/core/BUILD.bazel @@ -14,6 +14,7 @@ codex_rust_crate( crate_name = "codex_core", extra_binaries = [ "//codex-rs/bwrap:bwrap", + "//codex-rs/code-mode-host:code-mode-host", "//codex-rs/linux-sandbox:codex-linux-sandbox", "//codex-rs/rmcp-client:test_stdio_server", "//codex-rs/rmcp-client:test_streamable_http_server", diff --git a/codex-rs/core/src/test_support.rs b/codex-rs/core/src/test_support.rs index 1db714fadaa8..1f946602f5b6 100644 --- a/codex-rs/core/src/test_support.rs +++ b/codex-rs/core/src/test_support.rs @@ -71,6 +71,13 @@ pub fn auth_manager_from_auth_with_home(auth: CodexAuth, codex_home: PathBuf) -> AuthManager::from_auth_for_testing_with_home(auth, codex_home) } +pub fn with_code_mode_host_program( + thread_manager: ThreadManager, + host_program: PathBuf, +) -> ThreadManager { + thread_manager.with_code_mode_host_program_for_tests(host_program) +} + pub fn thread_manager_with_models_provider( auth: CodexAuth, provider: ModelProviderInfo, diff --git a/codex-rs/core/src/thread_manager.rs b/codex-rs/core/src/thread_manager.rs index 4ea86cb33d00..669da4954775 100644 --- a/codex-rs/core/src/thread_manager.rs +++ b/codex-rs/core/src/thread_manager.rs @@ -364,6 +364,16 @@ impl ThreadManager { } } + pub(crate) fn with_code_mode_host_program_for_tests(mut self, host_program: PathBuf) -> Self { + let Some(state) = Arc::get_mut(&mut self.state) else { + unreachable!("new thread manager state should not be shared"); + }; + state.code_mode_session_provider = Arc::new( + ProcessOwnedCodeModeSessionProvider::with_host_program(host_program), + ); + self + } + /// Construct with a dummy AuthManager containing the provided CodexAuth. /// Used for integration tests: should not be used by ordinary business logic. pub(crate) fn with_models_provider_for_tests( diff --git a/codex-rs/core/tests/common/test_codex.rs b/codex-rs/core/tests/common/test_codex.rs index 8e565ff34670..62624d9e3ca0 100644 --- a/codex-rs/core/tests/common/test_codex.rs +++ b/codex-rs/core/tests/common/test_codex.rs @@ -290,6 +290,7 @@ pub struct TestCodexBuilder { user_instructions_provider: Option>, supports_openai_form_elicitation: bool, external_time_provider: Option>, + code_mode_host_program: Option, } impl TestCodexBuilder { @@ -396,6 +397,11 @@ impl TestCodexBuilder { self } + pub fn with_code_mode_host_program(mut self, host_program: PathBuf) -> Self { + self.code_mode_host_program = Some(host_program); + self + } + pub fn with_windows_cmd_shell(self) -> Self { if cfg!(windows) { self.with_user_shell(get_shell_by_model_provided_path(&PathBuf::from("cmd.exe"))) @@ -613,6 +619,20 @@ impl TestCodexBuilder { /*attestation_provider*/ None, /*external_time_provider*/ self.external_time_provider.clone(), ); + let code_mode_host_program = self + .code_mode_host_program + .take() + .or_else(|| codex_utils_cargo_bin::cargo_bin("codex-code-mode-host").ok()); + let thread_manager = if config.features.enabled(Feature::CodeModeHost) + && let Some(code_mode_host_program) = code_mode_host_program + { + codex_core::test_support::with_code_mode_host_program( + thread_manager, + code_mode_host_program, + ) + } else { + thread_manager + }; let thread_manager = Arc::new(thread_manager); let user_shell_override = self.user_shell_override.clone(); @@ -708,12 +728,6 @@ impl TestCodexBuilder { } else { load_default_config_for_test(home).await }; - // Core tests run without an installed sibling code-mode host binary. Tests that exercise - // the process host opt in explicitly after this default test-harness override. - config - .features - .disable(Feature::CodeModeHost) - .expect("test config should allow disabling the code-mode host"); config.cwd = cwd_override; config.model_provider = model_provider; if let Ok(path) = codex_utils_cargo_bin::cargo_bin("codex") { @@ -1225,6 +1239,7 @@ pub fn test_codex() -> TestCodexBuilder { user_instructions_provider: None, supports_openai_form_elicitation: false, external_time_provider: None, + code_mode_host_program: None, } } diff --git a/codex-rs/core/tests/suite/code_mode.rs b/codex-rs/core/tests/suite/code_mode.rs index 9293b506efd4..8d56fae7d0a7 100644 --- a/codex-rs/core/tests/suite/code_mode.rs +++ b/codex-rs/core/tests/suite/code_mode.rs @@ -43,6 +43,7 @@ use core_test_support::skip_if_no_network; use core_test_support::skip_if_wine_exec; use core_test_support::stdio_server_bin; use core_test_support::test_codex::TestCodex; +use core_test_support::test_codex::TestCodexBuilder; use core_test_support::test_codex::test_codex; use core_test_support::test_codex::turn_permission_fields; use core_test_support::wait_for_event; @@ -190,10 +191,19 @@ async fn run_code_mode_turn_with_model_and_config( model: &'static str, configure: impl FnOnce(&mut Config) + Send + 'static, ) -> Result<(TestCodex, ResponseMock)> { - let mut builder = test_codex().with_model(model).with_config(move |config| { + let builder = test_codex().with_model(model).with_config(move |config| { let _ = config.features.enable(Feature::CodeMode); configure(config); }); + run_code_mode_turn_with_builder(server, prompt, code, builder).await +} + +async fn run_code_mode_turn_with_builder( + server: &MockServer, + prompt: &str, + code: &str, + mut builder: TestCodexBuilder, +) -> Result<(TestCodex, ResponseMock)> { let test = builder.build(server).await?; responses::mount_sse_once( @@ -224,14 +234,18 @@ async fn missing_process_host_returns_a_tool_error() -> Result<()> { skip_if_no_network!(Ok(())); let server = responses::start_mock_server().await; - let (_test, follow_up_mock) = - run_code_mode_turn_with_config(&server, "Run code mode", "text('unreachable')", |config| { + let builder = test_codex() + .with_model("test-gpt-5.1-codex") + .with_code_mode_host_program("codex-code-mode-host-does-not-exist".into()) + .with_config(|config| { config .features - .enable(Feature::CodeModeHost) - .expect("code mode host should be enabled"); - }) - .await?; + .enable(Feature::CodeMode) + .expect("code mode should be enabled"); + }); + let (_test, follow_up_mock) = + run_code_mode_turn_with_builder(&server, "Run code mode", "text('unreachable')", builder) + .await?; let output = follow_up_mock .single_request() From 6795df872c20df210959d58124be60ef8f5374fe Mon Sep 17 00:00:00 2001 From: Channing Conger Date: Tue, 7 Jul 2026 19:33:36 -0700 Subject: [PATCH 3/7] Fix code mode host test wiring --- codex-rs/app-server/BUILD.bazel | 1 + .../app-server/tests/common/test_app_server.rs | 15 +++++++++++++++ codex-rs/core/BUILD.bazel | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/codex-rs/app-server/BUILD.bazel b/codex-rs/app-server/BUILD.bazel index a8e7f502718c..e5ef8268e5d8 100644 --- a/codex-rs/app-server/BUILD.bazel +++ b/codex-rs/app-server/BUILD.bazel @@ -5,6 +5,7 @@ codex_rust_crate( crate_name = "codex_app_server", extra_binaries = [ "//codex-rs/bwrap:bwrap", + "//codex-rs/code-mode-host:codex-code-mode-host", ], extra_binaries_non_windows = [ "//codex-rs/cli:codex", diff --git a/codex-rs/app-server/tests/common/test_app_server.rs b/codex-rs/app-server/tests/common/test_app_server.rs index e080ab0261be..75c6337fa1d5 100644 --- a/codex-rs/app-server/tests/common/test_app_server.rs +++ b/codex-rs/app-server/tests/common/test_app_server.rs @@ -147,6 +147,7 @@ pub struct TestAppServer { pub const DEFAULT_CLIENT_NAME: &str = "codex-app-server-tests"; pub const DISABLE_PLUGIN_STARTUP_TASKS_ARG: &str = "--disable-plugin-startup-tasks-for-tests"; const DISABLE_MANAGED_CONFIG_ENV_VAR: &str = "CODEX_APP_SERVER_DISABLE_MANAGED_CONFIG"; +const CODE_MODE_HOST_PATH_ENV_VAR: &str = "CODEX_CODE_MODE_HOST_PATH"; impl TestAppServer { /// Starts building a server with a temporary CODEX_HOME and the standard @@ -1939,6 +1940,20 @@ impl TestAppServerBuilder { } TestAppServerEnvironment::None => None, }; + if !env_overrides + .iter() + .any(|(key, _)| key == CODE_MODE_HOST_PATH_ENV_VAR) + && let Ok(code_mode_host_program) = + codex_utils_cargo_bin::cargo_bin("codex-code-mode-host") + { + env_overrides.insert( + 0, + ( + CODE_MODE_HOST_PATH_ENV_VAR.to_string(), + Some(code_mode_host_program.to_string_lossy().into_owned()), + ), + ); + } let program = match program { Some(program) => program, None => codex_utils_cargo_bin::cargo_bin("codex-app-server") diff --git a/codex-rs/core/BUILD.bazel b/codex-rs/core/BUILD.bazel index f9307e8dc004..a3f0583b8023 100644 --- a/codex-rs/core/BUILD.bazel +++ b/codex-rs/core/BUILD.bazel @@ -14,7 +14,7 @@ codex_rust_crate( crate_name = "codex_core", extra_binaries = [ "//codex-rs/bwrap:bwrap", - "//codex-rs/code-mode-host:code-mode-host", + "//codex-rs/code-mode-host:codex-code-mode-host", "//codex-rs/linux-sandbox:codex-linux-sandbox", "//codex-rs/rmcp-client:test_stdio_server", "//codex-rs/rmcp-client:test_streamable_http_server", From dc96c1b697f9637e3bfbf5368a5810f84381302b Mon Sep 17 00:00:00 2001 From: Channing Conger Date: Wed, 8 Jul 2026 03:27:28 +0000 Subject: [PATCH 4/7] fix Windows runfile path propagation --- workspace_root_test_launcher.bat.tpl | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/workspace_root_test_launcher.bat.tpl b/workspace_root_test_launcher.bat.tpl index 3613b91d76c9..534b2f57c1b9 100644 --- a/workspace_root_test_launcher.bat.tpl +++ b/workspace_root_test_launcher.bat.tpl @@ -104,14 +104,24 @@ if defined TEST_WORKSPACE set "workspace_logical_path=%TEST_WORKSPACE%/%logical_ set "native_logical_path=%logical_path:/=\%" set "native_workspace_logical_path=%workspace_logical_path:/=\%" +rem Capture paths in FOR variables before ENDLOCAL. Delayed !variables! are +rem unavailable after ENDLOCAL restores the caller's expansion mode. for %%R in ("%RUNFILES_DIR%" "%TEST_SRCDIR%") do ( set "runfiles_root=%%~R" if defined runfiles_root ( if exist "!runfiles_root!\!native_logical_path!" ( - endlocal & set "%~1=!runfiles_root!\!native_logical_path!" & exit /b 0 + for %%P in ("!runfiles_root!\!native_logical_path!") do ( + endlocal + set "%~1=%%~P" + exit /b 0 + ) ) if exist "!runfiles_root!\!native_workspace_logical_path!" ( - endlocal & set "%~1=!runfiles_root!\!native_workspace_logical_path!" & exit /b 0 + for %%P in ("!runfiles_root!\!native_workspace_logical_path!") do ( + endlocal + set "%~1=%%~P" + exit /b 0 + ) ) ) ) @@ -128,13 +138,18 @@ if defined manifest if exist "%manifest%" ( rem Bazel tests even though the manifest file was present. for /f "usebackq tokens=1,* delims= " %%A in ("%manifest%") do ( if "%%A"=="%logical_path%" ( - endlocal & set "%~1=%%B" & exit /b 0 + endlocal + set "%~1=%%B" + exit /b 0 ) if "%%A"=="%workspace_logical_path%" ( - endlocal & set "%~1=%%B" & exit /b 0 + endlocal + set "%~1=%%B" + exit /b 0 ) ) ) >&2 echo failed to resolve runfile: %logical_path% -endlocal & exit /b 1 +endlocal +exit /b 1 From 9a65f765acb35d6664f862a28bd88f54593c378c Mon Sep 17 00:00:00 2001 From: Channing Conger Date: Wed, 8 Jul 2026 03:37:58 +0000 Subject: [PATCH 5/7] avoid scoped Windows runfile assignments --- workspace_root_test_launcher.bat.tpl | 81 +++++++++++++++------------- 1 file changed, 44 insertions(+), 37 deletions(-) diff --git a/workspace_root_test_launcher.bat.tpl b/workspace_root_test_launcher.bat.tpl index 534b2f57c1b9..dba4df3371c7 100644 --- a/workspace_root_test_launcher.bat.tpl +++ b/workspace_root_test_launcher.bat.tpl @@ -12,6 +12,11 @@ if errorlevel 1 exit /b 1 __RUNFILE_ENV_EXPORTS__ +if not defined test_bin ( + >&2 echo resolved test binary was lost while exporting runfile environment variables + exit /b 1 +) + __WORKSPACE_ROOT_SETUP__ set "TOTAL_SHARDS=%RULES_RUST_TEST_TOTAL_SHARDS%" @@ -97,59 +102,61 @@ rmdir /s /q "!TEMP_DIR!" 2>nul exit /b !TEST_EXIT! :resolve_runfile -setlocal EnableExtensions EnableDelayedExpansion -set "logical_path=%~2" -set "workspace_logical_path=%logical_path%" -if defined TEST_WORKSPACE set "workspace_logical_path=%TEST_WORKSPACE%/%logical_path%" -set "native_logical_path=%logical_path:/=\%" -set "native_workspace_logical_path=%workspace_logical_path:/=\%" - -rem Capture paths in FOR variables before ENDLOCAL. Delayed !variables! are -rem unavailable after ENDLOCAL restores the caller's expansion mode. +set "resolve_runfile_logical_path=%~2" +set "resolve_runfile_workspace_logical_path=!resolve_runfile_logical_path!" +if defined TEST_WORKSPACE set "resolve_runfile_workspace_logical_path=%TEST_WORKSPACE%/!resolve_runfile_logical_path!" +set "resolve_runfile_native_logical_path=!resolve_runfile_logical_path:/=\!" +set "resolve_runfile_native_workspace_logical_path=!resolve_runfile_workspace_logical_path:/=\!" + for %%R in ("%RUNFILES_DIR%" "%TEST_SRCDIR%") do ( - set "runfiles_root=%%~R" - if defined runfiles_root ( - if exist "!runfiles_root!\!native_logical_path!" ( - for %%P in ("!runfiles_root!\!native_logical_path!") do ( - endlocal - set "%~1=%%~P" - exit /b 0 - ) + set "resolve_runfile_root=%%~R" + if defined resolve_runfile_root ( + if exist "!resolve_runfile_root!\!resolve_runfile_native_logical_path!" ( + set "%~1=!resolve_runfile_root!\!resolve_runfile_native_logical_path!" + goto :resolve_runfile_success ) - if exist "!runfiles_root!\!native_workspace_logical_path!" ( - for %%P in ("!runfiles_root!\!native_workspace_logical_path!") do ( - endlocal - set "%~1=%%~P" - exit /b 0 - ) + if exist "!resolve_runfile_root!\!resolve_runfile_native_workspace_logical_path!" ( + set "%~1=!resolve_runfile_root!\!resolve_runfile_native_workspace_logical_path!" + goto :resolve_runfile_success ) ) ) -set "manifest=%RUNFILES_MANIFEST_FILE%" -if not defined manifest if exist "%~f0.runfiles_manifest" set "manifest=%~f0.runfiles_manifest" -if not defined manifest if exist "%~dpn0.runfiles_manifest" set "manifest=%~dpn0.runfiles_manifest" -if not defined manifest if exist "%~f0.exe.runfiles_manifest" set "manifest=%~f0.exe.runfiles_manifest" +set "resolve_runfile_manifest=%RUNFILES_MANIFEST_FILE%" +if not defined resolve_runfile_manifest if exist "%~f0.runfiles_manifest" set "resolve_runfile_manifest=%~f0.runfiles_manifest" +if not defined resolve_runfile_manifest if exist "%~dpn0.runfiles_manifest" set "resolve_runfile_manifest=%~dpn0.runfiles_manifest" +if not defined resolve_runfile_manifest if exist "%~f0.exe.runfiles_manifest" set "resolve_runfile_manifest=%~f0.exe.runfiles_manifest" -if defined manifest if exist "%manifest%" ( +if defined resolve_runfile_manifest if exist "!resolve_runfile_manifest!" ( rem Read the manifest directly instead of shelling out to findstr. In the rem GitHub Windows runner, the nested `findstr` path produced rem `FINDSTR: Cannot open D:MANIFEST`, which then broke runfile resolution for rem Bazel tests even though the manifest file was present. - for /f "usebackq tokens=1,* delims= " %%A in ("%manifest%") do ( - if "%%A"=="%logical_path%" ( - endlocal + for /f "usebackq tokens=1,* delims= " %%A in ("!resolve_runfile_manifest!") do ( + if "%%A"=="!resolve_runfile_logical_path!" ( set "%~1=%%B" - exit /b 0 + goto :resolve_runfile_success ) - if "%%A"=="%workspace_logical_path%" ( - endlocal + if "%%A"=="!resolve_runfile_workspace_logical_path!" ( set "%~1=%%B" - exit /b 0 + goto :resolve_runfile_success ) ) ) ->&2 echo failed to resolve runfile: %logical_path% -endlocal +>&2 echo failed to resolve runfile: !resolve_runfile_logical_path! +call :clear_resolve_runfile_state exit /b 1 + +:resolve_runfile_success +call :clear_resolve_runfile_state +exit /b 0 + +:clear_resolve_runfile_state +set "resolve_runfile_logical_path=" +set "resolve_runfile_workspace_logical_path=" +set "resolve_runfile_native_logical_path=" +set "resolve_runfile_native_workspace_logical_path=" +set "resolve_runfile_root=" +set "resolve_runfile_manifest=" +exit /b 0 From 84a9616d0e1ac8b9a88cc59c919c69ec7bc5d6ba Mon Sep 17 00:00:00 2001 From: Channing Conger Date: Wed, 8 Jul 2026 03:50:29 +0000 Subject: [PATCH 6/7] handle self-mapped Windows runfiles --- workspace_root_test_launcher.bat.tpl | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/workspace_root_test_launcher.bat.tpl b/workspace_root_test_launcher.bat.tpl index dba4df3371c7..de9299b0c2e6 100644 --- a/workspace_root_test_launcher.bat.tpl +++ b/workspace_root_test_launcher.bat.tpl @@ -132,13 +132,19 @@ if defined resolve_runfile_manifest if exist "!resolve_runfile_manifest!" ( rem GitHub Windows runner, the nested `findstr` path produced rem `FINDSTR: Cannot open D:MANIFEST`, which then broke runfile resolution for rem Bazel tests even though the manifest file was present. + rem A one-field manifest entry maps to itself, so fall back to %%A when the + rem optional mapped path in %%B is empty. for /f "usebackq tokens=1,* delims= " %%A in ("!resolve_runfile_manifest!") do ( if "%%A"=="!resolve_runfile_logical_path!" ( - set "%~1=%%B" + set "resolve_runfile_manifest_path=%%B" + if not defined resolve_runfile_manifest_path set "resolve_runfile_manifest_path=%%A" + set "%~1=!resolve_runfile_manifest_path!" goto :resolve_runfile_success ) if "%%A"=="!resolve_runfile_workspace_logical_path!" ( - set "%~1=%%B" + set "resolve_runfile_manifest_path=%%B" + if not defined resolve_runfile_manifest_path set "resolve_runfile_manifest_path=%%A" + set "%~1=!resolve_runfile_manifest_path!" goto :resolve_runfile_success ) ) @@ -159,4 +165,5 @@ set "resolve_runfile_native_logical_path=" set "resolve_runfile_native_workspace_logical_path=" set "resolve_runfile_root=" set "resolve_runfile_manifest=" +set "resolve_runfile_manifest_path=" exit /b 0 From 42bfd0a02d856228cb3509da59f1511eca738e00 Mon Sep 17 00:00:00 2001 From: Channing Conger Date: Wed, 8 Jul 2026 04:02:11 +0000 Subject: [PATCH 7/7] preserve resolved Windows runfile paths --- defs.bzl | 3 ++- workspace_root_test_launcher.bat.tpl | 22 +++++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/defs.bzl b/defs.bzl index 8532a223ebac..8eb70ed9e41a 100644 --- a/defs.bzl +++ b/defs.bzl @@ -110,8 +110,9 @@ def _windows_runfile_env_exports(ctx): lines = [] for runfile_dep, env_var in ctx.attr.runfile_env.items(): runfile = _runfile_env_file(runfile_dep) - lines.append('call :resolve_runfile {} "{}"'.format(env_var, _runfile_logical_path(runfile))) + lines.append('call :resolve_runfile "{}"'.format(_runfile_logical_path(runfile))) lines.append("if errorlevel 1 exit /b 1") + lines.append('set "{}=!resolve_runfile_result!"'.format(env_var)) return "\n".join(lines) def _runfile_env_file(target): diff --git a/workspace_root_test_launcher.bat.tpl b/workspace_root_test_launcher.bat.tpl index de9299b0c2e6..fa18c301dd22 100644 --- a/workspace_root_test_launcher.bat.tpl +++ b/workspace_root_test_launcher.bat.tpl @@ -1,14 +1,16 @@ @echo off setlocal EnableExtensions EnableDelayedExpansion -call :resolve_runfile workspace_root_marker "__WORKSPACE_ROOT_MARKER__" +call :resolve_runfile "__WORKSPACE_ROOT_MARKER__" if errorlevel 1 exit /b 1 +set "workspace_root_marker=!resolve_runfile_result!" for %%I in ("%workspace_root_marker%") do set "workspace_root_marker_dir=%%~dpI" for %%I in ("%workspace_root_marker_dir%..\..") do set "workspace_root=%%~fI" -call :resolve_runfile test_bin "__TEST_BIN__" +call :resolve_runfile "__TEST_BIN__" if errorlevel 1 exit /b 1 +set "test_bin=!resolve_runfile_result!" __RUNFILE_ENV_EXPORTS__ @@ -102,7 +104,8 @@ rmdir /s /q "!TEMP_DIR!" 2>nul exit /b !TEST_EXIT! :resolve_runfile -set "resolve_runfile_logical_path=%~2" +set "resolve_runfile_result=" +set "resolve_runfile_logical_path=%~1" set "resolve_runfile_workspace_logical_path=!resolve_runfile_logical_path!" if defined TEST_WORKSPACE set "resolve_runfile_workspace_logical_path=%TEST_WORKSPACE%/!resolve_runfile_logical_path!" set "resolve_runfile_native_logical_path=!resolve_runfile_logical_path:/=\!" @@ -112,11 +115,11 @@ for %%R in ("%RUNFILES_DIR%" "%TEST_SRCDIR%") do ( set "resolve_runfile_root=%%~R" if defined resolve_runfile_root ( if exist "!resolve_runfile_root!\!resolve_runfile_native_logical_path!" ( - set "%~1=!resolve_runfile_root!\!resolve_runfile_native_logical_path!" + set "resolve_runfile_result=!resolve_runfile_root!\!resolve_runfile_native_logical_path!" goto :resolve_runfile_success ) if exist "!resolve_runfile_root!\!resolve_runfile_native_workspace_logical_path!" ( - set "%~1=!resolve_runfile_root!\!resolve_runfile_native_workspace_logical_path!" + set "resolve_runfile_result=!resolve_runfile_root!\!resolve_runfile_native_workspace_logical_path!" goto :resolve_runfile_success ) ) @@ -138,13 +141,13 @@ if defined resolve_runfile_manifest if exist "!resolve_runfile_manifest!" ( if "%%A"=="!resolve_runfile_logical_path!" ( set "resolve_runfile_manifest_path=%%B" if not defined resolve_runfile_manifest_path set "resolve_runfile_manifest_path=%%A" - set "%~1=!resolve_runfile_manifest_path!" + set "resolve_runfile_result=!resolve_runfile_manifest_path!" goto :resolve_runfile_success ) if "%%A"=="!resolve_runfile_workspace_logical_path!" ( set "resolve_runfile_manifest_path=%%B" if not defined resolve_runfile_manifest_path set "resolve_runfile_manifest_path=%%A" - set "%~1=!resolve_runfile_manifest_path!" + set "resolve_runfile_result=!resolve_runfile_manifest_path!" goto :resolve_runfile_success ) ) @@ -155,6 +158,11 @@ call :clear_resolve_runfile_state exit /b 1 :resolve_runfile_success +if not defined resolve_runfile_result ( + >&2 echo resolved runfile has an empty path: !resolve_runfile_logical_path! + call :clear_resolve_runfile_state + exit /b 1 +) call :clear_resolve_runfile_state exit /b 0