fix: withAskpass 等待非同步 callback 完成才清理 askpass 腳本
commitAndPush 傳入 async callback,但 withAskpass 是同步 try/finally, 會在第一個 await(LLM 合併指令檔)時就刪除 .git-askpass.sh,導致後續 git push 因 GIT_ASKPASS 指向已刪除腳本而失敗(cannot exec .git-askpass.sh / could not read Username)。前置驗證的 verifyRemoteAccess 用同步 callback 所以 ls-remote 通過,造成前置驗證過但 push 失敗的落差。 改為當 callback 回傳 thenable 時以 result.finally(cleanup) 延後清理, 同步 callback 維持立即清理與原樣回傳,不影響 verifyRemoteAccess / cloneRepo。 新增回歸測試斷言 git push 執行當下 askpass 腳本仍存在。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+14
-3
@@ -62,11 +62,22 @@ function withAskpass(workspace, fn) {
|
||||
const askpassScript = path.join(workspace, '.git-askpass.sh');
|
||||
fs.writeFileSync(askpassScript, '#!/bin/sh\necho "$GIT_TOKEN"\n', { mode: 0o700 });
|
||||
const credEnv = { ...process.env, GIT_ASKPASS: askpassScript, GIT_USERNAME: 'x-token', GIT_TOKEN: GITEA_TOKEN };
|
||||
const cleanup = () => { try { fs.unlinkSync(askpassScript); } catch {} };
|
||||
let result;
|
||||
try {
|
||||
return fn(credEnv);
|
||||
} finally {
|
||||
try { fs.unlinkSync(askpassScript); } catch {}
|
||||
result = fn(credEnv);
|
||||
} catch (e) {
|
||||
cleanup();
|
||||
throw e;
|
||||
}
|
||||
// Defer cleanup until an async callback settles, otherwise the askpass script
|
||||
// is deleted at the first `await` and later network ops (e.g. git push) fail
|
||||
// with "cannot exec .git-askpass.sh". Sync callbacks clean up immediately.
|
||||
if (result && typeof result.then === 'function') {
|
||||
return result.finally(cleanup);
|
||||
}
|
||||
cleanup();
|
||||
return result;
|
||||
}
|
||||
|
||||
function readGitOutput(run, args, cwd, env) {
|
||||
|
||||
Reference in New Issue
Block a user