chore: move appdata folder to .claudeDo
This commit is contained in:
@@ -7,7 +7,7 @@ public sealed class AttachmentStore
|
||||
private readonly string _root;
|
||||
|
||||
public AttachmentStore(string? root = null)
|
||||
=> _root = root ?? Paths.Expand("~/.todo-app/attachments");
|
||||
=> _root = root ?? Path.Combine(Paths.AppDataRoot(), "attachments");
|
||||
|
||||
public string Root => _root;
|
||||
|
||||
|
||||
@@ -63,9 +63,9 @@ dir(s) via an optional `AttachmentStore` ctor param (defaults to the production
|
||||
|
||||
- **ClaudeDoDbContext** — EF Core DbContext; WAL mode + foreign keys via `UseSqlite` options
|
||||
- **IDbContextFactory\<ClaudeDoDbContext\>** — registered in DI; used by singleton consumers (e.g. the Worker hosted service)
|
||||
- **Paths** — expands `~` and `%USERPROFILE%`, resolves relative paths. App root `~/.todo-app`
|
||||
- **AppSettings** — loads `~/.todo-app/ui.config.json` (DbPath, SignalRUrl)
|
||||
- **AttachmentStore** — dependency-free file store, default root `~/.todo-app/attachments/<taskId>/`. `SaveAsync` enforces a 5 MB cap and a path-traversal/containment guard. Also `DeleteFile`, `DeleteTaskDir`, `TaskDir`, `Root`, `EnumerateTaskIds` (used by the worker orphan sweep). Attachment files live **outside** git worktrees intentionally.
|
||||
- **Paths** — expands `~` and `%USERPROFILE%`, resolves relative paths. App root `~/.claudeDo`
|
||||
- **AppSettings** — loads `~/.claudeDo/ui.config.json` (DbPath, SignalRUrl)
|
||||
- **AttachmentStore** — dependency-free file store, default root `~/.claudeDo/attachments/<taskId>/`. `SaveAsync` enforces a 5 MB cap and a path-traversal/containment guard. Also `DeleteFile`, `DeleteTaskDir`, `TaskDir`, `Root`, `EnumerateTaskIds` (used by the worker orphan sweep). Attachment files live **outside** git worktrees intentionally.
|
||||
|
||||
## Git
|
||||
|
||||
|
||||
@@ -41,7 +41,50 @@ public static class Paths
|
||||
return trimmed.Length == 0 || trimmed.EndsWith(':') ? path : trimmed;
|
||||
}
|
||||
|
||||
/// <summary>~/.todo-app — parent directory for db, logs, config, sandbox, worktrees.</summary>
|
||||
public static string AppDataRoot() =>
|
||||
Expand("~/.todo-app");
|
||||
private const string DirName = ".claudeDo";
|
||||
private const string LegacyDirName = ".todo-app";
|
||||
|
||||
/// <summary>
|
||||
/// ~/.claudeDo — parent directory for db, logs, config, sandbox, worktrees.
|
||||
/// Falls back to the legacy ~/.todo-app while that one still exists and the new one
|
||||
/// doesn't, so a failed <see cref="MigrateLegacyAppDataRoot"/> degrades to "keep using
|
||||
/// the old folder" instead of silently starting over on an empty one.
|
||||
/// </summary>
|
||||
public static string AppDataRoot()
|
||||
{
|
||||
var root = Expand("~/" + DirName);
|
||||
if (!Directory.Exists(root))
|
||||
{
|
||||
var legacy = Expand("~/" + LegacyDirName);
|
||||
if (Directory.Exists(legacy)) return legacy;
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// One-time rename of ~/.todo-app to ~/.claudeDo, including the path literals stored
|
||||
/// inside worker.config.json / ui.config.json. No-op once the new folder exists.
|
||||
/// Called from the Worker at startup before anything opens a file under the root —
|
||||
/// the single mover, so the UI never races it.
|
||||
/// </summary>
|
||||
public static void MigrateLegacyAppDataRoot() => MigrateLegacyAppDataRoot(Expand("~"));
|
||||
|
||||
internal static void MigrateLegacyAppDataRoot(string home)
|
||||
{
|
||||
var root = Path.Combine(home, DirName);
|
||||
var legacy = Path.Combine(home, LegacyDirName);
|
||||
if (Directory.Exists(root) || !Directory.Exists(legacy)) return;
|
||||
|
||||
// A locked file (e.g. an old worker still holding todo.db) fails the move; AppDataRoot
|
||||
// then keeps returning the legacy path and the next start retries.
|
||||
try { Directory.Move(legacy, root); }
|
||||
catch (IOException) { return; }
|
||||
catch (UnauthorizedAccessException) { return; }
|
||||
|
||||
foreach (var cfg in Directory.EnumerateFiles(root, "*.config.json"))
|
||||
{
|
||||
try { File.WriteAllText(cfg, File.ReadAllText(cfg).Replace(LegacyDirName, DirName)); }
|
||||
catch (IOException) { /* best effort — the default already points at the new root */ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user