diff --git a/scripts/lib.js b/scripts/lib.js index 3ecca47..9380f47 100644 --- a/scripts/lib.js +++ b/scripts/lib.js @@ -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} 通過時回傳 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) {