@akiojin/gwt 2.9.0 → 2.10.0
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/README.md +6 -0
- package/dist/cli/ui/components/App.d.ts.map +1 -1
- package/dist/cli/ui/components/App.js +10 -1
- package/dist/cli/ui/components/App.js.map +1 -1
- package/dist/cli/ui/types.d.ts +1 -1
- package/dist/cli/ui/types.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -11
- package/dist/index.js.map +1 -1
- package/dist/worktree.d.ts.map +1 -1
- package/dist/worktree.js +43 -23
- package/dist/worktree.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/ui/__tests__/components/App.protected-branch.test.tsx +67 -67
- package/src/cli/ui/__tests__/components/App.shortcuts.test.tsx +107 -130
- package/src/cli/ui/__tests__/components/App.test.tsx +102 -71
- package/src/cli/ui/__tests__/integration/edgeCases.test.tsx +57 -30
- package/src/cli/ui/components/App.tsx +16 -3
- package/src/cli/ui/types.ts +1 -1
- package/src/index.test.ts +1 -1
- package/src/index.ts +13 -12
- package/src/worktree.ts +54 -37
package/src/worktree.ts
CHANGED
|
@@ -100,11 +100,9 @@ async function listWorktrees(): Promise<WorktreeInfo[]> {
|
|
|
100
100
|
try {
|
|
101
101
|
const { getRepositoryRoot } = await import("./git.js");
|
|
102
102
|
const repoRoot = await getRepositoryRoot();
|
|
103
|
-
const { stdout } = await execa(
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
{ cwd: repoRoot },
|
|
107
|
-
);
|
|
103
|
+
const { stdout } = await execa("git", ["worktree", "list", "--porcelain"], {
|
|
104
|
+
cwd: repoRoot,
|
|
105
|
+
});
|
|
108
106
|
const worktrees: WorktreeInfo[] = [];
|
|
109
107
|
const lines = stdout.split("\n");
|
|
110
108
|
|
|
@@ -486,16 +484,14 @@ async function getOrphanedLocalBranches({
|
|
|
486
484
|
reasons.push("merged-pr");
|
|
487
485
|
}
|
|
488
486
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
);
|
|
487
|
+
const hasUniqueCommits = await branchHasUniqueCommitsComparedToBase(
|
|
488
|
+
localBranch.name,
|
|
489
|
+
baseBranch,
|
|
490
|
+
repoRoot,
|
|
491
|
+
);
|
|
495
492
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
}
|
|
493
|
+
if (!hasUniqueCommits) {
|
|
494
|
+
reasons.push("no-diff-with-base");
|
|
499
495
|
}
|
|
500
496
|
|
|
501
497
|
if (process.env.DEBUG_CLEANUP) {
|
|
@@ -506,14 +502,18 @@ async function getOrphanedLocalBranches({
|
|
|
506
502
|
);
|
|
507
503
|
}
|
|
508
504
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
505
|
+
let hasRemoteBranch = false;
|
|
506
|
+
try {
|
|
507
|
+
hasRemoteBranch = await checkRemoteBranchExists(localBranch.name);
|
|
508
|
+
} catch {
|
|
509
|
+
hasRemoteBranch = false;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
if (!hasUnpushed && hasRemoteBranch && hasUniqueCommits) {
|
|
513
|
+
reasons.push("remote-synced");
|
|
514
|
+
}
|
|
516
515
|
|
|
516
|
+
if (reasons.length > 0) {
|
|
517
517
|
cleanupTargets.push({
|
|
518
518
|
worktreePath: null, // worktreeは存在しない
|
|
519
519
|
branch: localBranch.name,
|
|
@@ -627,13 +627,19 @@ export async function getMergedPRWorktrees(): Promise<CleanupTarget[]> {
|
|
|
627
627
|
|
|
628
628
|
const cleanupReasons: CleanupReason[] = [];
|
|
629
629
|
|
|
630
|
-
if (mergedPR) {
|
|
631
|
-
cleanupReasons.push("merged-pr");
|
|
632
|
-
}
|
|
633
|
-
|
|
634
630
|
// worktreeパスの存在を確認
|
|
635
631
|
const fs = await import("node:fs");
|
|
636
|
-
|
|
632
|
+
// Some test environments mock node:fs without existsSync on the module root.
|
|
633
|
+
const existsSync =
|
|
634
|
+
typeof fs.existsSync === "function"
|
|
635
|
+
? fs.existsSync
|
|
636
|
+
: typeof (fs as { default?: { existsSync?: unknown } }).default
|
|
637
|
+
?.existsSync === "function"
|
|
638
|
+
? (fs as { default: { existsSync: (p: string) => boolean } }).default
|
|
639
|
+
.existsSync
|
|
640
|
+
: null;
|
|
641
|
+
|
|
642
|
+
const isAccessible = existsSync ? existsSync(worktree.worktreePath) : false;
|
|
637
643
|
|
|
638
644
|
let hasUncommitted = false;
|
|
639
645
|
let hasUnpushed = false;
|
|
@@ -657,16 +663,29 @@ export async function getMergedPRWorktrees(): Promise<CleanupTarget[]> {
|
|
|
657
663
|
}
|
|
658
664
|
}
|
|
659
665
|
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
+
let hasRemoteBranch = false;
|
|
667
|
+
try {
|
|
668
|
+
hasRemoteBranch = await checkRemoteBranchExists(worktree.branch);
|
|
669
|
+
} catch {
|
|
670
|
+
hasRemoteBranch = false;
|
|
671
|
+
}
|
|
666
672
|
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
673
|
+
if (mergedPR) {
|
|
674
|
+
cleanupReasons.push("merged-pr");
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
const hasUniqueCommits = await branchHasUniqueCommitsComparedToBase(
|
|
678
|
+
worktree.branch,
|
|
679
|
+
baseBranch,
|
|
680
|
+
repoRoot,
|
|
681
|
+
);
|
|
682
|
+
|
|
683
|
+
// 差分がない場合はベース同等としてクリーンアップ候補
|
|
684
|
+
if (!hasUniqueCommits) {
|
|
685
|
+
cleanupReasons.push("no-diff-with-base");
|
|
686
|
+
} else if (!hasUncommitted && !hasUnpushed && hasRemoteBranch) {
|
|
687
|
+
// 未マージでも、ローカルに未コミット/未プッシュがなくリモートが最新ならローカルのみクリーンアップ許可
|
|
688
|
+
cleanupReasons.push("remote-synced");
|
|
670
689
|
}
|
|
671
690
|
|
|
672
691
|
if (process.env.DEBUG_CLEANUP) {
|
|
@@ -681,8 +700,6 @@ export async function getMergedPRWorktrees(): Promise<CleanupTarget[]> {
|
|
|
681
700
|
continue;
|
|
682
701
|
}
|
|
683
702
|
|
|
684
|
-
const hasRemoteBranch = await checkRemoteBranchExists(worktree.branch);
|
|
685
|
-
|
|
686
703
|
const target: CleanupTarget = {
|
|
687
704
|
worktreePath: worktree.worktreePath,
|
|
688
705
|
branch: worktree.branch,
|