screw-up 1.31.0 → 1.32.0

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 (34) hide show
  1. package/dist/index.cjs +503 -132
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.mjs +4 -4
  4. package/dist/main.cjs +519 -148
  5. package/dist/main.cjs.map +1 -1
  6. package/dist/main.mjs +6 -6
  7. package/dist/{metadata-file-BWd04LhD.js → metadata-file-D79yMa_A.js} +500 -128
  8. package/dist/metadata-file-D79yMa_A.js.map +1 -0
  9. package/dist/{packageMetadata-ip0rBTwa.cjs → packageMetadata-6po5LHyH.cjs} +5 -5
  10. package/dist/{packageMetadata-ip0rBTwa.cjs.map → packageMetadata-6po5LHyH.cjs.map} +1 -1
  11. package/dist/{packageMetadata-BDGBM3Fx.cjs → packageMetadata-Cwh4Fqmw.cjs} +3 -3
  12. package/dist/{packageMetadata-BsMXJpMH.js → packageMetadata-Sm2NpI2b.js} +6 -6
  13. package/dist/{packageMetadata-BsMXJpMH.js.map → packageMetadata-Sm2NpI2b.js.map} +1 -1
  14. package/dist/src/analyzer.d.ts +2 -2
  15. package/dist/src/analyzer.d.ts.map +1 -1
  16. package/dist/src/cli-internal.d.ts +2 -2
  17. package/dist/src/cli.d.ts +2 -2
  18. package/dist/src/declaration-import-fix.d.ts +2 -2
  19. package/dist/src/default-import-fix.d.ts +2 -2
  20. package/dist/src/fast-tags.d.ts +2 -2
  21. package/dist/src/fast-tags.d.ts.map +1 -1
  22. package/dist/src/generated/packageMetadata.d.ts +4 -4
  23. package/dist/src/git-operations.d.ts +2 -2
  24. package/dist/src/git-ref-utils.d.ts +16 -2
  25. package/dist/src/git-ref-utils.d.ts.map +1 -1
  26. package/dist/src/index.d.ts +2 -2
  27. package/dist/src/internal.d.ts +2 -2
  28. package/dist/src/main.d.ts +2 -2
  29. package/dist/src/metadata-file.d.ts +2 -2
  30. package/dist/src/text-edits.d.ts +2 -2
  31. package/dist/src/types.d.ts +2 -2
  32. package/dist/src/vite-plugin.d.ts +2 -2
  33. package/package.json +7 -7
  34. package/dist/metadata-file-BWd04LhD.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,11 +1,11 @@
1
1
  /*!
2
2
  * name: screw-up
3
- * version: 1.31.0
3
+ * version: 1.32.0
4
4
  * description: Simply package metadata inserter on Vite plugin
5
5
  * author: Kouji Matsui (@kekyo@mi.kekyo.net)
6
6
  * license: MIT
7
7
  * repository.url: https://github.com/kekyo/screw-up.git
8
- * git.commit.hash: ebb41ebf06ebe1bec39a3770c70a62cb95b4b7d6
8
+ * git.commit.hash: 8a0078c34fa41bdb0cbf2d23837ac5e3217cbf53
9
9
  */
10
10
  //#region \0rolldown/runtime.js
11
11
  var __create = Object.create;
@@ -38,6 +38,7 @@ require("glob");
38
38
  let isomorphic_git = require("isomorphic-git");
39
39
  isomorphic_git = __toESM(isomorphic_git);
40
40
  let crypto$1 = require("crypto");
41
+ let zlib = require("zlib");
41
42
  //#region node_modules/async-primitives/dist/index.mjs
