feat(worktree-ensure): 定位工作包的工作樹,不在就重建
處理 PR 留言的人不必先手動 cd 到正確的目錄:路徑由 owner/repo/分支名 純函式推導, 問這一支就知道該在哪裡動手。 「不在就重建」是常態不是防禦性程式設計。進度完全不寫在本機——換一台機器或換一個 agent 接手時,工作樹本來就不存在,而重建的成本就是一次 git worktree add。 兩種情況明確中止而不是硬幹:分支在本機與遠端都不見時報 BRANCH_NOT_FOUND(憑空長一棵 空的工作樹只會讓人以為進度還在),推導出的路徑上是別的東西時報 WORKTREE_PATH_TAKEN。 議題 #42 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* 定位一顆工作包的工作樹,不在就重建。
|
||||
*
|
||||
* 處理 PR 留言的人不必先手動 `cd` 到正確的目錄:路徑由 `owner/repo/分支名` 純函式推導
|
||||
* (見 lib 的 `worktreePath`),問這一支就知道該在哪裡動手。
|
||||
*
|
||||
* **「不在就重建」是常態,不是防禦性程式設計。** 進度完全不寫在本機——換一台機器或
|
||||
* 換一個 agent 接手時,工作樹本來就不存在,而重建的成本就是一次 `git worktree add`。
|
||||
*
|
||||
* 重建與建立走同一套(lib 的 `planWorktree`/`createWorktree`):一樣先 `git fetch`
|
||||
* 更新遠端引用,一樣不設 upstream,分支已經存在就接上去而不是長一棵空的。兩邊各寫
|
||||
* 一份,遲早會在「起點取自哪裡」這種地方分岔,而那種分岔要等到有人的進度不見了
|
||||
* 才會被發現。
|
||||
*
|
||||
* 分支在本機與遠端都不存在時明確中止:憑空長一棵空的工作樹,只會讓人以為進度還在。
|
||||
* 推導出的路徑上是別的東西時也中止,不盲目拿來用。
|
||||
*
|
||||
* 用法:
|
||||
* node scripts/worktree-ensure.js --repo owner/name --branch <分支名>
|
||||
* [--path <目標專案>] [--dry-run]
|
||||
*/
|
||||
import {
|
||||
ScriptError,
|
||||
createWorktree,
|
||||
main,
|
||||
openGitRepo,
|
||||
parseFlags,
|
||||
parseRepo,
|
||||
planWorktree,
|
||||
worktreePath,
|
||||
} from './lib.js';
|
||||
|
||||
main(async () => {
|
||||
const flags = parseFlags(process.argv.slice(2), {
|
||||
required: ['repo', 'branch'],
|
||||
optional: ['path'],
|
||||
booleans: ['dry-run'],
|
||||
});
|
||||
const repo = parseRepo(flags.repo);
|
||||
const branch = flags.branch;
|
||||
const path = flags.path ?? process.cwd();
|
||||
const worktree = worktreePath(repo, branch);
|
||||
|
||||
const git = openGitRepo(path);
|
||||
if (!git('remote').split('\n').includes('origin')) {
|
||||
throw new ScriptError(
|
||||
'NO_ORIGIN',
|
||||
`${path} 沒有 origin 遠端;重建工作樹要先能讀到 origin/${branch},請先設定 origin`,
|
||||
);
|
||||
}
|
||||
|
||||
// 不給 source:這裡只重建既有分支的工作樹,沒有「從來源長一支新的」那條路,
|
||||
// 那是 branch-prep 的事——在這裡憑空開一支新分支,等於把 PR 的進度扔掉
|
||||
const plan = planWorktree(git, { branch, worktree });
|
||||
const 報告 = { path, repo, branch, worktree, 動作: plan.動作 };
|
||||
|
||||
if (flags['dry-run']) {
|
||||
return { dryRun: true, ...報告, commands: plan.commands.map((args) => `git ${args.join(' ')}`) };
|
||||
}
|
||||
|
||||
createWorktree(git, plan, { worktree, branch });
|
||||
|
||||
return { ...報告, 重建: plan.commands.length > 0 };
|
||||
});
|
||||
Reference in New Issue
Block a user