@gadmin2n/cli 0.0.113 → 0.0.115

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.
@@ -200,9 +200,18 @@ function syncClaudeContext(instanceDir, dryRun, source) {
200
200
  console.info(`${chalk.gray('Source: ')} ${source.repo} (${source.branch}) :: ${CLAUDE_SOURCE_SUBDIR}/`);
201
201
  console.info(`${chalk.gray('Targets:')} ${CLAUDE_TARGET_DIRS.map((d) => `${d}/`).join(', ')}\n`);
202
202
  if (dryRun) {
203
- console.info(chalk.gray('(dry-run mode would clone the repo and copy remote files into target dirs, overwriting existing files; instance-only files are kept)\n'));
203
+ console.info(chalk.gray('(dry-run — no files written. The real run would:'));
204
+ console.info(chalk.gray(` 1. git clone ${source.repo} --branch ${source.branch} --depth 1 (into tmp dir)`));
205
+ console.info(chalk.gray(` 2. Copy <tmp>/${CLAUDE_SOURCE_SUBDIR}/** → each target dir, OVERWRITING same-named files`));
206
+ console.info(chalk.gray(' 3. Files only present in target dirs (instance-only) are kept untouched)\n'));
204
207
  return;
205
208
  }
209
+ // Real run: warn the user that same-named files will be overwritten before
210
+ // we actually do it. They've already accepted the protocol prompt at this
211
+ // point, so we don't ask for further confirmation — just make the behaviour
212
+ // visible so changes to the local copy aren't silently clobbered.
213
+ console.info(chalk.yellow('⚠️ Same-named files in target dirs will be overwritten by the remote version.'));
214
+ console.info(chalk.gray(' Instance-only files (only present locally) are kept untouched.\n'));
206
215
  const claudeSrc = fetchClaudeContextRepo(source.repo, source.branch);
207
216
  if (!claudeSrc) {
208
217
  return;
@@ -443,7 +452,7 @@ function handleBinary(rel, baseRoot, oursRoot, theirsRoot, opts, conflicts) {
443
452
  detail: `binary differs three-ways. To accept template: cp "${theirsPath}" "${oursPath}"`,
444
453
  });
445
454
  console.warn(chalk.yellow(` ⚠️ binary conflict (cannot 3-way merge): ${rel}`));
446
- console.warn(chalk.gray(` template: ${theirsPath}`));
455
+ console.warn(chalk.gray(` template(theirs): ${theirsPath}`));
447
456
  console.warn(chalk.gray(` base: ${basePath}`));
448
457
  }
