refactor: migrate snapshot and skill_state paths to ~/.codewhale
- Add resolve_project_state_dir and ensure_project_state_dir to
codewhale-config, providing project-local .codewhale/.deepseek
resolution matching the home-directory pattern.
- Migrate snapshot paths to prefer ~/.codewhale/snapshots with
~/.deepseek/snapshots fallback (snapshot_base_with_home).
- Migrate skill_state.rs to use codewhale_config::ensure_state_dir
instead of hardcoded home.join(".deepseek").
- Update doc comments to reference canonical .codewhale paths.
Part of #2231 (state-root migration).
This commit is contained in:
@@ -1618,6 +1618,36 @@ pub fn ensure_state_dir(subdir: &str) -> Result<PathBuf> {
|
||||
Ok(dir)
|
||||
}
|
||||
|
||||
/// Resolve a project-local state subdirectory, preferring `.codewhale/`
|
||||
/// when it exists, falling back to `.deepseek/` for legacy projects.
|
||||
///
|
||||
/// Returns `(true, path)` when the primary `.codewhale/` path is used,
|
||||
/// `(false, path)` for the legacy fallback. The boolean helps callers
|
||||
/// emit a deprecation notice on legacy paths.
|
||||
pub fn resolve_project_state_dir(
|
||||
workspace: &Path,
|
||||
subdir: &str,
|
||||
) -> (bool, PathBuf) {
|
||||
let primary = workspace.join(CODEWHALE_APP_DIR).join(subdir);
|
||||
if primary.exists() {
|
||||
return (true, primary);
|
||||
}
|
||||
let legacy = workspace.join(LEGACY_APP_DIR).join(subdir);
|
||||
(false, legacy)
|
||||
}
|
||||
|
||||
/// Ensure a project-local state subdirectory exists under `.codewhale/`,
|
||||
/// creating it if necessary. Returns the directory path.
|
||||
pub fn ensure_project_state_dir(
|
||||
workspace: &Path,
|
||||
subdir: &str,
|
||||
) -> Result<PathBuf> {
|
||||
let dir = workspace.join(CODEWHALE_APP_DIR).join(subdir);
|
||||
std::fs::create_dir_all(&dir)
|
||||
.with_context(|| format!("failed to create {}/", dir.display()))?;
|
||||
Ok(dir)
|
||||
}
|
||||
|
||||
pub fn resolve_config_path(explicit: Option<PathBuf>) -> Result<PathBuf> {
|
||||
let path = if let Some(path) = explicit {
|
||||
path
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
//! filesystem-discovered `SkillRegistry`: the registry tells us which skills
|
||||
//! exist on disk, and this store tells API clients which ones are marked active.
|
||||
//!
|
||||
//! Storage shape (TOML at `~/.deepseek/skills_state.toml`):
|
||||
//! Storage shape (TOML at `~/.codewhale/skills_state.toml`, legacy `~/.deepseek/skills_state.toml`):
|
||||
//!
|
||||
//! ```toml
|
||||
//! disabled = ["skill-name-1", "skill-name-2"]
|
||||
@@ -104,10 +104,8 @@ impl SkillStateStore {
|
||||
}
|
||||
|
||||
fn default_state_path() -> Result<PathBuf> {
|
||||
let home = dirs::home_dir().context("could not resolve $HOME for ~/.deepseek")?;
|
||||
let dir = home.join(".deepseek");
|
||||
fs::create_dir_all(&dir)
|
||||
.with_context(|| format!("create deepseek state dir at {}", dir.display()))?;
|
||||
let dir = codewhale_config::ensure_state_dir(".")
|
||||
.context("could not resolve or create CodeWhale state directory")?;
|
||||
Ok(dir.join(STATE_FILE_NAME))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
//! Path resolution for the per-workspace snapshot side-repos.
|
||||
//!
|
||||
//! Snapshots live in `~/.deepseek/snapshots/<project_hash>/<worktree_hash>/`.
|
||||
//! The two-level hash split lets us snapshot multiple worktrees of the same
|
||||
//! project independently — `git worktree list` users won't get cross-talk
|
||||
//! between feature branches.
|
||||
//! Snapshots live under the resolved state directory
|
||||
//! (`~/.codewhale/snapshots` or legacy `~/.deepseek/snapshots`) with
|
||||
//! a two-level hash split so we can snapshot multiple worktrees of the
|
||||
//! same project independently — `git worktree list` users won't get
|
||||
//! cross-talk between feature branches.
|
||||
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
/// Compute the snapshot directory for a given workspace path.
|
||||
///
|
||||
/// Returns `~/.deepseek/snapshots/<project_hash>/<worktree_hash>/`. The
|
||||
/// caller is responsible for creating it on disk; we purposefully don't
|
||||
/// touch the filesystem here so this is cheap to call repeatedly.
|
||||
/// Returns `$STATE_DIR/snapshots/<project_hash>/<worktree_hash>/` where
|
||||
/// `$STATE_DIR` is resolved via `codewhale_config::resolve_state_dir`.
|
||||
/// The caller is responsible for creating it on disk; we purposefully
|
||||
/// don't touch the filesystem here so this is cheap to call repeatedly.
|
||||
///
|
||||
/// The `project_hash` is derived from the canonicalized workspace path
|
||||
/// after stripping any `.worktrees/<name>` suffix — multiple worktrees
|
||||
@@ -24,7 +26,7 @@ pub fn snapshot_dir_for(workspace: &Path) -> PathBuf {
|
||||
}
|
||||
|
||||
/// Same as [`snapshot_dir_for`] but with an injectable home directory.
|
||||
/// Used by tests so we never touch the user's real `~/.deepseek/`.
|
||||
/// Used by tests so they never touch the user's real state directory.
|
||||
pub fn snapshot_dir_with_home(workspace: &Path, home: Option<PathBuf>) -> PathBuf {
|
||||
let home = home.unwrap_or_else(|| PathBuf::from("."));
|
||||
let canonical = workspace
|
||||
@@ -33,12 +35,21 @@ pub fn snapshot_dir_with_home(workspace: &Path, home: Option<PathBuf>) -> PathBu
|
||||
let project_root = strip_worktree_suffix(&canonical);
|
||||
let project_hash = stable_hex(&project_root);
|
||||
let worktree_hash = stable_hex(&canonical);
|
||||
home.join(".deepseek")
|
||||
.join("snapshots")
|
||||
snapshot_base_with_home(Some(home))
|
||||
.join(project_hash)
|
||||
.join(worktree_hash)
|
||||
}
|
||||
|
||||
fn snapshot_base_with_home(home: Option<PathBuf>) -> PathBuf {
|
||||
let home = home.unwrap_or_else(|| PathBuf::from("."));
|
||||
// Prefer .codewhale, fall back to .deepseek
|
||||
let primary = home.join(".codewhale").join("snapshots");
|
||||
if primary.exists() {
|
||||
return primary;
|
||||
}
|
||||
home.join(".deepseek").join("snapshots")
|
||||
}
|
||||
|
||||
/// Resolve the `.git` directory inside the snapshot dir.
|
||||
pub fn snapshot_git_dir(workspace: &Path) -> PathBuf {
|
||||
snapshot_dir_for(workspace).join(".git")
|
||||
|
||||
Reference in New Issue
Block a user