42
43
  /*!
43
44
  * name: async-primitives
@@ -222,8 +223,8 @@ createLogicalContext(Symbol("[root]"));
222
223
  //#endregion
223
224
  //#region src/generated/packageMetadata.ts
224
225
  var name = "screw-up";
225
- var version = "1.31.0";
226
- var git_commit_hash = "ebb41ebf06ebe1bec39a3770c70a62cb95b4b7d6";
226
+ var version = "1.32.0";
227
+ var git_commit_hash = "8a0078c34fa41bdb0cbf2d23837ac5e3217cbf53";
227
228
  //#endregion
228
229
  //#region node_modules/json5/dist/index.js
229
230
  var require_dist = /* @__PURE__ */ __commonJSMin(((exports, module) => {
@@ -1686,10 +1687,10 @@ var require_dayjs_min = /* @__PURE__ */ __commonJSMin(((exports, module) => {
1686
1687
  //#region src/internal.ts
1687
1688
  var import_dist = /* @__PURE__ */ __toESM(require_dist(), 1);
1688
1689
  var import_dayjs_min = /* @__PURE__ */ __toESM(require_dayjs_min(), 1);
1689
- var JSON5 = __resolveDefaultExport$3(import_dist.default, false);
1690
- var dayjs$1 = __resolveDefaultExport$3(import_dayjs_min.default, false);
1690
+ var JSON5 = __resolveDefaultExport$2(import_dist.default, false);
1691
+ var dayjs$1 = __resolveDefaultExport$2(import_dayjs_min.default, false);
1691
1692
  globalThis.__screwUpIsInCJS_db7919f73ec9 = true;
1692
- function __resolveDefaultExport$3(module, isESM) {
1693
+ function __resolveDefaultExport$2(module, isESM) {
1693
1694
  const __isInCJS = typeof globalThis !== "undefined" && globalThis.__screwUpIsInCJS_db7919f73ec9 === true;
1694
1695
  const maybe = module;
1695
1696
  const hasDefault = !!(maybe && typeof maybe === "object" && "default" in maybe);
@@ -1851,26 +1852,16 @@ var resolvePackageMetadata = async (projectRoot, fetchGitMetadata, alwaysOverrid
1851
1852
  };
1852
1853
  //#endregion
1853
1854
  //#region src/git-ref-utils.ts
1854
- var git$1 = __resolveDefaultExport$2(isomorphic_git.default, false);
1855
- globalThis.__screwUpIsInCJS_89cc61422477 = true;
1856
- function __resolveDefaultExport$2(module, isESM) {
1857
- const __isInCJS = typeof globalThis !== "undefined" && globalThis.__screwUpIsInCJS_89cc61422477 === true;
1858
- const maybe = module;
1859
- const hasDefault = !!(maybe && typeof maybe === "object" && "default" in maybe);
1860
- const unwrapNamespaceDefault = (value) => {
1861
- if (!value || typeof value !== "object") return value;
1862
- const inner = value;
1863
- if ((inner.__esModule === true || typeof Symbol !== "undefined" && inner[Symbol.toStringTag] === "Module") && "default" in inner) return inner.default;
1864
- return value;
1865
- };
1866
- const resolvedDefault = hasDefault ? unwrapNamespaceDefault(maybe.default) : void 0;
1867
- if (__isInCJS) return hasDefault ? resolvedDefault !== null && resolvedDefault !== void 0 ? resolvedDefault : module : module;
1868
- if (isESM) {
1869
- if (hasDefault) return resolvedDefault;
1870
- throw new Error("Default export not found.");
1871
- }
1872
- return hasDefault ? resolvedDefault !== null && resolvedDefault !== void 0 ? resolvedDefault : module : module;
1873
- }
1855
+ var PACK_TRAILER_SIZE = 20;
1856
+ var LOOSE_TAG_RESOLUTION_CONCURRENCY = 4;
1857
+ var PACKED_OBJECT_TYPE_BY_CODE = new Map([
1858
+ [1, "commit"],
1859
+ [2, "tree"],
1860
+ [3, "blob"],
1861
+ [4, "tag"],
1862
+ [6, "ofs-delta"],
1863
+ [7, "ref-delta"]
1864
+ ]);
1874
1865
  /**
1875
1866
  * Resolve the actual Git directory for repositories, worktrees, and submodules.
1876
1867
  * @param repoPath - Repository path
@@ -1884,24 +1875,354 @@ var getActualGitDir = async (repoPath) => {
1884
1875
  if (!match) return gitDir;
1885
1876
  return (0, path.isAbsolute)(match[1]) ? match[1] : (0, path.join)(repoPath, match[1]);
1886
1877
  };
1878
+ var readFixedRange = async (fileHandle, offset, length) => {
1879
+ const buffer = Buffer.alloc(length);
1880
+ const { bytesRead } = await fileHandle.read(buffer, 0, length, offset);
1881
+ if (bytesRead !== length) throw new Error(`Unexpected EOF while reading pack entry at offset ${offset} (expected ${length}, got ${bytesRead})`);
1882
+ return buffer;
1883
+ };
1884
+ var readLooseObject = async (gitDir, oid) => {
1885
+ try {
1886
+ const wrapped = (0, zlib.inflateSync)(await (0, fs_promises.readFile)((0, path.join)(gitDir, "objects", oid.slice(0, 2), oid.slice(2))));
1887
+ const headerEnd = wrapped.indexOf(0);
1888
+ if (headerEnd < 0) throw new Error(`Invalid loose object header: ${oid}`);
1889
+ const header = wrapped.subarray(0, headerEnd).toString("utf-8");
1890
+ const match = header.match(/^(commit|tree|blob|tag) (\d+)$/);
1891
+ if (!match) throw new Error(`Unsupported loose object header: ${header}`);
1892
+ const content = wrapped.subarray(headerEnd + 1);
1893
+ const expectedSize = Number(match[2]);
1894
+ if (content.length !== expectedSize) throw new Error(`Loose object size mismatch: ${oid} (expected ${expectedSize}, got ${content.length})`);
1895
+ return {
1896
+ oid,
1897
+ type: match[1],
1898
+ content
1899
+ };
1900
+ } catch (error) {
1901
+ if (error.code === "ENOENT") return null;
1902
+ throw error;
1903
+ }
1904
+ };
1905
+ var readLargePackOffset = (idxBuffer, largeOffsetsStart, largeOffsetIndex) => {
1906
+ const offset = Number(idxBuffer.readBigUInt64BE(largeOffsetsStart + largeOffsetIndex * 8));
1907
+ if (!Number.isSafeInteger(offset)) throw new Error(`Pack offset exceeds safe integer range: ${offset}`);
1908
+ return offset;
1909
+ };
1910
+ var loadPackIndex = async (idxPath) => {
1911
+ const packPath = idxPath.replace(/\.idx$/, ".pack");
1912
+ const [idxBuffer, packStat, fileHandle] = await Promise.all([
1913
+ (0, fs_promises.readFile)(idxPath),
1914
+ (0, fs_promises.stat)(packPath),
1915
+ (0, fs_promises.open)(packPath, "r")
1916
+ ]);
1917
+ if (idxBuffer.readUInt32BE(0) !== 4285812579) throw new Error(`Unsupported pack index signature: ${idxPath}`);
1918
+ if (idxBuffer.readUInt32BE(4) !== 2) throw new Error(`Unsupported pack index version: ${idxPath}`);
1919
+ const objectCount = idxBuffer.readUInt32BE(1028);
1920
+ const oidStart = 1032;
1921
+ const offsetStart = oidStart + objectCount * 20 + objectCount * 4;
1922
+ const largeOffsetStart = offsetStart + objectCount * 4;
1923
+ const objectByOid = /* @__PURE__ */ new Map();
1924
+ const objectByOffset = /* @__PURE__ */ new Map();
1925
+ const sortedObjects = [];
1926
+ const packIndex = {
1927
+ fileHandle,
1928
+ objectByOid,
1929
+ objectByOffset
1930
+ };
1931
+ for (let index = 0; index < objectCount; index++) {
1932
+ const oidOffset = oidStart + index * 20;
1933
+ const oid = idxBuffer.subarray(oidOffset, oidOffset + 20).toString("hex");
1934
+ const rawOffset = idxBuffer.readUInt32BE(offsetStart + index * 4);
1935
+ const offset = (rawOffset & 2147483648) === 0 ? rawOffset : readLargePackOffset(idxBuffer, largeOffsetStart, rawOffset & 2147483647);
1936
+ sortedObjects.push({
1937
+ oid,
1938
+ offset
1939
+ });
1940
+ }
1941
+ sortedObjects.sort((left, right) => left.offset - right.offset);
1942
+ const packEndOffset = packStat.size - PACK_TRAILER_SIZE;
1943
+ for (let index = 0; index < sortedObjects.length; index++) {
1944
+ var _sortedObjects$offset, _sortedObjects;
1945
+ const currentObject = sortedObjects[index];
1946
+ const nextOffset = (_sortedObjects$offset = (_sortedObjects = sortedObjects[index + 1]) === null || _sortedObjects === void 0 ? void 0 : _sortedObjects.offset) !== null && _sortedObjects$offset !== void 0 ? _sortedObjects$offset : packEndOffset;
1947
+ const location = {
1948
+ oid: currentObject.oid,
1949
+ offset: currentObject.offset,
1950
+ nextOffset,
1951
+ packIndex
1952
+ };
1953
+ objectByOid.set(currentObject.oid, location);
1954
+ objectByOffset.set(currentObject.offset, location);
1955
+ }
1956
+ return packIndex;
1957
+ };
1958
+ var loadPackStore = async (gitDir) => {
1959
+ try {
1960
+ const packDir = (0, path.join)(gitDir, "objects", "pack");
1961
+ const idxPaths = (await (0, fs_promises.readdir)(packDir)).filter((entryName) => entryName.endsWith(".idx")).map((entryName) => (0, path.join)(packDir, entryName));
1962
+ const packs = await Promise.all(idxPaths.map(loadPackIndex));
1963
+ const objectByOid = /* @__PURE__ */ new Map();
1964
+ for (const pack of packs) for (const [oid, location] of pack.objectByOid.entries()) objectByOid.set(oid, location);
1965
+ return {
1966
+ packs,
1967
+ objectByOid
1968
+ };
1969
+ } catch (error) {
1970
+ if (error.code === "ENOENT") return {
1971
+ packs: [],
1972
+ objectByOid: /* @__PURE__ */ new Map()
1973
+ };
1974
+ throw error;
1975
+ }
1976
+ };
1977
+ var decodeOfsDeltaDistance = (buffer, startOffset) => {
1978
+ let cursor = startOffset;
1979
+ let byte = buffer[cursor++];
1980
+ let distance = byte & 127;
1981
+ while (byte & 128) {
1982
+ byte = buffer[cursor++];
1983
+ distance = distance + 1 << 7 | byte & 127;
1984
+ }
1985
+ return {
1986
+ distance,
1987
+ nextOffset: cursor
1988
+ };
1989
+ };
1990
+ var parsePackedEntryHeader = (entryBuffer, objectOffset) => {
1991
+ let cursor = 0;
1992
+ let byte = entryBuffer[cursor++];
1993
+ const packedType = PACKED_OBJECT_TYPE_BY_CODE.get(byte >> 4 & 7);
1994
+ if (!packedType) throw new Error(`Unsupported packed object type at offset ${objectOffset}`);
1995
+ let declaredSize = byte & 15;
1996
+ let shift = 4;
1997
+ while (byte & 128) {
1998
+ byte = entryBuffer[cursor++];
1999
+ declaredSize |= (byte & 127) << shift;
2000
+ shift += 7;
2001
+ }
2002
+ let baseOffset;
2003
+ let baseOid;
2004
+ if (packedType === "ofs-delta") {
2005
+ const decoded = decodeOfsDeltaDistance(entryBuffer, cursor);
2006
+ cursor = decoded.nextOffset;
2007
+ baseOffset = objectOffset - decoded.distance;
2008
+ } else if (packedType === "ref-delta") {
2009
+ baseOid = entryBuffer.subarray(cursor, cursor + 20).toString("hex");
2010
+ cursor += 20;
2011
+ }
2012
+ return {
2013
+ packedType,
2014
+ declaredSize,
2015
+ headerLength: cursor,
2016
+ baseOffset,
2017
+ baseOid
2018
+ };
2019
+ };
2020
+ var readDeltaSize = (buffer, startOffset) => {
2021
+ let cursor = startOffset;
2022
+ let size = 0;
2023
+ let shift = 0;
2024
+ while (cursor < buffer.length) {
2025
+ const byte = buffer[cursor++];
2026
+ size |= (byte & 127) << shift;
2027
+ if ((byte & 128) === 0) return {
2028
+ size,
2029
+ nextOffset: cursor
2030
+ };
2031
+ shift += 7;
2032
+ }
2033
+ throw new Error("Invalid git delta size encoding");
2034
+ };
2035
+ var applyGitDelta = (baseContent, deltaContent) => {
2036
+ const baseSizeInfo = readDeltaSize(deltaContent, 0);
2037
+ if (baseSizeInfo.size !== baseContent.length) throw new Error(`Git delta base size mismatch: expected ${baseSizeInfo.size}, got ${baseContent.length}`);
2038
+ const targetSizeInfo = readDeltaSize(deltaContent, baseSizeInfo.nextOffset);
2039
+ const result = Buffer.alloc(targetSizeInfo.size);
2040
+ let deltaOffset = targetSizeInfo.nextOffset;
2041
+ let resultOffset = 0;
2042
+ while (deltaOffset < deltaContent.length) {
2043
+ const opcode = deltaContent[deltaOffset++];
2044
+ if ((opcode & 128) !== 0) {
2045
+ let copyOffset = 0;
2046
+ let copySize = 0;
2047
+ if (opcode & 1) copyOffset |= deltaContent[deltaOffset++];
2048
+ if (opcode & 2) copyOffset |= deltaContent[deltaOffset++] << 8;
2049
+ if (opcode & 4) copyOffset |= deltaContent[deltaOffset++] << 16;
2050
+ if (opcode & 8) copyOffset |= deltaContent[deltaOffset++] << 24;
2051
+ if (opcode & 16) copySize |= deltaContent[deltaOffset++];
2052
+ if (opcode & 32) copySize |= deltaContent[deltaOffset++] << 8;
2053
+ if (opcode & 64) copySize |= deltaContent[deltaOffset++] << 16;
2054
+ if (copySize === 0) copySize = 65536;
2055
+ baseContent.copy(result, resultOffset, copyOffset, copyOffset + copySize);
2056
+ resultOffset += copySize;
2057
+ continue;
2058
+ }
2059
+ if (opcode === 0) throw new Error("Invalid git delta opcode");
2060
+ deltaContent.copy(result, resultOffset, deltaOffset, deltaOffset + opcode);
2061
+ deltaOffset += opcode;
2062
+ resultOffset += opcode;
2063
+ }
2064
+ if (resultOffset !== result.length) throw new Error(`Git delta size mismatch: expected ${result.length}, got ${resultOffset}`);
2065
+ return result;
2066
+ };
2067
+ var inflatePackedObject = (compressedContent) => Buffer.from((0, zlib.inflateSync)(compressedContent));
2068
+ var parseTagTargetOid = (tagContent) => {
2069
+ const firstLineEnd = tagContent.indexOf(10);
2070
+ const firstLine = firstLineEnd >= 0 ? tagContent.subarray(0, firstLineEnd).toString("utf-8") : tagContent.toString("utf-8");
2071
+ const match = firstLine.match(/^object ([0-9a-f]{40})$/);
2072
+ if (!match) throw new Error(`Invalid annotated tag payload: ${firstLine}`);
2073
+ return match[1];
2074
+ };
2075
+ var parseTreeEntries = (treeContent) => {
2076
+ const entries = [];
2077
+ let offset = 0;
2078
+ while (offset < treeContent.length) {
2079
+ const modeEnd = treeContent.indexOf(32, offset);
2080
+ if (modeEnd < 0) throw new Error("Invalid tree entry mode");
2081
+ const nameEnd = treeContent.indexOf(0, modeEnd + 1);
2082
+ if (nameEnd < 0 || nameEnd + 21 > treeContent.length) throw new Error("Invalid tree entry name");
2083
+ entries.push({
2084
+ mode: treeContent.subarray(offset, modeEnd).toString("utf-8"),
2085
+ name: treeContent.subarray(modeEnd + 1, nameEnd).toString("utf-8"),
2086
+ oid: treeContent.subarray(nameEnd + 1, nameEnd + 21).toString("hex")
2087
+ });
2088
+ offset = nameEnd + 21;
2089
+ }
2090
+ return entries;
2091
+ };
2092
+ var createGitObjectResolver = async (repoPath) => {
2093
+ const actualGitDir = await getActualGitDir(repoPath);
2094
+ const resolvedObjects = /* @__PURE__ */ new Map();
2095
+ let packStorePromise;
2096
+ const getPackStore = async () => {
2097
+ if (!packStorePromise) packStorePromise = loadPackStore(actualGitDir);
2098
+ return packStorePromise;
2099
+ };
2100
+ const readPackedObject = async (location) => {
2101
+ var _location$packIndex$o, _location$packIndex$o2, _header$baseOid;
2102
+ const entryLength = location.nextOffset - location.offset;
2103
+ const entryBuffer = await readFixedRange(location.packIndex.fileHandle, location.offset, entryLength);
2104
+ const header = parsePackedEntryHeader(entryBuffer, location.offset);
2105
+ const compressedContent = entryBuffer.subarray(header.headerLength);
2106
+ if (header.packedType === "commit" || header.packedType === "tree" || header.packedType === "blob" || header.packedType === "tag") {
2107
+ const content = inflatePackedObject(compressedContent);
2108
+ if (content.length !== header.declaredSize) throw new Error(`Packed object size mismatch: ${location.oid} (expected ${header.declaredSize}, got ${content.length})`);
2109
+ return {
2110
+ oid: location.oid,
2111
+ type: header.packedType,
2112
+ content
2113
+ };
2114
+ }
2115
+ const deltaContent = inflatePackedObject(compressedContent);
2116
+ if (deltaContent.length !== header.declaredSize) throw new Error(`Packed delta size mismatch: ${location.oid} (expected ${header.declaredSize}, got ${deltaContent.length})`);
2117
+ const baseObject = header.packedType === "ofs-delta" ? await readObject((_location$packIndex$o = (_location$packIndex$o2 = location.packIndex.objectByOffset.get(header.baseOffset)) === null || _location$packIndex$o2 === void 0 ? void 0 : _location$packIndex$o2.oid) !== null && _location$packIndex$o !== void 0 ? _location$packIndex$o : (() => {
2118
+ throw new Error(`Missing ofs-delta base object at offset ${header.baseOffset}`);
2119
+ })()) : await readObject((_header$baseOid = header.baseOid) !== null && _header$baseOid !== void 0 ? _header$baseOid : (() => {
2120
+ throw new Error("Missing ref-delta base object id");
2121
+ })());
2122
+ const content = applyGitDelta(baseObject.content, deltaContent);
2123
+ return {
2124
+ oid: location.oid,
2125
+ type: baseObject.type,
2126
+ content
2127
+ };
2128
+ };
2129
+ const readObject = async (oid) => {
2130
+ const cachedObject = resolvedObjects.get(oid);
2131
+ if (cachedObject) return cachedObject;
2132
+ const objectPromise = (async () => {
2133
+ const looseObject = await readLooseObject(actualGitDir, oid);
2134
+ if (looseObject) return looseObject;
2135
+ const location = (await getPackStore()).objectByOid.get(oid);
2136
+ if (!location) throw new Error(`Git object not found: ${oid}`);
2137
+ return readPackedObject(location);
2138
+ })();
2139
+ resolvedObjects.set(oid, objectPromise);
2140
+ try {
2141
+ return await objectPromise;
2142
+ } catch (error) {
2143
+ resolvedObjects.delete(oid);
2144
+ throw error;
2145
+ }
2146
+ };
2147
+ return {
2148
+ close: async () => {
2149
+ if (!packStorePromise) return;
2150
+ const packStore = await packStorePromise;
2151
+ await Promise.allSettled(packStore.packs.map(async (pack) => {
2152
+ await pack.fileHandle.close();
2153
+ }));
2154
+ },
2155
+ readObject,
2156
+ resolveTagOidToCommit: async (tagOid) => {
2157
+ let currentOid = tagOid;
2158
+ const visitedOids = /* @__PURE__ */ new Set();
2159
+ while (true) {
2160
+ if (visitedOids.has(currentOid)) throw new Error(`Detected cyclic tag reference: ${currentOid}`);
2161
+ visitedOids.add(currentOid);
2162
+ const object = await readObject(currentOid);
2163
+ if (object.type !== "tag") return currentOid;
2164
+ currentOid = parseTagTargetOid(object.content);
2165
+ }
2166
+ }
2167
+ };
2168
+ };
2169
+ var runWithConcurrency = async (values, concurrency, worker) => {
2170
+ let nextIndex = 0;
2171
+ const runWorker = async () => {
2172
+ while (nextIndex < values.length) {
2173
+ const currentIndex = nextIndex;
2174
+ nextIndex += 1;
2175
+ await worker(values[currentIndex]);
2176
+ }
2177
+ };
2178
+ await Promise.all(Array.from({ length: Math.min(concurrency, Math.max(values.length, 1)) }, () => runWorker()));
2179
+ };
1887
2180
  /**
1888
- * Resolve a tag object OID to the commit OID it ultimately points to.
1889
- * Lightweight tags are returned unchanged.
2181
+ * Resolve multiple tag object OIDs to their peeled commit OIDs.
1890
2182
  * @param repoPath - Repository path
1891
- * @param tagOid - Tag or commit OID
1892
- * @returns Commit hash this tag points to
2183
+ * @param tagOids - Tag or commit OIDs
2184
+ * @returns Map of tag object OID to peeled commit OID
1893
2185
  */
1894
- var resolveTagOidToCommit = async (repoPath, tagOid) => {
2186
+ var resolveTagOidsToCommits = async (repoPath, tagOids) => {
2187
+ const resolver = await createGitObjectResolver(repoPath);
2188
+ const result = /* @__PURE__ */ new Map();
2189
+ const uniqueTagOids = Array.from(new Set(tagOids));
1895
2190
  try {
1896
- var _tagObject$tag;
1897
- const tagObject = await git$1.readTag({
1898
- fs: fs_promises.default,
1899
- dir: repoPath,
1900
- oid: tagOid
2191
+ await runWithConcurrency(uniqueTagOids, LOOSE_TAG_RESOLUTION_CONCURRENCY, async (tagOid) => {
2192
+ result.set(tagOid, await resolver.resolveTagOidToCommit(tagOid));
1901
2193
  });
1902
- if (tagObject === null || tagObject === void 0 || (_tagObject$tag = tagObject.tag) === null || _tagObject$tag === void 0 ? void 0 : _tagObject$tag.object) return tagObject.tag.object;
1903
- } catch (_unused) {}
1904
- return tagOid;
2194
+ } finally {
2195
+ await resolver.close();
2196
+ }
2197
+ return result;
2198
+ };
2199
+ var collectTreeFiles = async (resolver, treeOid, prefix, files) => {
2200
+ const treeObject = await resolver.readObject(treeOid);
2201
+ if (treeObject.type !== "tree") throw new Error(`Expected tree object: ${treeOid}`);
2202
+ for (const entry of parseTreeEntries(treeObject.content)) {
2203
+ const path$7 = prefix ? `${prefix}/${entry.name}` : entry.name;
2204
+ if (entry.mode === "40000") {
2205
+ await collectTreeFiles(resolver, entry.oid, path$7, files);
2206
+ continue;
2207
+ }
2208
+ if (entry.mode !== "160000") files.set(path$7, entry.oid);
2209
+ }
2210
+ };
2211
+ /**
2212
+ * Collect all tracked file blob OIDs under the specified tree.
2213
+ * @param repoPath - Repository path
2214
+ * @param treeOid - Tree object OID
2215
+ * @returns Map of repository-relative file path to blob OID
2216
+ */
2217
+ var listTreeFiles = async (repoPath, treeOid) => {
2218
+ const resolver = await createGitObjectResolver(repoPath);
2219
+ const files = /* @__PURE__ */ new Map();
2220
+ try {
2221
+ await collectTreeFiles(resolver, treeOid, "", files);
2222
+ } finally {
2223
+ await resolver.close();
2224
+ }
2225
+ return files;
1905
2226
  };
1906
2227
  //#endregion
1907
2228
  //#region src/fast-tags.ts
@@ -1995,19 +2316,28 @@ var resolveTagsBatchWithCommit = async (repoPath, tagNames, logger) => {
1995
2316
  const remainingTags = tagNames.filter((tag) => !result.has(tag));
1996
2317
  if (remainingTags.length > 0) {
1997
2318
  const looseRefsStart = Date.now();
1998
- await Promise.all(remainingTags.map(async (tagName) => {
2319
+ const looseTagEntries = (await Promise.all(remainingTags.map(async (tagName) => {
1999
2320
  const looseRefPath = (0, path.join)(actualGitDir, "refs", "tags", tagName);
2000
2321
  try {
2001
- const oid = (await (0, fs_promises.readFile)(looseRefPath, "utf-8")).trim();
2002
- const commitOid = await resolveTagOidToCommit(repoPath, oid);
2322
+ return {
2323
+ tagName,
2324
+ oid: (await (0, fs_promises.readFile)(looseRefPath, "utf-8")).trim()
2325
+ };
2326
+ } catch (error) {
2327
+ if (error.code !== "ENOENT") throw error;
2328
+ return;
2329
+ }
2330
+ }))).filter((entry) => entry !== void 0);
2331
+ if (looseTagEntries.length > 0) {
2332
+ const commitOids = await resolveTagOidsToCommits(repoPath, looseTagEntries.map((entry) => entry.oid));
2333
+ for (const { tagName, oid } of looseTagEntries) {
2334
+ var _commitOids$get;
2003
2335
  result.set(tagName, {
2004
2336
  oid,
2005
- commitOid
2337
+ commitOid: (_commitOids$get = commitOids.get(oid)) !== null && _commitOids$get !== void 0 ? _commitOids$get : oid
2006
2338
  });
2007
- } catch (error) {
2008
- if (error.code !== "ENOENT") throw error;
2009
2339
  }
2010
- }));
2340
+ }
2011
2341
  logger.debug(`[fast-tags] read loose refs: ${Date.now() - looseRefsStart}ms`);
2012
2342
  }
2013
2343
  const totalTime = Date.now() - startTime;
@@ -2220,7 +2550,8 @@ var getCommit = async (repositoryPath, hash) => {
2220
2550
  shortHash: commit.oid.substring(0, 7),
2221
2551
  date: (/* @__PURE__ */ new Date(commit.commit.author.timestamp * 1e3)).toISOString(),
2222
2552
  message: commit.commit.message.trim(),
2223
- parents: commit.commit.parent || []
2553
+ parents: commit.commit.parent || [],
2554
+ tree: commit.commit.tree
2224
2555
  };
2225
2556
  } catch (_unused) {
2226
2557
  return;
@@ -2248,7 +2579,8 @@ var getCurrentCommit = async (repositoryPath) => {
2248
2579
  shortHash: commit.oid.substring(0, 7),
2249
2580
  date: (/* @__PURE__ */ new Date(commit.commit.author.timestamp * 1e3)).toISOString(),
2250
2581
  message: commit.commit.message.trim(),
2251
- parents: commit.commit.parent || []
2582
+ parents: commit.commit.parent || [],
2583
+ tree: commit.commit.tree
2252
2584
  };
2253
2585
  } catch (_unused2) {
2254
2586
  return;
@@ -2288,94 +2620,133 @@ var getRelatedBranches = async (repositoryPath, commitHash) => {
2288
2620
  return [];
2289
2621
  }
2290
2622
  };
2291
- /**
2292
- * Check if the repository has modified files (following RelaxVersioner logic).
2293
- * Checks for staged files, unstaged files, and untracked files (respecting .gitignore).
2294
- * @param repositoryPath - Local Git repository directory
2295
- * @returns Modified files
2296
- */
2297
- var isModifiedFile = ([, head, workdir, stage]) => {
2298
- return workdir === 2 || stage === 2 || stage === 3 || head === 1 && workdir === 0 || head === 0 && workdir === 1;
2299
- };
2300
- var getStatusRow = async (filepath, entries) => {
2301
- const [head, workdir, stage] = entries;
2302
- const [headType, workdirType, stageType] = await Promise.all([
2303
- head ? head.type() : void 0,
2304
- workdir ? workdir.type() : void 0,
2305
- stage ? stage.type() : void 0
2306
- ]);
2307
- const isBlob = [
2308
- headType,
2309
- workdirType,
2310
- stageType
2311
- ].includes("blob");
2312
- if ((headType === "tree" || headType === "special") && !isBlob) return;
2313
- if (headType === "commit") return;
2314
- if ((workdirType === "tree" || workdirType === "special") && !isBlob) return;
2315
- if (stageType === "commit") return;
2316
- if ((stageType === "tree" || stageType === "special") && !isBlob) return;
2317
- const headOid = headType === "blob" ? await head.oid() : void 0;
2318
- const stageOid = stageType === "blob" ? await stage.oid() : void 0;
2319
- let workdirOid;
2320
- if (headType !== "blob" && workdirType === "blob" && stageType !== "blob") workdirOid = "42";
2321
- else if (workdirType === "blob") workdirOid = await workdir.oid();
2322
- const entry = [
2323
- void 0,
2324
- headOid,
2325
- workdirOid,
2326
- stageOid
2327
- ];
2328
- const statusValues = entry.map((value) => entry.indexOf(value));
2329
- return [
2330
- filepath,
2331
- statusValues[1],
2332
- statusValues[2],
2333
- statusValues[3]
2334
- ];
2335
- };
2336
- var reduceModifiedFiles = async (parent, children) => {
2337
- const modifiedFiles = parent ? [parent] : [];
2338
- for (const child of children) modifiedFiles.push(...child);
2339
- return modifiedFiles;
2340
- };
2341
- var iterateSequentially = async (walk, children) => {
2342
- const results = [];
2343
- for (const child of children) results.push(await walk(child));
2344
- return results;
2345
- };
2346
- var getModifiedFiles = async (repositoryPath) => {
2623
+ var parseGitIndex = async (gitDir) => {
2347
2624
  try {
2348
- return await isomorphic_git.walk({
2349
- fs: fs_promises.default,
2350
- dir: repositoryPath,
2351
- trees: [
2352
- isomorphic_git.TREE({ ref: "HEAD" }),
2353
- isomorphic_git.WORKDIR(),
2354
- isomorphic_git.STAGE()
2355
- ],
2356
- map: async (filepath, entries) => {
2357
- const [head, workdir, stage] = entries;
2358
- if (!head && !stage && workdir) {
2359
- if (await isomorphic_git.isIgnored({
2360
- fs: fs_promises.default,
2361
- dir: repositoryPath,
2362
- filepath
2363
- })) return null;
2625
+ const buffer = await fs_promises.default.readFile((0, path.join)(gitDir, "index"));
2626
+ if (buffer.subarray(0, 4).toString("ascii") !== "DIRC") throw new Error("Unsupported git index signature");
2627
+ const version = buffer.readUInt32BE(4);
2628
+ if (version !== 2 && version !== 3) throw new Error(`Unsupported git index version: ${version}`);
2629
+ const entryCount = buffer.readUInt32BE(8);
2630
+ let offset = 12;
2631
+ const entries = /* @__PURE__ */ new Map();
2632
+ for (let index = 0; index < entryCount; index++) {
2633
+ const entryStart = offset;
2634
+ const size = buffer.readUInt32BE(entryStart + 36);
2635
+ const oid = buffer.subarray(entryStart + 40, entryStart + 60).toString("hex");
2636
+ const flags = buffer.readUInt16BE(entryStart + 60);
2637
+ const stage = flags >> 12 & 3;
2638
+ offset = entryStart + 62;
2639
+ if (version >= 3 && (flags & 16384) !== 0) offset += 2;
2640
+ const pathEnd = buffer.indexOf(0, offset);
2641
+ if (pathEnd < 0) throw new Error("Invalid git index path entry");
2642
+ const path$3 = buffer.subarray(offset, pathEnd).toString("utf-8");
2643
+ offset = pathEnd + 1;
2644
+ while ((offset - entryStart) % 8 !== 0) offset += 1;
2645
+ entries.set(path$3, {
2646
+ path: path$3,
2647
+ oid,
2648
+ size,
2649
+ stage
2650
+ });
2651
+ }
2652
+ return entries;
2653
+ } catch (error) {
2654
+ if (error.code === "ENOENT") return /* @__PURE__ */ new Map();
2655
+ throw error;
2656
+ }
2657
+ };
2658
+ var listTrackedDirectories = (indexEntries) => {
2659
+ const directories = new Set([""]);
2660
+ for (const path$4 of indexEntries.keys()) {
2661
+ const segments = path$4.split("/");
2662
+ let currentPath = "";
2663
+ for (let index = 0; index < segments.length - 1; index++) {
2664
+ currentPath = currentPath ? `${currentPath}/${segments[index]}` : segments[index];
2665
+ directories.add(currentPath);
2666
+ }
2667
+ }
2668
+ return directories;
2669
+ };
2670
+ var listWorkingDirectoryFiles = async (repositoryPath, trackedDirectories, relativePath = "") => {
2671
+ const directoryPath = relativePath ? (0, path.join)(repositoryPath, relativePath) : repositoryPath;
2672
+ const entries = await fs_promises.default.readdir(directoryPath, { withFileTypes: true });
2673
+ const files = [];
2674
+ for (const entry of entries) {
2675
+ if (entry.name === ".git") continue;
2676
+ const entryPath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
2677
+ if (entry.isDirectory()) {
2678
+ if (!trackedDirectories.has(entryPath)) {
2679
+ if (await isomorphic_git.isIgnored({
2680
+ fs: fs_promises.default,
2681
+ dir: repositoryPath,
2682
+ filepath: entryPath
2683
+ })) continue;
2684
+ }
2685
+ files.push(...await listWorkingDirectoryFiles(repositoryPath, trackedDirectories, entryPath));
2686
+ continue;
2687
+ }
2688
+ if (entry.isFile() || entry.isSymbolicLink()) files.push(entryPath);
2689
+ }
2690
+ return files;
2691
+ };
2692
+ var calculateBlobOid = async (filePath) => {
2693
+ const content = await fs_promises.default.readFile(filePath);
2694
+ return (0, crypto$1.createHash)("sha1").update(`blob ${content.length}\0`).update(content).digest("hex");
2695
+ };
2696
+ var getModifiedFiles = async (repositoryPath, headTreeOid) => {
2697
+ try {
2698
+ const gitDir = await getActualGitDir(repositoryPath);
2699
+ const [headFiles, indexEntries] = await Promise.all([listTreeFiles(repositoryPath, headTreeOid), parseGitIndex(gitDir)]);
2700
+ const workdirFiles = await listWorkingDirectoryFiles(repositoryPath, listTrackedDirectories(indexEntries));
2701
+ const modifiedFiles = /* @__PURE__ */ new Map();
2702
+ const rememberModifiedFile = (path$5, reason) => {
2703
+ if (!modifiedFiles.has(path$5)) modifiedFiles.set(path$5, {
2704
+ path: path$5,
2705
+ reason
2706
+ });
2707
+ };
2708
+ for (const [path$6, headOid] of headFiles.entries()) {
2709
+ const indexEntry = indexEntries.get(path$6);
2710
+ if (!indexEntry) rememberModifiedFile(path$6, "staged");
2711
+ else if (indexEntry.stage !== 0 || indexEntry.oid !== headOid) rememberModifiedFile(path$6, "staged");
2712
+ }
2713
+ for (const indexEntry of indexEntries.values()) {
2714
+ if (!headFiles.has(indexEntry.path)) rememberModifiedFile(indexEntry.path, "staged");
2715
+ const absolutePath = (0, path.join)(repositoryPath, indexEntry.path);
2716
+ try {
2717
+ const stats = await fs_promises.default.lstat(absolutePath);
2718
+ if (!stats.isFile() && !stats.isSymbolicLink()) {
2719
+ rememberModifiedFile(indexEntry.path, "worktree");
2720
+ continue;
2364
2721
  }
2365
- const statusRow = await getStatusRow(filepath, entries);
2366
- if (!statusRow || !isModifiedFile(statusRow)) return;
2367
- return statusRow;
2368
- },
2369
- reduce: reduceModifiedFiles,
2370
- iterate: iterateSequentially
2371
- });
2722
+ if (indexEntry.stage !== 0) {
2723
+ rememberModifiedFile(indexEntry.path, "staged");
2724
+ continue;
2725
+ }
2726
+ if (indexEntry.size !== stats.size || await calculateBlobOid(absolutePath) !== indexEntry.oid) rememberModifiedFile(indexEntry.path, "worktree");
2727
+ } catch (error) {
2728
+ if (error.code === "ENOENT") {
2729
+ rememberModifiedFile(indexEntry.path, "worktree");
2730
+ continue;
2731
+ }
2732
+ throw error;
2733
+ }
2734
+ }
2735
+ const trackedPaths = new Set(indexEntries.keys());
2736
+ for (const filepath of workdirFiles) {
2737
+ if (trackedPaths.has(filepath)) continue;
2738
+ if (!await isomorphic_git.isIgnored({
2739
+ fs: fs_promises.default,
2740
+ dir: repositoryPath,
2741
+ filepath
2742
+ })) rememberModifiedFile(filepath, "untracked");
2743
+ }
2744
+ return Array.from(modifiedFiles.values());
2372
2745
  } catch (_unused5) {
2373
2746
  return [];
2374
2747
  }
2375
2748
  };
2376
- var formatModifiedFile = (modifiedFile) => {
2377
- return `'${modifiedFile[0]}':${modifiedFile[1]}:${modifiedFile[2]}:${modifiedFile[3]}`;
2378
- };
2749
+ var formatModifiedFile = (modifiedFile) => `'${modifiedFile.path}':${modifiedFile.reason}`;
2379
2750
  /**
2380
2751
  * Lookup version label recursively core analyzer
2381
2752
  * @param cwd - The directory to check
@@ -2475,7 +2846,7 @@ var getGitMetadata = async (repositoryPath, checkWorkingDirectoryStatus, logger)
2475
2846
  metadata.git = gitMetadata;
2476
2847
  if (version) {
2477
2848
  if (checkWorkingDirectoryStatus) {
2478
- const modifiedFiles = await getModifiedFiles(gitRootPath);
2849
+ const modifiedFiles = await getModifiedFiles(gitRootPath, currentCommit.tree);
2479
2850
  if (modifiedFiles.length >= 1) {
2480
2851
  const newVersion = incrementLastVersionComponent(version);
2481
2852
  logger.debug(`Increased git version by detected modified items: ${formatVersion(version)} ---> ${formatVersion(newVersion)}, Files=[${modifiedFiles.map(formatModifiedFile).join(", ")}]`);