From ba0e7f763cea114606bc0e93fb8d09692f7d91c3 Mon Sep 17 00:00:00 2001 From: Champbreed Date: Sat, 21 Mar 2026 11:58:28 +0100 Subject: [PATCH] =?UTF-8?q?fix(install):=20implement=20safety=20backup=20d?= =?UTF-8?q?uring=20migration=20to=20prevent=20dat=E2=80=A6=20(#368)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(install): implement safety backup during migration to prevent data loss * fix: safely migrate skills by backing up directory and preserving permissions --- tools/bin/install.js | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/tools/bin/install.js b/tools/bin/install.js index 3e7baab2..96fa4962 100755 --- a/tools/bin/install.js +++ b/tools/bin/install.js @@ -199,19 +199,22 @@ function installForTarget(tempDir, target) { const gitDir = path.join(target.path, ".git"); if (fs.existsSync(gitDir)) { console.log(` Migrating from full-repo install to skills-only layout…`); - const entries = fs.readdirSync(target.path); - for (const name of entries) { - const full = path.join(target.path, name); - const stat = fs.lstatSync(full); - if (stat.isDirectory() && !stat.isSymbolicLink()) { - if (fs.rmSync) { - fs.rmSync(full, { recursive: true, force: true }); - } else { - fs.rmdirSync(full, { recursive: true }); - } + const backupPath = `${target.path}_backup_${Date.now()}`; + try { + const stats = fs.lstatSync(target.path); + const isSymlink = stats.isSymbolicLink(); + const symlinkTarget = isSymlink ? + fs.readlinkSync(target.path) : null; + fs.renameSync(target.path, backupPath); + console.log(` ⚠️ Safety Backup created at: ${backupPath}`); + if (isSymlink) { + fs.symlinkSync(symlinkTarget, target.path, 'dir'); } else { - fs.unlinkSync(full); + fs.mkdirSync(target.path, { recursive: true, mode: stats.mode }); } + } catch (err) { + console.error(` Migration Error: ${err.message}`); + process.exit(1); } } else { console.log(` Updating existing install at ${target.path}…`);