From 83986e0589a4bd1a43f12dd361728c9454382f9b Mon Sep 17 00:00:00 2001 From: vitya Date: Sun, 23 Aug 2026 10:17:37 +0300 Subject: [PATCH] meta(tasks): migration script --skip + merge-guard --- scripts/migrate-tasks-v2.mjs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/scripts/migrate-tasks-v2.mjs b/scripts/migrate-tasks-v2.mjs index 399b9df..14595f9 100644 --- a/scripts/migrate-tasks-v2.mjs +++ b/scripts/migrate-tasks-v2.mjs @@ -35,6 +35,8 @@ const APPLY = process.argv.includes("--apply"); const VERIFY = process.argv.includes("--verify"); const scopeArg = process.argv.find((a) => a.startsWith("--repos=")); const SCOPE = scopeArg ? scopeArg.split("=")[1].split(",") : null; +const skipArg = process.argv.find((a) => a.startsWith("--skip=")); +const SKIP = skipArg ? new Set(skipArg.split("=")[1].split(",")) : new Set(); const extraArg = process.argv.find((a) => a.startsWith("--extra=")); const EXTRA = extraArg ? extraArg.split("=")[1].split(",").map((p) => path.resolve(p)) : []; const PLAN_FILE = path.join(os.tmpdir(), "tasks-v2-plan.json"); @@ -167,9 +169,11 @@ function collect() { const candidates = []; for (const d of dirs) { if (SCOPE && !SCOPE.includes(d.name)) continue; + if (SKIP.has(d.name)) continue; if (fs.existsSync(path.join(ROOT, d.name, ".tasks"))) candidates.push(d.name); } for (const extra of EXTRA) { + if (SKIP.has(path.basename(extra))) continue; if (fs.existsSync(path.join(extra, ".tasks"))) candidates.push(path.basename(extra)); } const all = []; @@ -296,6 +300,11 @@ function applyOne(repoDir, td, repoTasks, globalBySlug) { console.log(` skip ${path.basename(repoDir)}: not a git repo (no commit safety)`); return; } + const conflicted = git(repoDir, "status --porcelain").split("\n").some((l) => /^(UU|AA|DD|AU|UA|DU|UD)/.test(l)); + if (conflicted || git(repoDir, "rev-parse -q --verify MERGE_HEAD")) { + console.log(` skip ${path.basename(repoDir)}: unresolved merge/rebase (git commit unsafe)`); + return; + } let renamed = 0; for (const t of repoTasks) { if (!t.hasFile) continue; @@ -343,6 +352,7 @@ async function main() { for (const t of ts) if (!bySlug.has(t.slug)) bySlug.set(t.slug, t); } for (const [repo, ts] of Object.entries(byRepo)) { + if (SKIP.has(repo)) { console.log(`skip (--skip): ${repo}`); continue; } applyOne(repoDirFor(repo), path.join(repoDirFor(repo), ".tasks"), ts, bySlug); console.log(`applied: ${repo}`); }