Files
tolaria/src-tauri/src/commands/vault/lifecycle_cmds.rs
2026-05-01 02:01:49 +02:00

157 lines
5.1 KiB
Rust

use crate::commands::expand_tilde;
use crate::{git, vault};
use std::path::Path;
#[tauri::command]
pub fn migrate_is_a_to_type(vault_path: String) -> Result<usize, String> {
let vault_path = expand_tilde(&vault_path);
vault::migrate_is_a_to_type(&vault_path)
}
#[tauri::command]
pub fn create_empty_vault(target_path: String) -> Result<String, String> {
let path = expand_tilde(&target_path).into_owned();
let vault_dir = Path::new(&path);
initialize_empty_vault(vault_dir, &path)?;
Ok(canonical_vault_path_string(vault_dir))
}
fn initialize_empty_vault(vault_dir: &Path, vault_path: &str) -> Result<(), String> {
ensure_directory_is_missing_or_empty(vault_dir)?;
std::fs::create_dir_all(vault_dir)
.map_err(|e| format!("Failed to create vault directory: {}", e))?;
git::init_repo(vault_path)?;
vault::seed_config_files(vault_path);
Ok(())
}
fn ensure_directory_is_missing_or_empty(vault_dir: &Path) -> Result<(), String> {
if !vault_dir.exists() {
return Ok(());
}
let metadata = std::fs::metadata(vault_dir)
.map_err(|e| format!("Failed to inspect target folder: {e}"))?;
if !metadata.is_dir() {
return Err("Choose a folder path for the new vault".to_string());
}
let has_entries = std::fs::read_dir(vault_dir)
.map_err(|e| format!("Failed to inspect target folder: {e}"))?
.next()
.is_some();
if has_entries {
return Err("Choose an empty folder to create a new vault".to_string());
}
Ok(())
}
fn canonical_vault_path_string(vault_dir: &Path) -> String {
vault_dir
.canonicalize()
.unwrap_or_else(|_| vault_dir.to_path_buf())
.to_string_lossy()
.to_string()
}
#[tauri::command]
pub async fn create_getting_started_vault(target_path: Option<String>) -> Result<String, String> {
let path = resolve_getting_started_target(target_path.as_deref())?;
tokio::task::spawn_blocking(move || vault::create_getting_started_vault(&path))
.await
.map_err(|e| format!("Task panicked: {e}"))?
}
fn resolve_getting_started_target(target_path: Option<&str>) -> Result<String, String> {
match target_path {
Some(path) if !path.is_empty() => Ok(expand_tilde(path).into_owned()),
_ => vault::default_vault_path().map(|path| path.to_string_lossy().to_string()),
}
}
#[tauri::command]
pub fn check_vault_exists(path: String) -> bool {
let path = expand_tilde(&path);
vault::vault_exists(&path)
}
#[tauri::command]
pub fn get_default_vault_path() -> Result<String, String> {
vault::default_vault_path().map(|path| path.to_string_lossy().to_string())
}
#[tauri::command]
pub fn repair_vault(vault_path: String) -> Result<String, String> {
let vault_path = expand_tilde(&vault_path);
vault::migrate_is_a_to_type(&vault_path)?;
vault::repair_config_files(&vault_path)?;
git::ensure_gitignore(std::path::Path::new(vault_path.as_ref()))?;
Ok("Vault repaired".to_string())
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
#[test]
fn empty_vault_target_validation_allows_missing_or_empty_directories() {
let dir = tempfile::TempDir::new().unwrap();
let missing = dir.path().join("new-vault");
let empty = dir.path().join("empty-vault");
fs::create_dir(&empty).unwrap();
assert_eq!(ensure_directory_is_missing_or_empty(&missing), Ok(()));
assert_eq!(ensure_directory_is_missing_or_empty(&empty), Ok(()));
}
#[test]
fn empty_vault_target_validation_rejects_files_and_nonempty_directories() {
let dir = tempfile::TempDir::new().unwrap();
let file = dir.path().join("vault.md");
let nonempty = dir.path().join("vault");
fs::write(&file, "# Not a folder").unwrap();
fs::create_dir(&nonempty).unwrap();
fs::write(nonempty.join("note.md"), "# Existing note").unwrap();
assert_eq!(
ensure_directory_is_missing_or_empty(&file),
Err("Choose a folder path for the new vault".to_string())
);
assert_eq!(
ensure_directory_is_missing_or_empty(&nonempty),
Err("Choose an empty folder to create a new vault".to_string())
);
}
#[test]
fn canonical_vault_path_uses_existing_canonical_path_or_original_path() {
let dir = tempfile::TempDir::new().unwrap();
let existing = dir.path().join("existing");
let missing = dir.path().join("missing");
fs::create_dir(&existing).unwrap();
assert_eq!(
canonical_vault_path_string(&existing),
existing.canonicalize().unwrap().to_string_lossy()
);
assert_eq!(
canonical_vault_path_string(&missing),
missing.to_string_lossy()
);
}
#[test]
fn getting_started_target_uses_explicit_path_when_provided() {
let dir = tempfile::TempDir::new().unwrap();
let explicit = dir.path().join("starter");
assert_eq!(
resolve_getting_started_target(explicit.to_str()),
Ok(explicit.to_string_lossy().to_string())
);
}
}