@optique/git 1.0.0-dev.886 → 1.0.0-dev.896

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/index.cjs CHANGED
@@ -76,6 +76,45 @@ function listFailureMessage(error, dir, errors, fallback) {
76
76
  }
77
77
  /** Default depth for commit suggestions. */
78
78
  const DEFAULT_SUGGESTION_DEPTH = 15;
79
+ /**
80
+ * Computes the shortest unique short OID for each given full OID within the
81
+ * provided set, starting from a minimum length. When two or more OIDs share
82
+ * the same short prefix, their prefixes are lengthened until each is unique
83
+ * (up to the full 40-char OID).
84
+ *
85
+ * Note: this only disambiguates within the given set, not against the entire
86
+ * object database. In the rare case that a suggested short OID collides with
87
+ * an older commit outside the suggestion window, the parser will report a
88
+ * clear "ambiguous" error prompting the user to type more characters.
89
+ */
90
+ function uniqueShortOids(oids, minLength) {
91
+ const result = /* @__PURE__ */ new Map();
92
+ const lengths = /* @__PURE__ */ new Map();
93
+ for (const oid of oids) lengths.set(oid, minLength);
94
+ let remaining = new Set(oids);
95
+ while (remaining.size > 0) {
96
+ const groups = /* @__PURE__ */ new Map();
97
+ for (const oid of remaining) {
98
+ const len = lengths.get(oid);
99
+ const short = oid.slice(0, len);
100
+ const group = groups.get(short);
101
+ if (group != null) group.push(oid);
102
+ else groups.set(short, [oid]);
103
+ }
104
+ const nextRemaining = /* @__PURE__ */ new Set();
105
+ for (const [short, group] of groups) if (group.length === 1) result.set(group[0], short);
106
+ else for (const oid of group) {
107
+ const currentLen = lengths.get(oid);
108
+ if (currentLen >= oid.length) result.set(oid, oid);
109
+ else {
110
+ lengths.set(oid, currentLen + 1);
111
+ nextRemaining.add(oid);
112
+ }
113
+ }
114
+ remaining = nextRemaining;
115
+ }
116
+ return result;
117
+ }
79
118
  function createAsyncValueParser(options, metavar, parseFn, suggestFn) {
80
119
  (0, __optique_core_nonempty.ensureNonEmptyString)(metavar);
81
120
  if (options?.suggestionDepth !== void 0) {
@@ -400,8 +439,11 @@ function gitCommit(options) {
400
439
  dir,
401
440
  depth
402
441
  });
403
- for (const commit of commits) if (commit.oid.startsWith(prefix)) {
404
- const shortOid = commit.oid.slice(0, Math.max(7, prefix.length));
442
+ const matching = commits.filter((c) => c.oid.startsWith(prefix));
443
+ const minLen = Math.max(7, prefix.length);
444
+ const shortOids = uniqueShortOids(matching.map((c) => c.oid), minLen);
445
+ for (const commit of matching) {
446
+ const shortOid = shortOids.get(commit.oid);
405
447
  const firstLine = commit.commit.message.split("\n")[0];
406
448
  yield {
407
449
  kind: "literal",
@@ -500,8 +542,11 @@ function gitRef(options) {
500
542
  text: tag
501
543
  };
502
544
  }
503
- for (const commit of commits) if (commit.oid.startsWith(prefix)) {
504
- const shortOid = commit.oid.slice(0, Math.max(7, prefix.length));
545
+ const matching = commits.filter((c) => c.oid.startsWith(prefix));
546
+ const minLen = Math.max(7, prefix.length);
547
+ const shortOids = uniqueShortOids(matching.map((c) => c.oid), minLen);
548
+ for (const commit of matching) {
549
+ const shortOid = shortOids.get(commit.oid);
505
550
  if (seen.has(shortOid)) continue;
506
551
  seen.add(shortOid);
507
552
  const firstLine = commit.commit.message.split("\n")[0];
package/dist/index.js CHANGED
@@ -54,6 +54,45 @@ function listFailureMessage(error, dir, errors, fallback) {
54
54
  }
55
55
  /** Default depth for commit suggestions. */
56
56
  const DEFAULT_SUGGESTION_DEPTH = 15;
57
+ /**
58
+ * Computes the shortest unique short OID for each given full OID within the
59
+ * provided set, starting from a minimum length. When two or more OIDs share
60
+ * the same short prefix, their prefixes are lengthened until each is unique
61
+ * (up to the full 40-char OID).
62
+ *
63
+ * Note: this only disambiguates within the given set, not against the entire
64
+ * object database. In the rare case that a suggested short OID collides with
65
+ * an older commit outside the suggestion window, the parser will report a
66
+ * clear "ambiguous" error prompting the user to type more characters.
67
+ */
68
+ function uniqueShortOids(oids, minLength) {
69
+ const result = /* @__PURE__ */ new Map();
70
+ const lengths = /* @__PURE__ */ new Map();
71
+ for (const oid of oids) lengths.set(oid, minLength);
72
+ let remaining = new Set(oids);
73
+ while (remaining.size > 0) {
74
+ const groups = /* @__PURE__ */ new Map();
75
+ for (const oid of remaining) {
76
+ const len = lengths.get(oid);
77
+ const short = oid.slice(0, len);
78
+ const group = groups.get(short);
79
+ if (group != null) group.push(oid);
80
+ else groups.set(short, [oid]);
81
+ }
82
+ const nextRemaining = /* @__PURE__ */ new Set();
83
+ for (const [short, group] of groups) if (group.length === 1) result.set(group[0], short);
84
+ else for (const oid of group) {
85
+ const currentLen = lengths.get(oid);
86
+ if (currentLen >= oid.length) result.set(oid, oid);
87
+ else {
88
+ lengths.set(oid, currentLen + 1);
89
+ nextRemaining.add(oid);
90
+ }
91
+ }
92
+ remaining = nextRemaining;
93
+ }
94
+ return result;
95
+ }
57
96
  function createAsyncValueParser(options, metavar, parseFn, suggestFn) {
58
97
  ensureNonEmptyString(metavar);
59
98
  if (options?.suggestionDepth !== void 0) {
@@ -378,8 +417,11 @@ function gitCommit(options) {
378
417
  dir,
379
418
  depth
380
419
  });
381
- for (const commit of commits) if (commit.oid.startsWith(prefix)) {
382
- const shortOid = commit.oid.slice(0, Math.max(7, prefix.length));
420
+ const matching = commits.filter((c) => c.oid.startsWith(prefix));
421
+ const minLen = Math.max(7, prefix.length);
422
+ const shortOids = uniqueShortOids(matching.map((c) => c.oid), minLen);
423
+ for (const commit of matching) {
424
+ const shortOid = shortOids.get(commit.oid);
383
425
  const firstLine = commit.commit.message.split("\n")[0];
384
426
  yield {
385
427
  kind: "literal",
@@ -478,8 +520,11 @@ function gitRef(options) {
478
520
  text: tag
479
521
  };
480
522
  }
481
- for (const commit of commits) if (commit.oid.startsWith(prefix)) {
482
- const shortOid = commit.oid.slice(0, Math.max(7, prefix.length));
523
+ const matching = commits.filter((c) => c.oid.startsWith(prefix));
524
+ const minLen = Math.max(7, prefix.length);
525
+ const shortOids = uniqueShortOids(matching.map((c) => c.oid), minLen);
526
+ for (const commit of matching) {
527
+ const shortOid = shortOids.get(commit.oid);
483
528
  if (seen.has(shortOid)) continue;
484
529
  seen.add(shortOid);
485
530
  const firstLine = commit.commit.message.split("\n")[0];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/git",
3
- "version": "1.0.0-dev.886+4b42a9bd",
3
+ "version": "1.0.0-dev.896+5a811a7f",
4
4
  "description": "Git value parsers for Optique",
5
5
  "keywords": [
6
6
  "CLI",
@@ -59,7 +59,7 @@
59
59
  "dependencies": {
60
60
  "@logtape/logtape": "^1.2.2",
61
61
  "isomorphic-git": "^1.36.1",
62
- "@optique/core": "1.0.0-dev.886+4b42a9bd"
62
+ "@optique/core": "1.0.0-dev.896+5a811a7f"
63
63
  },
64
64
  "devDependencies": {
65
65
  "@types/node": "^20.19.9",