hillclimb 0.8.8 → 0.8.10
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/main.js +154 -68
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -14711,8 +14711,11 @@ function createGitError(args, err, timeoutMs = GIT_COMMAND_TIMEOUT_MS) {
|
|
|
14711
14711
|
const message = isTimeout ? `${command} timed out after ${timeoutMs}ms` : failure.code === "ENOBUFS" ? `${command} output exceeded the ${formatSize(failure.maxBufferBytes ?? EXEC_OPTS.maxBuffer)} limit` : formatGitFailure(command, failure, err);
|
|
14712
14712
|
const wrapped = new Error(message);
|
|
14713
14713
|
wrapped.isGitTimeout = isTimeout;
|
|
14714
|
+
wrapped.gitExitStatus = failure.code || failure.signal ? void 0 : failure.status;
|
|
14714
14715
|
const stderr = outputToString(failure.stderr);
|
|
14715
14716
|
wrapped.gitStderr = stderr ? truncateOutput(stderr) : void 0;
|
|
14717
|
+
const stdout = outputToString(failure.stdout);
|
|
14718
|
+
wrapped.gitStdout = stdout ? truncateOutput(stdout) : void 0;
|
|
14716
14719
|
wrapped.isGitMissingObject = !isTimeout && failure.code !== "ENOBUFS" && matchesMissingObject(stderr);
|
|
14717
14720
|
return wrapped;
|
|
14718
14721
|
}
|
|
@@ -14751,25 +14754,64 @@ function isGitRepo(dir) {
|
|
|
14751
14754
|
return false;
|
|
14752
14755
|
}
|
|
14753
14756
|
}
|
|
14754
|
-
function
|
|
14755
|
-
|
|
14756
|
-
|
|
14757
|
-
|
|
14758
|
-
|
|
14759
|
-
|
|
14760
|
-
|
|
14761
|
-
if (sha) return sha;
|
|
14762
|
-
} catch (err) {
|
|
14763
|
-
if (isGitTimeoutError(err)) throw err;
|
|
14757
|
+
function stashRetryReason(failure) {
|
|
14758
|
+
const status = failure.gitExitStatus;
|
|
14759
|
+
if (status !== 1 && status !== 128) return null;
|
|
14760
|
+
if (/Unable to create [^\n]*index\.lock[^\n]*: File exists/.test(
|
|
14761
|
+
failure.gitStderr ?? ""
|
|
14762
|
+
)) {
|
|
14763
|
+
return "index-lock-contention";
|
|
14764
14764
|
}
|
|
14765
|
-
|
|
14766
|
-
return
|
|
14767
|
-
}
|
|
14768
|
-
|
|
14769
|
-
|
|
14770
|
-
|
|
14765
|
+
if (status === 1 && !failure.gitStderr && !failure.gitStdout) {
|
|
14766
|
+
return "empty-stash-failure";
|
|
14767
|
+
}
|
|
14768
|
+
return null;
|
|
14769
|
+
}
|
|
14770
|
+
function captureWorkingCommitSha(repoRoot) {
|
|
14771
|
+
for (let attempt = 1; ; attempt++) {
|
|
14772
|
+
let sha;
|
|
14773
|
+
try {
|
|
14774
|
+
sha = timeCaptureStage(
|
|
14775
|
+
repoRoot,
|
|
14776
|
+
"stash-create",
|
|
14777
|
+
() => (
|
|
14778
|
+
// Keep the two expected stderr classifications independent of locale.
|
|
14779
|
+
gitWithEnv(repoRoot, ["stash", "create"], {
|
|
14780
|
+
...process.env,
|
|
14781
|
+
LC_ALL: "C"
|
|
14782
|
+
})
|
|
14783
|
+
)
|
|
14784
|
+
);
|
|
14785
|
+
} catch (err) {
|
|
14786
|
+
const failure = err;
|
|
14787
|
+
const stderr = failure.gitStderr ?? "";
|
|
14788
|
+
if (failure.gitExitStatus === 1 && stderr.includes("You do not have the initial commit yet") && hasUnbornHead(repoRoot)) {
|
|
14789
|
+
appendLog(
|
|
14790
|
+
"info",
|
|
14791
|
+
`git-traces: stash create unavailable (repo=${repoRoot}, reason=unborn-head); capturing index tree`
|
|
14792
|
+
);
|
|
14793
|
+
const tree = git(repoRoot, ["write-tree"]);
|
|
14794
|
+
return git(repoRoot, ["commit-tree", tree, "-m", "empty baseline"]);
|
|
14795
|
+
}
|
|
14796
|
+
const retryReason = stashRetryReason(failure);
|
|
14797
|
+
if (!retryReason || attempt >= 5) throw err;
|
|
14798
|
+
appendLog(
|
|
14799
|
+
"warn",
|
|
14800
|
+
`git-traces: retrying stash create after ${retryReason === "index-lock-contention" ? "index lock contention" : "empty Git failure (possible index contention)"} (repo=${repoRoot}, attempt=${attempt}, maxAttempts=5, reason=${retryReason}): ${failure.message}`
|
|
14801
|
+
);
|
|
14802
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 250);
|
|
14803
|
+
continue;
|
|
14804
|
+
}
|
|
14805
|
+
return sha || git(repoRoot, ["rev-parse", "--verify", "HEAD"]);
|
|
14771
14806
|
}
|
|
14772
14807
|
}
|
|
14808
|
+
function hasUnbornHead(repoRoot) {
|
|
14809
|
+
const ref = git(repoRoot, ["symbolic-ref", "--quiet", "HEAD"]);
|
|
14810
|
+
const args = ["show-ref", "--verify", "--quiet", ref];
|
|
14811
|
+
const result = spawnSync("git", args, { cwd: repoRoot, ...EXEC_OPTS });
|
|
14812
|
+
if (result.error) throw createGitError(args, result.error);
|
|
14813
|
+
return result.status === 1;
|
|
14814
|
+
}
|
|
14773
14815
|
function captureBaselineSha(repoRoot) {
|
|
14774
14816
|
return captureWorkingCommitSha(repoRoot);
|
|
14775
14817
|
}
|
|
@@ -15040,39 +15082,53 @@ function filterOmittedFilesFromTree(repoRoot, treeSha, options = {}) {
|
|
|
15040
15082
|
}
|
|
15041
15083
|
function buildUntrackedTree(repoRoot, options = {}) {
|
|
15042
15084
|
const limits = options.limits ?? DEFAULT_SNAPSHOT_LIMITS;
|
|
15043
|
-
const list =
|
|
15044
|
-
|
|
15045
|
-
"
|
|
15046
|
-
"--exclude-standard",
|
|
15047
|
-
|
|
15048
|
-
]);
|
|
15049
|
-
if (!list) return null;
|
|
15085
|
+
const list = timeCaptureStage(
|
|
15086
|
+
repoRoot,
|
|
15087
|
+
"untracked-list",
|
|
15088
|
+
() => git(repoRoot, ["ls-files", "--others", "--exclude-standard", "-z"])
|
|
15089
|
+
);
|
|
15050
15090
|
const kept = [];
|
|
15051
|
-
|
|
15052
|
-
|
|
15053
|
-
|
|
15054
|
-
|
|
15055
|
-
|
|
15056
|
-
|
|
15057
|
-
|
|
15058
|
-
|
|
15059
|
-
|
|
15060
|
-
|
|
15061
|
-
|
|
15062
|
-
|
|
15063
|
-
|
|
15064
|
-
|
|
15065
|
-
|
|
15066
|
-
|
|
15067
|
-
|
|
15068
|
-
|
|
15069
|
-
|
|
15070
|
-
|
|
15091
|
+
let candidates = 0;
|
|
15092
|
+
let keptBytes = 0;
|
|
15093
|
+
let omitted = 0;
|
|
15094
|
+
let omittedBytes = 0;
|
|
15095
|
+
let skipped = 0;
|
|
15096
|
+
timeCaptureStage(repoRoot, "untracked-filter", () => {
|
|
15097
|
+
for (const relPath of list.split("\0")) {
|
|
15098
|
+
if (!relPath) continue;
|
|
15099
|
+
candidates++;
|
|
15100
|
+
try {
|
|
15101
|
+
const absPath = path14.join(repoRoot, relPath);
|
|
15102
|
+
const stat = fs14.lstatSync(absPath);
|
|
15103
|
+
const reason = classifyOmission(
|
|
15104
|
+
relPath,
|
|
15105
|
+
stat.size,
|
|
15106
|
+
() => readWorkingFileHead(absPath),
|
|
15107
|
+
limits,
|
|
15108
|
+
false
|
|
15109
|
+
);
|
|
15110
|
+
if (reason) {
|
|
15111
|
+
omitted++;
|
|
15112
|
+
omittedBytes += stat.size;
|
|
15113
|
+
options.omittedFiles?.push({
|
|
15114
|
+
path: relPath,
|
|
15115
|
+
sizeBytes: stat.size,
|
|
15116
|
+
tracked: false,
|
|
15117
|
+
reason
|
|
15118
|
+
});
|
|
15119
|
+
continue;
|
|
15120
|
+
}
|
|
15121
|
+
kept.push(relPath);
|
|
15122
|
+
keptBytes += stat.size;
|
|
15123
|
+
} catch {
|
|
15124
|
+
skipped++;
|
|
15071
15125
|
}
|
|
15072
|
-
kept.push(relPath);
|
|
15073
|
-
} catch {
|
|
15074
15126
|
}
|
|
15075
|
-
}
|
|
15127
|
+
});
|
|
15128
|
+
appendLog(
|
|
15129
|
+
"info",
|
|
15130
|
+
`git-traces: untracked inventory (repo=${repoRoot}, candidates=${candidates}, kept=${kept.length}, keptBytes=${keptBytes}, omitted=${omitted}, omittedBytes=${omittedBytes}, skipped=${skipped})`
|
|
15131
|
+
);
|
|
15076
15132
|
if (kept.length === 0) return null;
|
|
15077
15133
|
const tmpIndex = path14.join(
|
|
15078
15134
|
os7.tmpdir(),
|
|
@@ -15080,11 +15136,19 @@ function buildUntrackedTree(repoRoot, options = {}) {
|
|
|
15080
15136
|
);
|
|
15081
15137
|
const env = { ...process.env, GIT_INDEX_FILE: tmpIndex };
|
|
15082
15138
|
try {
|
|
15083
|
-
|
|
15084
|
-
|
|
15085
|
-
|
|
15086
|
-
|
|
15087
|
-
|
|
15139
|
+
timeCaptureStage(
|
|
15140
|
+
repoRoot,
|
|
15141
|
+
"untracked-hash-and-index",
|
|
15142
|
+
() => gitBuffer(repoRoot, ["update-index", "--add", "-z", "--stdin"], {
|
|
15143
|
+
input: `${kept.join("\0")}\0`,
|
|
15144
|
+
env
|
|
15145
|
+
})
|
|
15146
|
+
);
|
|
15147
|
+
return timeCaptureStage(
|
|
15148
|
+
repoRoot,
|
|
15149
|
+
"untracked-write-tree",
|
|
15150
|
+
() => gitWithEnv(repoRoot, ["write-tree"], env)
|
|
15151
|
+
);
|
|
15088
15152
|
} finally {
|
|
15089
15153
|
try {
|
|
15090
15154
|
fs14.unlinkSync(tmpIndex);
|
|
@@ -15139,26 +15203,48 @@ function mergeSnapshotTrees(repoRoot, filteredTrackedTree, untrackedTree) {
|
|
|
15139
15203
|
);
|
|
15140
15204
|
const env = { ...process.env, GIT_INDEX_FILE: tmpIndex };
|
|
15141
15205
|
try {
|
|
15142
|
-
|
|
15143
|
-
const untrackedList = gitBuffer(
|
|
15206
|
+
timeCaptureStage(
|
|
15144
15207
|
repoRoot,
|
|
15145
|
-
|
|
15146
|
-
|
|
15147
|
-
|
|
15148
|
-
|
|
15149
|
-
|
|
15150
|
-
|
|
15151
|
-
|
|
15152
|
-
|
|
15153
|
-
|
|
15154
|
-
|
|
15208
|
+
"assembly-read-tree",
|
|
15209
|
+
() => gitWithEnv(repoRoot, ["read-tree", filteredTrackedTree], env)
|
|
15210
|
+
);
|
|
15211
|
+
const untrackedList = timeCaptureStage(
|
|
15212
|
+
repoRoot,
|
|
15213
|
+
"assembly-list-untracked",
|
|
15214
|
+
() => gitBuffer(repoRoot, ["ls-tree", "-r", untrackedTree], { env }).toString(
|
|
15215
|
+
"utf-8"
|
|
15216
|
+
)
|
|
15217
|
+
);
|
|
15218
|
+
let overlayEntries = 0;
|
|
15219
|
+
const indexInfo = timeCaptureStage(
|
|
15220
|
+
repoRoot,
|
|
15221
|
+
"assembly-prepare-index",
|
|
15222
|
+
() => untrackedList.split("\n").filter(Boolean).map((line) => {
|
|
15223
|
+
const [meta, filePath] = line.split(" ");
|
|
15224
|
+
const [mode, , sha] = meta.split(/\s+/);
|
|
15225
|
+
overlayEntries++;
|
|
15226
|
+
return `${mode} ${sha} ${filePath}`;
|
|
15227
|
+
}).join("\n")
|
|
15228
|
+
);
|
|
15229
|
+
appendLog(
|
|
15230
|
+
"info",
|
|
15231
|
+
`git-traces: assembly inventory (repo=${repoRoot}, untrackedEntries=${overlayEntries})`
|
|
15232
|
+
);
|
|
15155
15233
|
if (indexInfo) {
|
|
15156
|
-
|
|
15157
|
-
|
|
15158
|
-
|
|
15159
|
-
|
|
15234
|
+
timeCaptureStage(
|
|
15235
|
+
repoRoot,
|
|
15236
|
+
"assembly-update-index",
|
|
15237
|
+
() => gitBuffer(repoRoot, ["update-index", "--index-info"], {
|
|
15238
|
+
input: indexInfo,
|
|
15239
|
+
env
|
|
15240
|
+
})
|
|
15241
|
+
);
|
|
15160
15242
|
}
|
|
15161
|
-
return
|
|
15243
|
+
return timeCaptureStage(
|
|
15244
|
+
repoRoot,
|
|
15245
|
+
"assembly-write-tree",
|
|
15246
|
+
() => gitWithEnv(repoRoot, ["write-tree"], env)
|
|
15247
|
+
);
|
|
15162
15248
|
} finally {
|
|
15163
15249
|
try {
|
|
15164
15250
|
fs14.unlinkSync(tmpIndex);
|