mirror of
https://github.com/openai/codex.git
synced 2026-10-23 18:08:45 +00:00
runtime: detect Codex package layout
This commit is contained in:
+62
-15
@@ -39,7 +39,9 @@ use codex_core::config::ConfigBuilder;
|
||||
use codex_core::config::ConfigOverrides;
|
||||
use codex_core::config::find_codex_home;
|
||||
use codex_features::FEATURES;
|
||||
use codex_install_context::CodexPackageLayout;
|
||||
use codex_install_context::InstallContext;
|
||||
use codex_install_context::InstallMethod;
|
||||
use codex_install_context::StandalonePlatform;
|
||||
use codex_login::AuthDotJson;
|
||||
use codex_login::AuthManager;
|
||||
@@ -812,7 +814,10 @@ fn installation_check(show_details: bool) -> DoctorCheck {
|
||||
|
||||
fn doctor_install_context(current_exe: Option<&Path>) -> InstallContext {
|
||||
if inherited_managed_env_for_cargo_binary(current_exe) {
|
||||
InstallContext::Other
|
||||
InstallContext {
|
||||
method: InstallMethod::Other,
|
||||
package_layout: None,
|
||||
}
|
||||
} else {
|
||||
InstallContext::current().clone()
|
||||
}
|
||||
@@ -843,8 +848,8 @@ fn inherited_managed_env_for_cargo_binary(current_exe: Option<&Path>) -> bool {
|
||||
}
|
||||
|
||||
fn describe_install_context(context: &InstallContext) -> String {
|
||||
match context {
|
||||
InstallContext::Standalone {
|
||||
match &context.method {
|
||||
InstallMethod::Standalone {
|
||||
release_dir,
|
||||
resources_dir,
|
||||
platform,
|
||||
@@ -853,22 +858,63 @@ fn describe_install_context(context: &InstallContext) -> String {
|
||||
StandalonePlatform::Unix => "unix",
|
||||
StandalonePlatform::Windows => "windows",
|
||||
};
|
||||
let resources = resources_dir
|
||||
.as_ref()
|
||||
.map(|path| path.display().to_string())
|
||||
.unwrap_or_else(|| "none".to_string());
|
||||
match &context.package_layout {
|
||||
Some(package_layout) => {
|
||||
let resources = display_optional_path(package_layout.resources_dir.as_deref());
|
||||
let path = display_optional_path(package_layout.path_dir.as_deref());
|
||||
format!(
|
||||
"standalone ({platform}, package {}, bin {}, resources {resources}, path {path})",
|
||||
package_layout.package_dir.display(),
|
||||
package_layout.bin_dir.display()
|
||||
)
|
||||
}
|
||||
None => {
|
||||
let resources = display_optional_path(resources_dir.as_deref());
|
||||
format!(
|
||||
"standalone ({platform}, release {}, resources {resources})",
|
||||
release_dir.display()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
InstallMethod::Npm => {
|
||||
describe_method_with_package_layout("npm", context.package_layout.as_ref())
|
||||
}
|
||||
InstallMethod::Bun => {
|
||||
describe_method_with_package_layout("bun", context.package_layout.as_ref())
|
||||
}
|
||||
InstallMethod::Brew => {
|
||||
describe_method_with_package_layout("brew", context.package_layout.as_ref())
|
||||
}
|
||||
InstallMethod::Other => {
|
||||
describe_method_with_package_layout("other", context.package_layout.as_ref())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn describe_method_with_package_layout(
|
||||
method: &str,
|
||||
package_layout: Option<&CodexPackageLayout>,
|
||||
) -> String {
|
||||
match package_layout {
|
||||
Some(package_layout) => {
|
||||
let resources = display_optional_path(package_layout.resources_dir.as_deref());
|
||||
let path = display_optional_path(package_layout.path_dir.as_deref());
|
||||
format!(
|
||||
"standalone ({platform}, release {}, resources {resources})",
|
||||
release_dir.display()
|
||||
"{method} (package {}, bin {}, resources {resources}, path {path})",
|
||||
package_layout.package_dir.display(),
|
||||
package_layout.bin_dir.display()
|
||||
)
|
||||
}
|
||||
InstallContext::Npm => "npm".to_string(),
|
||||
InstallContext::Bun => "bun".to_string(),
|
||||
InstallContext::Brew => "brew".to_string(),
|
||||
InstallContext::Other => "other".to_string(),
|
||||
None => method.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn display_optional_path(path: Option<&Path>) -> String {
|
||||
path.map(|path| path.display().to_string())
|
||||
.unwrap_or_else(|| "none".to_string())
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
enum NpmRootCheck {
|
||||
Match {
|
||||
@@ -2791,13 +2837,14 @@ fn path_readiness(details: &mut Vec<String>, label: &str, path: &Path) {
|
||||
}
|
||||
|
||||
fn standalone_release_cache_details(details: &mut Vec<String>) {
|
||||
let InstallContext::Standalone { release_dir, .. } = InstallContext::current() else {
|
||||
let context = InstallContext::current();
|
||||
let InstallMethod::Standalone { release_dir, .. } = &context.method else {
|
||||
return;
|
||||
};
|
||||
let Some(releases_dir) = release_dir.parent() else {
|
||||
return;
|
||||
};
|
||||
let Ok(entries) = std::fs::read_dir(releases_dir) else {
|
||||
let Ok(entries) = std::fs::read_dir(&releases_dir) else {
|
||||
return;
|
||||
};
|
||||
let release_count = entries.filter_map(Result::ok).count();
|
||||
|
||||
@@ -3,12 +3,13 @@
|
||||
//! Runtime diagnostics answer provenance questions that are hard to infer from
|
||||
//! user reports: which binary is running, which install channel it resembles,
|
||||
//! which platform it targets, and whether the search command comes from bundled
|
||||
//! standalone resources or from PATH.
|
||||
//! package files or from PATH.
|
||||
|
||||
use std::env;
|
||||
use std::process::Command;
|
||||
|
||||
use codex_install_context::InstallContext;
|
||||
use codex_install_context::InstallMethod;
|
||||
|
||||
use super::CheckStatus;
|
||||
use super::DoctorCheck;
|
||||
@@ -49,9 +50,10 @@ pub(super) fn runtime_check() -> DoctorCheck {
|
||||
|
||||
/// Verifies that the search command selected by the install context is usable.
|
||||
///
|
||||
/// Standalone installs should point at a bundled ripgrep binary, while local or
|
||||
/// package-managed installs usually resolve rg from PATH. A warning here means
|
||||
/// features that depend on file search may degrade even when the CLI launches.
|
||||
/// Package-layout installs should point at a bundled ripgrep binary, while local
|
||||
/// installs without that layout usually resolve rg from PATH. A warning here
|
||||
/// means features that depend on file search may degrade even when the CLI
|
||||
/// launches.
|
||||
pub(super) fn search_check() -> DoctorCheck {
|
||||
let current_exe = env::current_exe().ok();
|
||||
let install_context = doctor_install_context(current_exe.as_deref());
|
||||
@@ -109,28 +111,40 @@ pub(super) fn search_check() -> DoctorCheck {
|
||||
};
|
||||
let mut check = DoctorCheck::new("runtime.search", "search", status, summary).details(details);
|
||||
if status != CheckStatus::Ok {
|
||||
check = check.remediation("Install ripgrep or repair the bundled standalone resources.");
|
||||
check = check.remediation("Install ripgrep or repair the bundled Codex package.");
|
||||
}
|
||||
check
|
||||
}
|
||||
|
||||
fn install_method_name(context: &InstallContext) -> &'static str {
|
||||
match context {
|
||||
InstallContext::Standalone { .. } => "standalone",
|
||||
InstallContext::Npm => "npm",
|
||||
InstallContext::Bun => "bun",
|
||||
InstallContext::Brew => "brew",
|
||||
InstallContext::Other => "local build",
|
||||
match &context.method {
|
||||
InstallMethod::Standalone { .. } => "standalone",
|
||||
InstallMethod::Npm => "npm",
|
||||
InstallMethod::Bun => "bun",
|
||||
InstallMethod::Brew => "brew",
|
||||
InstallMethod::Other => "local build",
|
||||
}
|
||||
}
|
||||
|
||||
fn search_provider(context: &InstallContext) -> &'static str {
|
||||
match context {
|
||||
InstallContext::Standalone {
|
||||
let rg_command = context.rg_command();
|
||||
let from_package_layout = context
|
||||
.package_layout
|
||||
.as_ref()
|
||||
.and_then(|package_layout| package_layout.path_dir.as_ref())
|
||||
.is_some_and(|path_dir| rg_command.starts_with(path_dir));
|
||||
let from_legacy_standalone = matches!(
|
||||
&context.method,
|
||||
InstallMethod::Standalone {
|
||||
resources_dir: Some(resources_dir),
|
||||
..
|
||||
} if context.rg_command().starts_with(resources_dir) => "bundled",
|
||||
_ => "system",
|
||||
} if rg_command.starts_with(resources_dir)
|
||||
);
|
||||
|
||||
if from_package_layout || from_legacy_standalone {
|
||||
"bundled"
|
||||
} else {
|
||||
"system"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ use std::path::Path;
|
||||
|
||||
use codex_core::config::Config;
|
||||
use codex_install_context::InstallContext;
|
||||
use codex_install_context::InstallMethod;
|
||||
use serde::Deserialize;
|
||||
|
||||
use super::CheckStatus;
|
||||
@@ -129,22 +130,22 @@ fn push_cached_version_details(details: &mut Vec<String>, version_file: &Path) {
|
||||
}
|
||||
|
||||
fn update_action_label(context: &InstallContext) -> &'static str {
|
||||
match context {
|
||||
InstallContext::Npm => "npm install -g @openai/codex",
|
||||
InstallContext::Bun => "bun install -g @openai/codex",
|
||||
InstallContext::Brew => "brew upgrade --cask codex",
|
||||
InstallContext::Standalone { .. } => "standalone installer",
|
||||
InstallContext::Other => "manual or unknown",
|
||||
match &context.method {
|
||||
InstallMethod::Npm => "npm install -g @openai/codex",
|
||||
InstallMethod::Bun => "bun install -g @openai/codex",
|
||||
InstallMethod::Brew => "brew upgrade --cask codex",
|
||||
InstallMethod::Standalone { .. } => "standalone installer",
|
||||
InstallMethod::Other => "manual or unknown",
|
||||
}
|
||||
}
|
||||
|
||||
fn fetch_latest_version(context: &InstallContext) -> Result<String, String> {
|
||||
match context {
|
||||
InstallContext::Brew => fetch_homebrew_cask_version(),
|
||||
InstallContext::Npm
|
||||
| InstallContext::Bun
|
||||
| InstallContext::Standalone { .. }
|
||||
| InstallContext::Other => fetch_latest_github_release_version(),
|
||||
match &context.method {
|
||||
InstallMethod::Brew => fetch_homebrew_cask_version(),
|
||||
InstallMethod::Npm
|
||||
| InstallMethod::Bun
|
||||
| InstallMethod::Standalone { .. }
|
||||
| InstallMethod::Other => fetch_latest_github_release_version(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,11 +217,17 @@ mod tests {
|
||||
#[test]
|
||||
fn update_action_labels_install_contexts() {
|
||||
assert_eq!(
|
||||
update_action_label(&InstallContext::Npm),
|
||||
update_action_label(&InstallContext {
|
||||
method: InstallMethod::Npm,
|
||||
package_layout: None,
|
||||
}),
|
||||
"npm install -g @openai/codex"
|
||||
);
|
||||
assert_eq!(
|
||||
update_action_label(&InstallContext::Other),
|
||||
update_action_label(&InstallContext {
|
||||
method: InstallMethod::Other,
|
||||
package_layout: None,
|
||||
}),
|
||||
"manual or unknown"
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user