449
458
  function applyPlan(plan, baseRoot, oursRoot, theirsRoot, opts) {
@@ -799,8 +808,8 @@ class UpdateAction extends abstract_action_1.AbstractAction {
799
808
  baseRoot = path.join(instanceDir, '.gadmin/__nonexistent__');
800
809
  }
801
810
  try {
802
- console.info(`\n${chalk.gray('Template:')} @gadmin2n/schematics@${theirsVersion} (latest)`);
803
- console.info(`${chalk.gray('Instance:')} ${instanceDir}`);
811
+ console.info(`\n${chalk.gray('Template(Theirs):')} @gadmin2n/schematics@${theirsVersion} (latest)`);
812
+ console.info(`${chalk.gray('Instance(Ours):')} ${instanceDir}`);
804
813
  console.info(`${chalk.gray('Base: ')} ${metaExists
805
814
  ? `(materialized from schematics ${meta.schematicsVersion})`
806
815
  : '(not yet established — run `gadmin2 update` once to bootstrap)'}`);
@@ -875,7 +884,7 @@ class UpdateAction extends abstract_action_1.AbstractAction {
875
884
  console.error(chalk.red(err.message + '\n'));
876
885
  process.exit(2);
877
886
  }
878
- console.info(`Template: ${cfg.template} @ schematics ${meta.schematicsVersion}`);
887
+ console.info(`Template(Theirs): ${cfg.template} @ schematics ${meta.schematicsVersion}`);
879
888
  const allExcludes = [...excludes_1.HARDCODED_EXCLUDES, ...excludes_1.DEFAULT_EXCLUDES, ...userExcludes];
880
889
  const instanceFiles = (0, excludes_1.collectFiles)(instanceDir, allExcludes);
881
890
  const residual = (0, residual_scan_1.scanResidualMarkers)(instanceDir, instanceFiles);
@@ -979,8 +988,8 @@ class UpdateAction extends abstract_action_1.AbstractAction {
979
988
  }
980
989
  const theirsRoot = theirsHandle.dir;
981
990
  const schematicsVersion = theirsHandle.version;
982
- console.info(`\n${chalk.gray('Template:')} @gadmin2n/schematics@${schematicsVersion} (latest)`);
983
- console.info(`${chalk.gray('Instance:')} ${instanceDir}\n`);
991
+ console.info(`\n${chalk.gray('Template(Theirs):')} @gadmin2n/schematics@${schematicsVersion} (latest)`);
992
+ console.info(`${chalk.gray('Instance(Ours):')} ${instanceDir}\n`);
984
993
  // Snapshot package.json before any writes (for stage 3 install)
985
994
  pkgSnapshots = [
986
995
  snapshotPackageJson(instanceDir, '(root)'),
@@ -5,6 +5,7 @@ export interface ClassifyInput {
5
5
  theirsExists: boolean;
6
6
  oursEqBase?: () => boolean;
7
7
  oursEqTheirs?: () => boolean;
8
+ baseEqTheirs?: () => boolean;
8
9
  }
9
10
  export declare function classifyFile(input: ClassifyInput): ClassifyResult;
10
11
  export declare function classifyAll(baseDir: string, oursDir: string, theirsDir: string, userExcludes: string[]): ClassifiedPlan;
@@ -6,7 +6,7 @@ const fs = require("fs");
6
6
  const path = require("path");
7
7
  const excludes_1 = require("./excludes");
8
8
  function classifyFile(input) {
9
- var _a, _b, _c;
9
+ var _a, _b, _c, _d;
10
10
  const { baseExists, oursExists, theirsExists } = input;
11
11
  if (!baseExists && !oursExists && !theirsExists) {
12
12
  throw new Error('classifyFile: impossible state — file in none of the three sides');
@@ -25,8 +25,19 @@ function classifyFile(input) {
25
25
  if (baseExists && oursExists && !theirsExists) {
26
26
  return ((_b = input.oursEqBase) === null || _b === void 0 ? void 0 : _b.call(input)) ? 'delete' : 'modifyDeleteConflict';
27
27
  }
28
- // ✓✓✓ — all three sides exist. If ours already equals theirs, no merge needed.
29
- return ((_c = input.oursEqTheirs) === null || _c === void 0 ? void 0 : _c.call(input)) ? 'keep' : 'update';
28
+ // ✓✓✓ — all three sides exist.
29
+ // Fast path 1: ours already equals theirs no merge needed.
30
+ if ((_c = input.oursEqTheirs) === null || _c === void 0 ? void 0 : _c.call(input))
31
+ return 'keep';
32
+ // Fast path 2: base equals theirs → template hasn't changed for this file
33
+ // since the recorded base. A 3-way merge would produce ours unchanged
34
+ // (since theirs == base contributes no diff), so we skip the rewrite to
35
+ // avoid spurious "Updated" entries on every run when the instance has
36
+ // legitimately diverged from the template — rendered placeholders in
37
+ // init.sql, regenerated yarn.lock files, user-edited .env, etc.
38
+ if ((_d = input.baseEqTheirs) === null || _d === void 0 ? void 0 : _d.call(input))
39
+ return 'keep';
40
+ return 'update';
30
41
  }
31
42
  exports.classifyFile = classifyFile;
32
43
  function fileBytesEqual(p, q) {
@@ -53,6 +64,7 @@ function classifyAll(baseDir, oursDir, theirsDir, userExcludes) {
53
64
  theirsExists,
54
65
  oursEqBase: () => baseExists && oursExists && fileBytesEqual(path.join(baseDir, rel), path.join(oursDir, rel)),
55
66
  oursEqTheirs: () => oursExists && theirsExists && fileBytesEqual(path.join(oursDir, rel), path.join(theirsDir, rel)),
67
+ baseEqTheirs: () => baseExists && theirsExists && fileBytesEqual(path.join(baseDir, rel), path.join(theirsDir, rel)),
56
68
  });
57
69
  plan[result].push(rel);
58
70
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gadmin2n/cli",
3
- "version": "0.0.113",
3
+ "version": "0.0.115",
4
4
  "description": "Gadmin - modern, fast, powerful node.js web framework (@cli)",
5
5
  "publishConfig": {
6
6
  "access": "public"