@alessandroraffa/tangyr 1.0.0 → 1.0.1

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.
Files changed (2) hide show
  1. package/dist/index.js +44 -6
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -21351,6 +21351,19 @@ function writeSharedFile(filePath, parsed, serializer, isFirstWrite, logger) {
21351
21351
  `tangyr: first modification of ${filePath} \u2014 unmanaged data will be preserved but exact whitespace or comments may not be.`
21352
21352
  );
21353
21353
  }
21354
+ let realTarget = null;
21355
+ try {
21356
+ if (fs19.lstatSync(filePath).isSymbolicLink()) {
21357
+ realTarget = fs19.realpathSync(filePath);
21358
+ }
21359
+ } catch {
21360
+ realTarget = null;
21361
+ }
21362
+ if (realTarget && realTarget !== filePath) {
21363
+ logger.warn(
21364
+ `tangyr: ${filePath} is a symlink \u2014 the file being modified is ${realTarget}`
21365
+ );
21366
+ }
21354
21367
  fs19.mkdirSync(path18.dirname(filePath), { recursive: true });
21355
21368
  fs19.writeFileSync(filePath, serialized);
21356
21369
  return true;
@@ -22200,6 +22213,12 @@ async function runUninstallCommand(options, logger) {
22200
22213
  uninstallProjectRoot
22201
22214
  );
22202
22215
  if (actualPath && (fs27.existsSync(actualPath) || isSymlink(actualPath))) {
22216
+ if (!stillMatchesRecord(actualPath, file.hash)) {
22217
+ logger.warn(
22218
+ ` left in place (no longer what was installed): ${actualPath}`
22219
+ );
22220
+ continue;
22221
+ }
22203
22222
  removeManagedPath(actualPath);
22204
22223
  logger.verbose(` removed: ${actualPath}`);
22205
22224
  removedCount++;
@@ -22228,7 +22247,16 @@ async function runUninstallCommand(options, logger) {
22228
22247
  }
22229
22248
  }
22230
22249
  if (fullUninstall) {
22231
- for (const backup of manifest.backups) {
22250
+ const newestFirst = [...manifest.backups].reverse();
22251
+ const restored = /* @__PURE__ */ new Set();
22252
+ for (const backup of newestFirst) {
22253
+ if (restored.has(backup.originalPath)) {
22254
+ logger.verbose(
22255
+ ` superseded by a newer backup, not restored: ${backup.backupLocation}`
22256
+ );
22257
+ continue;
22258
+ }
22259
+ restored.add(backup.originalPath);
22232
22260
  try {
22233
22261
  restoreBackup(backup, logger);
22234
22262
  } catch (err) {
@@ -22621,6 +22649,13 @@ var MERGE_SURFACE_SLOTS = /* @__PURE__ */ new Set([
22621
22649
  "mcp_shared_file",
22622
22650
  "mcp_file"
22623
22651
  ]);
22652
+ function stillMatchesRecord(artifactPath, recorded) {
22653
+ if (isLegacyArtifactState(recorded)) {
22654
+ return true;
22655
+ }
22656
+ const actual = describeArtifactState(artifactPath);
22657
+ return actual === null || actual === recorded;
22658
+ }
22624
22659
  function isMergeSurfaceKey(relativePath) {
22625
22660
  const [, ...rest] = relativePath.split("/");
22626
22661
  return MERGE_SURFACE_SLOTS.has(rest.join("/"));
@@ -30689,10 +30724,7 @@ function parseCommandFile(commandFile) {
30689
30724
  function isBackupablePath(targetPath) {
30690
30725
  try {
30691
30726
  const lstat = fs43.lstatSync(targetPath);
30692
- if (lstat.isSymbolicLink()) {
30693
- return false;
30694
- }
30695
- return lstat.isFile() || lstat.isDirectory();
30727
+ return lstat.isSymbolicLink() || lstat.isFile() || lstat.isDirectory();
30696
30728
  } catch {
30697
30729
  return false;
30698
30730
  }
@@ -30702,7 +30734,10 @@ function backupConflictingTarget(targetPath, scopePath) {
30702
30734
  const relativeToRoot = path43.relative("/", targetPath).replace(/^\.\.\/+/gu, "");
30703
30735
  const backupPath = path43.join(scopePath, "backups", ts2, relativeToRoot);
30704
30736
  fs43.mkdirSync(path43.dirname(backupPath), { recursive: true });
30705
- if (fs43.lstatSync(targetPath).isDirectory()) {
30737
+ const stat = fs43.lstatSync(targetPath);
30738
+ if (stat.isSymbolicLink()) {
30739
+ fs43.symlinkSync(fs43.readlinkSync(targetPath), backupPath);
30740
+ } else if (stat.isDirectory()) {
30706
30741
  fs43.cpSync(targetPath, backupPath, {
30707
30742
  recursive: true,
30708
30743
  // Preserve links as links: following them would copy the kit into the
@@ -31058,6 +31093,9 @@ SKIPPED CONFLICTS (${skippedTargetPaths.size} target(s) left unchanged):`
31058
31093
  for (const backup of backupsToAdd) {
31059
31094
  manifest.backups.push(backup);
31060
31095
  }
31096
+ if (backupsToAdd.length > 0) {
31097
+ writeManifest(scopePath, manifest);
31098
+ }
31061
31099
  const mappings = loadMappings(kitInfo.path, config, configDir);
31062
31100
  const installLossReport = createLossReport();
31063
31101
  let installedCount = 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alessandroraffa/tangyr",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "CLI for the Tangyr discipline — install and manage operating kits for AI coding tools",
5
5
  "license": "MIT",
6
6
  "engines": {