Skip to content
Open
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
28 changes: 28 additions & 0 deletions src/app/session.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::fs;
use std::path::{Path, PathBuf};
use std::time::{Duration, SystemTime, UNIX_EPOCH};

Expand All @@ -19,6 +20,7 @@ pub const DEFAULT_WORD_WRAP_ENABLED: bool = true;
pub const DEFAULT_ALWAYS_ON_TOP: bool = false;

const APP_DIR_NAME: &str = "Rivet";
const PORTABLE_DATA_DIR_NAME: &str = "data";
const SESSIONS_DIR_NAME: &str = "sessions";
const BACKUP_DIR_NAME: &str = "backup";
const SESSION_FILE_NAME: &str = "session.json";
Expand Down Expand Up @@ -198,7 +200,33 @@ pub fn decide_restore_source(input: &RestoreDecisionInput) -> RestoreSource {
}
}

/// Data directory next to the executable, used when that location is
/// writable (i.e. running as a portable build, not installed under a
/// protected directory like Program Files). Returns `None` if the exe path
/// can't be resolved or the directory isn't writable, in which case the
/// caller falls back to the per-user AppData location.
fn portable_data_dir() -> Option<PathBuf> {
if cfg!(test) {
// Tests exercise data_dir() via LOCALAPPDATA/APPDATA env overrides;
// the test binary's own directory is writable, which would
// short-circuit those overrides and scribble into target/.
return None;
}
let exe = std::env::current_exe().ok()?;
let exe_dir = exe.parent()?;
let candidate = exe_dir.join(PORTABLE_DATA_DIR_NAME);
fs::create_dir_all(&candidate).ok()?;
let probe = candidate.join(".write_test");
fs::write(&probe, b"").ok()?;
let _ = fs::remove_file(&probe);
Some(candidate)
}

pub fn data_dir() -> Result<PathBuf> {
if let Some(portable) = portable_data_dir() {
return Ok(portable);
}

if let Ok(local) = std::env::var("LOCALAPPDATA")
&& !local.is_empty()
{
Expand Down
27 changes: 3 additions & 24 deletions src/logging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ use std::path::{Path, PathBuf};
use std::sync::{Mutex, OnceLock};
use std::time::{SystemTime, UNIX_EPOCH};

use windows::Win32::Foundation::HANDLE;
use windows::Win32::System::Com::CoTaskMemFree;
use windows::Win32::UI::Shell::{FOLDERID_LocalAppData, KNOWN_FOLDER_FLAG, SHGetKnownFolderPath};

use crate::app::session;
use crate::error::{AppError, Result};

const MAX_LOG_SIZE: u64 = 512 * 1024;
Expand Down Expand Up @@ -81,26 +78,8 @@ fn open_log_file() -> Result<File> {
}

fn log_directory() -> Result<PathBuf> {
let path = local_appdata_path().unwrap_or_else(std::env::temp_dir);
Ok(path.join("Rivet").join("logs"))
}

fn local_appdata_path() -> Option<PathBuf> {
let path =
unsafe { SHGetKnownFolderPath(&FOLDERID_LocalAppData, KNOWN_FOLDER_FLAG(0), HANDLE(0)) }
.ok()?;
let buffer = unsafe {
let mut length = 0usize;
while *path.0.add(length) != 0 {
length += 1;
}
std::slice::from_raw_parts(path.0, length)
};
let value = String::from_utf16(buffer).ok().map(PathBuf::from);
unsafe {
CoTaskMemFree(Some(path.0 as _));
}
value
let path = session::data_dir().unwrap_or_else(|_| std::env::temp_dir().join("Rivet"));
Ok(path.join("logs"))
}

fn rotate_logs(path: &Path) -> Result<()> {
Expand Down