UNPKG

@shutootaki/gwm

Version:
95 lines 3.05 kB
import { execAsync } from '../shell.js'; import { loadConfig } from '../../config.js'; import { getWorktreesWithStatus } from './worktree.js'; import { checkRemoteBranchStatus } from './remote.js'; /** * ワークツリーパスでローカル変更を確認 */ export async function checkLocalChanges(worktreePath) { let statusLines = []; try { const { stdout } = await execAsync('git status --porcelain', { cwd: worktreePath, encoding: 'utf8', }); statusLines = stdout.split('\n').filter((l) => l.trim() !== ''); } catch { // ignore, treat as no changes } let hasUnstagedChanges = false; let hasUntrackedFiles = false; let hasStagedChanges = false; statusLines.forEach((line) => { if (line.startsWith('??')) hasUntrackedFiles = true; else { const [x, y] = line.split(''); if (x && x !== ' ') hasStagedChanges = true; if (y && y !== ' ') hasUnstagedChanges = true; } }); // 未プッシュコミット let hasLocalCommits = false; try { // upstream が無い場合エラーになる await execAsync('git rev-parse --abbrev-ref --symbolic-full-name @{u}', { cwd: worktreePath, }); const { stdout: cherryOut } = await execAsync('git cherry -v', { cwd: worktreePath, encoding: 'utf8', }); if (cherryOut.trim().length > 0) hasLocalCommits = true; } catch { // upstreamが無い -> リモートに存在しない or 削除済み。未プッシュコミットは無視 hasLocalCommits = false; } return { hasUnstagedChanges, hasUntrackedFiles, hasStagedChanges, hasLocalCommits, }; } /** * ローカル変更があるかどうかを判定 */ function hasAnyLocalChanges(changes) { return (changes.hasLocalCommits || changes.hasStagedChanges || changes.hasUnstagedChanges || changes.hasUntrackedFiles); } /** * 削除可能なワークツリーを取得 */ export async function getCleanableWorktrees() { const config = loadConfig(); const worktrees = await getWorktreesWithStatus(); const results = []; for (const wt of worktrees) { // MAIN / ACTIVE を除外 if (wt.isMain || wt.isActive) continue; const { isDeleted, isMerged, mergedIntoBranch } = checkRemoteBranchStatus(wt.branch, config.main_branches); // 1. リモート削除 または マージ済み if (!isDeleted && !isMerged) continue; // 2. ローカル変更なし const local = await checkLocalChanges(wt.path); if (hasAnyLocalChanges(local)) continue; results.push({ worktree: wt, reason: isDeleted ? 'remote_deleted' : 'merged', mergedIntoBranch, }); } return results; } //# sourceMappingURL=clean.js.map