@tankpkg/cli 0.15.4 → 0.15.5

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/dist/bin/tank.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { a as VERSION, i as USER_AGENT, l as setConfig, n as flushLogs, o as getConfig, s as getConfigDir, t as authFlowLog } from "../debug-logger-U1Y6MrNL.js";
2
+ import { a as VERSION, i as USER_AGENT, l as setConfig, n as flushLogs, o as getConfig, s as getConfigDir, t as authFlowLog } from "../debug-logger-BjqA9j5b.js";
3
3
  import { t as logger } from "../logger-BhULz3Uz.js";
4
4
  import { createRequire } from "node:module";
5
5
  import { Command } from "commander";
@@ -8856,6 +8856,28 @@ function mkdirSafeNoSymlinks(targetDir) {
8856
8856
  } else fs.mkdirSync(current);
8857
8857
  }
8858
8858
  }
8859
+ function isDirNonEmpty(dir) {
8860
+ try {
8861
+ return fs.readdirSync(dir).length > 0;
8862
+ } catch {
8863
+ return false;
8864
+ }
8865
+ }
8866
+ function moveEntryAcrossDevices(src, dst) {
8867
+ try {
8868
+ fs.renameSync(src, dst);
8869
+ } catch (err) {
8870
+ if (err.code === "EXDEV") {
8871
+ fs.cpSync(src, dst, { recursive: true });
8872
+ fs.rmSync(src, {
8873
+ recursive: true,
8874
+ force: true
8875
+ });
8876
+ return;
8877
+ }
8878
+ throw err;
8879
+ }
8880
+ }
8859
8881
  async function extractSafely(tarball, destDir) {
8860
8882
  if (tarball.length > MAX_DOWNLOAD_BYTES) throw new TankIntegrityError(`Tarball exceeds ${MAX_DOWNLOAD_BYTES} byte limit`);
8861
8883
  const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "tank-extract-"));
@@ -8863,6 +8885,7 @@ async function extractSafely(tarball, destDir) {
8863
8885
  fs.writeFileSync(tmpTarball, tarball, { flag: "wx" });
8864
8886
  let entryCount = 0;
8865
8887
  let totalBytes = 0;
8888
+ let backupDir = null;
8866
8889
  try {
8867
8890
  await extract({
8868
8891
  file: tmpTarball,
@@ -8882,22 +8905,31 @@ async function extractSafely(tarball, destDir) {
8882
8905
  }
8883
8906
  });
8884
8907
  mkdirSafeNoSymlinks(destDir);
8908
+ if (isDirNonEmpty(destDir)) {
8909
+ backupDir = `${destDir}.tank-old-${crypto$1.randomUUID()}`;
8910
+ fs.renameSync(destDir, backupDir);
8911
+ mkdirSafeNoSymlinks(destDir);
8912
+ }
8885
8913
  for (const entry of fs.readdirSync(tmpDir)) {
8886
8914
  if (entry === path.basename(tmpTarball)) continue;
8887
- const src = path.join(tmpDir, entry);
8888
- const dst = path.join(destDir, entry);
8889
- try {
8890
- fs.renameSync(src, dst);
8891
- } catch (err) {
8892
- if (err.code === "EXDEV") {
8893
- fs.cpSync(src, dst, { recursive: true });
8894
- fs.rmSync(src, {
8895
- recursive: true,
8896
- force: true
8897
- });
8898
- } else throw err;
8899
- }
8915
+ moveEntryAcrossDevices(path.join(tmpDir, entry), path.join(destDir, entry));
8900
8916
  }
8917
+ if (backupDir !== null) {
8918
+ fs.rmSync(backupDir, {
8919
+ recursive: true,
8920
+ force: true
8921
+ });
8922
+ backupDir = null;
8923
+ }
8924
+ } catch (err) {
8925
+ if (backupDir !== null && fs.existsSync(backupDir)) try {
8926
+ fs.rmSync(destDir, {
8927
+ recursive: true,
8928
+ force: true
8929
+ });
8930
+ fs.renameSync(backupDir, destDir);
8931
+ } catch {}
8932
+ throw err;
8901
8933
  } finally {
8902
8934
  fs.rmSync(tmpDir, {
8903
8935
  recursive: true,
@@ -11900,7 +11932,11 @@ program.command("install").alias("i").description("Install a skill from the Tank
11900
11932
  process.exit(1);
11901
11933
  }
11902
11934
  });
11903
- program.command("remove").aliases(["rm", "r"]).description("Remove an installed skill").argument("<name>", "Skill name (e.g., @org/skill-name)").option("-g, --global", "Remove a globally installed skill").action(async (name, opts) => {
11935
+ program.command("remove").aliases([
11936
+ "rm",
11937
+ "r",
11938
+ "uninstall"
11939
+ ]).description("Remove an installed skill").argument("<name>", "Skill name (e.g., @org/skill-name)").option("-g, --global", "Remove a globally installed skill").action(async (name, opts) => {
11904
11940
  try {
11905
11941
  await removeCommand({
11906
11942
  name,