Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 32 additions & 24 deletions src-tauri/src/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,24 +70,19 @@ pub fn resolve_conflict_marker_style(db: &std::sync::Mutex<crate::db::Database>)
resolve_conflict_marker_style_from_db(&db.lock_or_recover())
}

/// File name of the app database inside the app data dir.
pub const APP_DB_FILE_NAME: &str = "treq.db";

/// The app database inside the app data dir, falling back to `<repo>/.treq/treq.db`.
pub fn resolve_app_db_path(repo_path: &str) -> PathBuf {
resolve_app_db_path_with(repo_path, |key| std::env::var(key).ok())
}

/// `resolve_app_db_path` reading env vars through `env`, so tests need not mutate the process env.
fn resolve_app_db_path_with(repo_path: &str, env: impl Fn(&str) -> Option<String>) -> PathBuf {
if let Some(explicit_db_path) = env("TREQ_APP_DB_PATH") {
let trimmed = explicit_db_path.trim();
if !trimmed.is_empty() {
return PathBuf::from(trimmed);
}
}

if let Some(app_data_dir) = app_data_dir_with(env) {
return app_data_dir.join("treq.db");
}

Path::new(repo_path).join(".treq").join("treq.db")
app_data_dir_with(env)
.unwrap_or_else(|| Path::new(repo_path).join(".treq"))
.join(APP_DB_FILE_NAME)
}

#[cfg(test)]
Expand All @@ -97,6 +92,25 @@ thread_local! {
const { std::cell::RefCell::new(None) };
}

/// Points this test thread's app data dir at `dir` until dropped.
#[cfg(test)]
pub(crate) struct AppDataDirGuard;

#[cfg(test)]
impl AppDataDirGuard {
pub(crate) fn set(dir: &Path) -> Self {
TEST_APP_DATA_DIR.with(|d| *d.borrow_mut() = Some(dir.to_path_buf()));
Self
}
}

#[cfg(test)]
impl Drop for AppDataDirGuard {
fn drop(&mut self) {
TEST_APP_DATA_DIR.with(|d| *d.borrow_mut() = None);
}
}

