acdev 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/paths.js ADDED
@@ -0,0 +1,128 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ /** Product data directory inside the target repo (config, state, .env). */
5
+ export const DATA_DIR = '.acdev';
6
+ /** Older product data dirs — migrated once if present (newest first). */
7
+ export const LEGACY_DATA_DIRS = ['.codepilot', '.agent-mcp'];
8
+
9
+ /** Sibling worktrees root (next to the target repo). */
10
+ export const WORKTREES_DIR = '.acdev-worktrees';
11
+ export const LEGACY_WORKTREES_DIRS = ['.codepilot-worktrees', '.agent-mcp-worktrees'];
12
+
13
+ /** @deprecated use LEGACY_DATA_DIRS */
14
+ export const LEGACY_DATA_DIR = LEGACY_DATA_DIRS[LEGACY_DATA_DIRS.length - 1];
15
+ /** @deprecated use LEGACY_WORKTREES_DIRS */
16
+ export const LEGACY_WORKTREES_DIR = LEGACY_WORKTREES_DIRS[LEGACY_WORKTREES_DIRS.length - 1];
17
+
18
+ /** @type {Set<string>} */
19
+ const dataMigrationChecked = new Set();
20
+ /** @type {Set<string>} */
21
+ const worktreesMigrationChecked = new Set();
22
+
23
+ /**
24
+ * @param {string} src
25
+ * @param {string} dest
26
+ */
27
+ function copyDirRecursive(src, dest) {
28
+ fs.mkdirSync(dest, { recursive: true });
29
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
30
+ const from = path.join(src, entry.name);
31
+ const to = path.join(dest, entry.name);
32
+ if (entry.isDirectory()) {
33
+ copyDirRecursive(from, to);
34
+ } else {
35
+ fs.copyFileSync(from, to);
36
+ }
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Prefer rename; fall back to recursive copy (e.g. cross-device).
42
+ * @param {string} from
43
+ * @param {string} to
44
+ */
45
+ function renameOrCopyDir(from, to) {
46
+ try {
47
+ fs.renameSync(from, to);
48
+ } catch {
49
+ copyDirRecursive(from, to);
50
+ }
51
+ }
52
+
53
+ /**
54
+ * If `.acdev/` is missing but a legacy data dir exists, migrate once (best-effort).
55
+ * Prefers `.codepilot/` over `.agent-mcp/` when both exist.
56
+ * @param {string} repoRoot
57
+ * @returns {boolean} true if migration ran
58
+ */
59
+ export function migrateLegacyDataDir(repoRoot) {
60
+ if (dataMigrationChecked.has(repoRoot)) return false;
61
+ dataMigrationChecked.add(repoRoot);
62
+
63
+ const next = path.join(repoRoot, DATA_DIR);
64
+ if (fs.existsSync(next)) {
65
+ return false;
66
+ }
67
+
68
+ for (const legacyName of LEGACY_DATA_DIRS) {
69
+ const legacy = path.join(repoRoot, legacyName);
70
+ if (!fs.existsSync(legacy)) continue;
71
+ renameOrCopyDir(legacy, next);
72
+ console.log(`[acdev] Migrated ${legacyName}/ → ${DATA_DIR}/`);
73
+ return true;
74
+ }
75
+ return false;
76
+ }
77
+
78
+ /**
79
+ * If `.acdev-worktrees/` is missing but a legacy worktrees dir exists, migrate once.
80
+ * Worktrees live as a sibling of the repo root.
81
+ * @param {string} repoRoot
82
+ * @returns {boolean} true if migration ran
83
+ */
84
+ export function migrateLegacyWorktreesDir(repoRoot) {
85
+ if (worktreesMigrationChecked.has(repoRoot)) return false;
86
+ worktreesMigrationChecked.add(repoRoot);
87
+
88
+ const next = path.join(repoRoot, '..', WORKTREES_DIR);
89
+ if (fs.existsSync(next)) {
90
+ return false;
91
+ }
92
+
93
+ for (const legacyName of LEGACY_WORKTREES_DIRS) {
94
+ const legacy = path.join(repoRoot, '..', legacyName);
95
+ if (!fs.existsSync(legacy)) continue;
96
+ renameOrCopyDir(legacy, next);
97
+ console.log(`[acdev] Migrated ${legacyName}/ → ${WORKTREES_DIR}/`);
98
+ return true;
99
+ }
100
+ return false;
101
+ }
102
+
103
+ /**
104
+ * Ensure legacy data is migrated, then return `.acdev` absolute path.
105
+ * Does not create the directory.
106
+ * @param {string} repoRoot
107
+ */
108
+ export function dataDir(repoRoot) {
109
+ migrateLegacyDataDir(repoRoot);
110
+ return path.join(repoRoot, DATA_DIR);
111
+ }
112
+
113
+ /**
114
+ * Absolute path to the worktrees root (migrates legacy name if needed).
115
+ * @param {string} repoRoot
116
+ */
117
+ export function worktreesRoot(repoRoot) {
118
+ migrateLegacyWorktreesDir(repoRoot);
119
+ return path.join(repoRoot, '..', WORKTREES_DIR);
120
+ }
121
+
122
+ /**
123
+ * Reset migration caches (tests only).
124
+ */
125
+ export function _resetMigrationCachesForTests() {
126
+ dataMigrationChecked.clear();
127
+ worktreesMigrationChecked.clear();
128
+ }