mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-24 12:44:18 +08:00
fix(codex): probe CODEX_SQLITE_HOME when locating state DB for history migration
The session-history migration only scanned ~/.codex/state_5.sqlite and the config.toml `sqlite_home` location. When Codex's SQLite state is relocated via the CODEX_SQLITE_HOME env var, the state DB was never scanned and its threads kept their old provider bucket. Add a CODEX_SQLITE_HOME fallback (config `sqlite_home` still takes precedence) in the shared codex_state_db_paths helper used by both the third-party and unified-session history migrations, plus serial env tests.
This commit is contained in:
@@ -1116,16 +1116,23 @@ fn migrate_codex_state_dbs(
|
||||
}
|
||||
|
||||
fn codex_state_db_paths(codex_dir: &Path, config_text: &str) -> Vec<PathBuf> {
|
||||
let mut paths = vec![codex_dir.join(CODEX_STATE_DB_FILENAME)];
|
||||
let mut paths = Vec::new();
|
||||
push_unique_path(&mut paths, codex_dir.join(CODEX_STATE_DB_FILENAME));
|
||||
// Codex lets SQLite state move away from CODEX_HOME; config takes precedence.
|
||||
if let Some(sqlite_home) = sqlite_home_from_codex_config(config_text) {
|
||||
let db_path = sqlite_home.join(CODEX_STATE_DB_FILENAME);
|
||||
if !paths.contains(&db_path) {
|
||||
paths.push(db_path);
|
||||
}
|
||||
push_unique_path(&mut paths, sqlite_home.join(CODEX_STATE_DB_FILENAME));
|
||||
} else if let Some(sqlite_home) = sqlite_home_from_env() {
|
||||
push_unique_path(&mut paths, sqlite_home.join(CODEX_STATE_DB_FILENAME));
|
||||
}
|
||||
paths
|
||||
}
|
||||
|
||||
fn push_unique_path(paths: &mut Vec<PathBuf>, path: PathBuf) {
|
||||
if !paths.contains(&path) {
|
||||
paths.push(path);
|
||||
}
|
||||
}
|
||||
|
||||
fn sqlite_home_from_codex_config(config_text: &str) -> Option<PathBuf> {
|
||||
let doc = config_text.parse::<DocumentMut>().ok()?;
|
||||
let raw = doc.get("sqlite_home")?.as_str()?.trim();
|
||||
@@ -1135,6 +1142,15 @@ fn sqlite_home_from_codex_config(config_text: &str) -> Option<PathBuf> {
|
||||
Some(resolve_user_path(raw))
|
||||
}
|
||||
|
||||
fn sqlite_home_from_env() -> Option<PathBuf> {
|
||||
let raw = std::env::var("CODEX_SQLITE_HOME").ok()?;
|
||||
let raw = raw.trim();
|
||||
if raw.is_empty() {
|
||||
return None;
|
||||
}
|
||||
Some(resolve_user_path(raw))
|
||||
}
|
||||
|
||||
fn resolve_user_path(raw: &str) -> PathBuf {
|
||||
if raw == "~" {
|
||||
return crate::config::get_home_dir();
|
||||
@@ -1313,8 +1329,33 @@ fn relative_backup_path(path: &Path, root: &Path) -> PathBuf {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::provider::Provider;
|
||||
use serial_test::serial;
|
||||
use std::ffi::OsString;
|
||||
use tempfile::tempdir;
|
||||
|
||||
struct EnvVarGuard {
|
||||
key: &'static str,
|
||||
previous: Option<OsString>,
|
||||
}
|
||||
|
||||
impl EnvVarGuard {
|
||||
fn set(key: &'static str, value: &Path) -> Self {
|
||||
let previous = std::env::var_os(key);
|
||||
std::env::set_var(key, value);
|
||||
Self { key, previous }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for EnvVarGuard {
|
||||
fn drop(&mut self) {
|
||||
if let Some(previous) = &self.previous {
|
||||
std::env::set_var(self.key, previous);
|
||||
} else {
|
||||
std::env::remove_var(self.key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn source_ids(values: &[&str]) -> BTreeSet<String> {
|
||||
values.iter().map(|value| value.to_string()).collect()
|
||||
}
|
||||
@@ -2116,6 +2157,46 @@ base_url = "https://proxy.example/v1"
|
||||
assert_eq!(backed_up_source_count, 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn state_db_paths_include_codex_sqlite_home_env() {
|
||||
let dir = tempdir().expect("tempdir");
|
||||
let codex_dir = dir.path().join(".codex");
|
||||
let sqlite_home = dir.path().join("sqlite-home");
|
||||
let _guard = EnvVarGuard::set("CODEX_SQLITE_HOME", &sqlite_home);
|
||||
|
||||
let paths = codex_state_db_paths(&codex_dir, "");
|
||||
|
||||
assert_eq!(
|
||||
paths,
|
||||
vec![
|
||||
codex_dir.join(CODEX_STATE_DB_FILENAME),
|
||||
sqlite_home.join(CODEX_STATE_DB_FILENAME),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn config_sqlite_home_takes_precedence_over_codex_sqlite_home_env() {
|
||||
let dir = tempdir().expect("tempdir");
|
||||
let codex_dir = dir.path().join(".codex");
|
||||
let env_sqlite_home = dir.path().join("env-sqlite-home");
|
||||
let config_sqlite_home = dir.path().join("config-sqlite-home");
|
||||
let _guard = EnvVarGuard::set("CODEX_SQLITE_HOME", &env_sqlite_home);
|
||||
let config_text = format!("sqlite_home = \"{}\"\n", config_sqlite_home.display());
|
||||
|
||||
let paths = codex_state_db_paths(&codex_dir, &config_text);
|
||||
|
||||
assert_eq!(
|
||||
paths,
|
||||
vec![
|
||||
codex_dir.join(CODEX_STATE_DB_FILENAME),
|
||||
config_sqlite_home.join(CODEX_STATE_DB_FILENAME),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn collects_third_party_provider_ids_from_codex_providers() {
|
||||
let db = Database::memory().expect("memory db");
|
||||
|
||||
Reference in New Issue
Block a user