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