/// The app data dir from `TREQ_APP_DATA_DIR`, or a test's per-thread override.
pub(crate) fn app_data_dir() -> Option<PathBuf> {
app_data_dir_with(|key| std::env::var(key).ok())
Expand All @@ -119,22 +133,16 @@ mod tests {
use std::path::Path;

#[test]
fn resolve_app_db_path_prefers_explicit_db_path() {
let env = |key: &str| match key {
"TREQ_APP_DB_PATH" => Some("/tmp/explicit-treq.db".to_string()),
"TREQ_APP_DATA_DIR" => Some("/tmp/ignored-dir".to_string()),
_ => None,
};
fn resolve_app_db_path_uses_app_data_dir() {
let env = |key: &str| (key == "TREQ_APP_DATA_DIR").then(|| "/tmp/app-data".to_string());

let resolved = resolve_app_db_path_with("/repo/path", env);
assert_eq!(resolved.to_string_lossy(), "/tmp/explicit-treq.db");
assert_eq!(resolved, Path::new("/tmp/app-data").join("treq.db"));
}

#[test]
fn resolve_app_db_path_falls_back_to_app_data_dir() {
let env = |key: &str| (key == "TREQ_APP_DATA_DIR").then(|| "/tmp/app-data".to_string());

let resolved = resolve_app_db_path_with("/repo/path", env);
assert_eq!(resolved, Path::new("/tmp/app-data").join("treq.db"));
fn resolve_app_db_path_falls_back_to_repo_dir() {
let resolved = resolve_app_db_path_with("/repo/path", |_| None);
assert_eq!(resolved, Path::new("/repo/path/.treq/treq.db"));
}
}
17 changes: 1 addition & 16 deletions src-tauri/src/core/skills.rs
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,7 @@ pub fn persist_app_index_setting(db: &crate::db::Database) -> Result<(), String>
#[cfg(test)]
mod tests {
use super::*;
use crate::core::AppDataDirGuard;
use tempfile::TempDir;

fn sample_files() -> Vec<(String, Vec<u8>)> {
Expand Down Expand Up @@ -548,22 +549,6 @@ mod tests {
}
}

/// Points this test thread's app data dir at `dir` until dropped.
struct AppDataDirGuard;

impl AppDataDirGuard {
fn set(dir: &Path) -> Self {
crate::core::TEST_APP_DATA_DIR.with(|d| *d.borrow_mut() = Some(dir.to_path_buf()));
Self
}
}

impl Drop for AppDataDirGuard {
fn drop(&mut self) {
crate::core::TEST_APP_DATA_DIR.with(|d| *d.borrow_mut() = None);
}
}

#[test]
fn skill_checksum_is_stable_for_path_order() {
let a = sample_files();
Expand Down
10 changes: 1 addition & 9 deletions src-tauri/src/core/workspaces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1593,14 +1593,8 @@ mod tests {
use rusqlite::Connection;
use std::fs;
use std::process::Command;
use std::sync::{Mutex, OnceLock};
use tempfile::TempDir;

fn env_lock() -> &'static Mutex<()> {
static LOCK: OnceLock<Mutex<()>> = OnceLock::new();
LOCK.get_or_init(|| Mutex::new(()))
}

fn test_workspace(id: i64, branch: &str, target: Option<&str>) -> Workspace {
Workspace {
id,
Expand Down Expand Up @@ -2383,17 +2377,15 @@ mod tests {

#[test]
fn resolve_workspace_diff_conflict_marker_style_defaults_when_settings_table_missing() {
let _guard = env_lock().lock().unwrap();
let temp_dir = TempDir::new().expect("temp dir should be created");
let db_path = temp_dir.path().join("treq.db");
Connection::open(&db_path)
.expect("db should be openable")
.execute("CREATE TABLE unrelated (id INTEGER PRIMARY KEY)", [])
.expect("setup table should succeed");

std::env::set_var("TREQ_APP_DB_PATH", db_path.to_string_lossy().to_string());
let _app_data_dir = crate::core::AppDataDirGuard::set(temp_dir.path());
let style = resolve_workspace_diff_conflict_marker_style("/unused/repo/path");
std::env::remove_var("TREQ_APP_DB_PATH");

assert_eq!(
style.expect("should resolve style"),
Expand Down
3 changes: 1 addition & 2 deletions src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,8 +356,7 @@ pub fn run() {
.expect("Failed to get app data dir");
std::fs::create_dir_all(&app_dir).expect("Failed to create app data directory");
std::env::set_var("TREQ_APP_DATA_DIR", app_dir.to_string_lossy().to_string());
let db_path = app_dir.join("treq.db");
std::env::set_var("TREQ_APP_DB_PATH", db_path.to_string_lossy().to_string());
let db_path = app_dir.join(crate::core::APP_DB_FILE_NAME);

let db = Database::new(db_path).expect("Failed to open database");
db.init().expect("Failed to initialize database");
Expand Down
21 changes: 9 additions & 12 deletions src-tauri/src/tauri_test_bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

use napi_derive::napi;
use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::Mutex;

use crate::binary_paths;
Expand All @@ -20,17 +19,15 @@ use crate::AppState;
use crate::e2e_test_helpers::TestRepo;

pub fn init_test_state() -> Result<AppState, String> {
let db_path = std::env::var("TREQ_APP_DB_PATH")
.map(PathBuf::from)
.unwrap_or_else(|_| {
std::env::temp_dir().join(format!("treq-tauri-test-{}.db", std::process::id()))
});

if let Some(parent) = db_path.parent() {
std::env::set_var("TREQ_APP_DATA_DIR", parent.to_string_lossy().to_string());
std::fs::create_dir_all(parent).map_err(|e| e.to_string())?;
}
std::env::set_var("TREQ_APP_DB_PATH", db_path.to_string_lossy().to_string());
let app_data_dir = crate::core::app_data_dir().unwrap_or_else(|| {
std::env::temp_dir().join(format!("treq-tauri-test-{}", std::process::id()))
});
std::fs::create_dir_all(&app_data_dir).map_err(|e| e.to_string())?;
std::env::set_var(
"TREQ_APP_DATA_DIR",
app_data_dir.to_string_lossy().to_string(),
);
let db_path = app_data_dir.join(crate::core::APP_DB_FILE_NAME);

let db = Database::new(db_path).map_err(|e| format!("Failed to open database: {e}"))?;
db.init()
Expand Down
8 changes: 4 additions & 4 deletions src-tauri/src/tracker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -475,12 +475,12 @@ fn kickoff_background_loop(inner: Arc<KickoffPollerInner>) {
}
}

/// Opens the app database from `TREQ_APP_DB_PATH` for poller threads, which
/// Opens the app database in `TREQ_APP_DATA_DIR` for poller threads, which
/// run outside Tauri's managed state.
pub fn open_app_db() -> Result<crate::db::Database, String> {
let db_path =
std::env::var("TREQ_APP_DB_PATH").map_err(|_| "TREQ_APP_DB_PATH not set".to_string())?;
crate::db::Database::new(std::path::PathBuf::from(db_path))
let app_data_dir =
crate::core::app_data_dir().ok_or_else(|| "TREQ_APP_DATA_DIR is not set".to_string())?;
crate::db::Database::new(app_data_dir.join(crate::core::APP_DB_FILE_NAME))
.map_err(|e| format!("Failed to open database: {e}"))
}

Expand Down
10 changes: 5 additions & 5 deletions test/setup.integration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ process.env.TREQ_DISABLE_AUTO_REBASE = "1";
// Skip startup auto-update curl checks (spawn_blocking contention under CI).
process.env.TREQ_DISABLE_AUTO_UPDATE = "1";

const testDbPath = path.join(
// One app data dir (and so one app treq.db) per worker process.
const testAppDataDir = path.join(
os.tmpdir(),
`treq-integration-${process.pid}-${randomUUID()}.db`,
`treq-integration-${process.pid}-${randomUUID()}`,
);
process.env.TREQ_APP_DB_PATH = testDbPath;
process.env.TREQ_APP_DATA_DIR = path.dirname(testDbPath);
process.env.TREQ_APP_DATA_DIR = testAppDataDir;

const require = createRequire(import.meta.url);
const tauriTest = require("../src-tauri/target") as {
Expand Down Expand Up @@ -128,7 +128,7 @@ afterEach(() => {

afterAll(() => {
try {
if (fs.existsSync(testDbPath)) fs.unlinkSync(testDbPath);
fs.rmSync(testAppDataDir, { recursive: true, force: true });
} catch {
// ignore
}
Expand Down
7 changes: 3 additions & 4 deletions test/setup.screenshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,8 @@ import {
process.env.TREQ_DISABLE_AUTO_REBASE = "1";
process.env.TREQ_DISABLE_AUTO_UPDATE = "1";

const testDbPath = path.join(os.tmpdir(), `treq-screenshot-${Date.now()}.db`);
process.env.TREQ_APP_DB_PATH = testDbPath;
process.env.TREQ_APP_DATA_DIR = path.dirname(testDbPath);
const testAppDataDir = path.join(os.tmpdir(), `treq-screenshot-${Date.now()}`);
process.env.TREQ_APP_DATA_DIR = testAppDataDir;

const require = createRequire(import.meta.url);
const tauriTest = require("../src-tauri/target") as {
Expand Down Expand Up @@ -67,7 +66,7 @@ afterEach(() => {

afterAll(() => {
try {
if (fs.existsSync(testDbPath)) fs.unlinkSync(testDbPath);
fs.rmSync(testAppDataDir, { recursive: true, force: true });
} catch {
// ignore
}
Expand Down
2 changes: 1 addition & 1 deletion vitest.integration.base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const integrationBaseTest: ViteUserConfig["test"] = {
setupFiles: ["./test/setup.integration.ts"],
globals: true,
// Per-repo `local.db` lives under each `createTestRepo` temp dir. The
// app-level DB (`TREQ_APP_DB_PATH` / napi `OnceLock`) is process-global,
// app-level DB (`TREQ_APP_DATA_DIR` / napi `OnceLock`) is process-global,
// so every project still needs one process per file ("forks", not
// "threads") -- otherwise files sharing a worker process would share an
// app.db.
Expand Down
Loading