fix(lib): git 的進度訊息不再漏到 stderr,並讓前置檢查交回帳號
兩件都是 branch-prep 與 claim 落地時才浮現的既有缺口: git 把 checkout/fetch 的進度訊息全寫在 stderr,而 execFileSync 預設讓 stderr 直接 繼承給父行程。腳本的輸出契約是「stdout 一行 JSON、stderr 乾淨」,不收的話呼叫端還得 自己分辨哪幾行是雜訊。改成收進來;失敗時這些內容仍讀得到,錯誤訊息不會因此變模糊。 preflight 的第二層本來就打過 /user 問「我是誰」,卻只把答案丟掉,害呼叫端要再問一次。 改為連同 repo 資訊一起交回去。原本沒有任何呼叫端在用它的回傳值,形狀改變是安全的。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+14
-6
@@ -365,7 +365,14 @@ function safeJson(text) {
|
||||
*/
|
||||
export function runGit(args, { cwd } = {}) {
|
||||
try {
|
||||
return execFileSync('git', args, { cwd, encoding: 'utf8' }).trim();
|
||||
// stderr 要收進來而不是繼承:git 把 checkout/fetch 的進度訊息全寫在 stderr,
|
||||
// 不收的話它們會混進腳本的輸出,而腳本的契約是「stdout 一行 JSON、stderr 乾淨」。
|
||||
// 失敗時這些內容仍讀得到(error.stderr),錯誤訊息不會因此變模糊。
|
||||
return execFileSync('git', args, {
|
||||
cwd,
|
||||
encoding: 'utf8',
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
}).trim();
|
||||
} catch (error) {
|
||||
const detail = (error.stderr || error.message || '').toString().trim();
|
||||
throw new ScriptError('GIT_FAILED', `git ${args.join(' ')} 失敗:${detail}`);
|
||||
@@ -379,15 +386,16 @@ export function runGit(args, { cwd } = {}) {
|
||||
* 前一層沒過就不往下打,避免把一個設定問題報成四個。
|
||||
* @param {{base: string, token: string}} login
|
||||
* @param {string} repo owner/name
|
||||
* @returns {Promise<object>} 通過時回傳 repo 資訊,省下呼叫端再查一次
|
||||
* @returns {Promise<{repo: object, user: object}>} 通過時把查到的 repo 與帳號一起交回去,
|
||||
* 省下呼叫端再查一次——第二層本來就已經問過「我是誰」了
|
||||
*/
|
||||
export async function preflight(login, repo) {
|
||||
checkEnvironment();
|
||||
await checkLogin(login);
|
||||
const user = await checkLogin(login);
|
||||
const info = await fetchRepo(login, repo);
|
||||
await checkIssueWrite(login, repo, info);
|
||||
checkTimeTracker(info);
|
||||
return info;
|
||||
return { repo: info, user };
|
||||
}
|
||||
|
||||
/** 第一層:執行環境。node 由「正在執行」本身證明,git 與 tea 則實際到 PATH 上找。 */
|
||||
@@ -458,7 +466,7 @@ export function onPath(binary) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** 第二層:Gitea 登入是否有效 */
|
||||
/** 第二層:Gitea 登入是否有效。順手把帳號交出去,呼叫端常要知道「我是誰」。 */
|
||||
async function checkLogin(login) {
|
||||
const response = await giteaRequest(login, 'GET', '/user');
|
||||
if (response.status === 401 || response.status === 403) {
|
||||
@@ -467,7 +475,7 @@ async function checkLogin(login) {
|
||||
`Gitea 不接受目前的 token(HTTP ${response.status});請重新執行 tea login add 更新登入`,
|
||||
);
|
||||
}
|
||||
expectOk(response, 'GET /user');
|
||||
return expectOk(response, 'GET /user');
|
||||
}
|
||||
|
||||
async function fetchRepo(login, repo) {
|
||||
|
||||
Reference in New Issue
Block a user