Module: Carson::Runtime::Housekeep
- Included in:
- Carson::Runtime
- Defined in:
- lib/carson/runtime/housekeep.rb
Instance Method Summary collapse
-
#housekeep!(json_output: false) ⇒ Object
Serves the current repo: sync + prune.
-
#housekeep_all!(json_output: false) ⇒ Object
Knocks each governed repo’s gate in turn.
-
#housekeep_target!(target:, json_output: false) ⇒ Object
Resolves a target name to a governed repo, then serves it.
-
#reap_dead_worktrees! ⇒ Object
Removes dead worktrees — those whose content is on main or with merged PR evidence.
Instance Method Details
#housekeep!(json_output: false) ⇒ Object
Serves the current repo: sync + prune.
13 14 15 |
# File 'lib/carson/runtime/housekeep.rb', line 13 def housekeep!( json_output: false ) housekeep_one( repo_path: repo_root, json_output: json_output ) end |
#housekeep_all!(json_output: false) ⇒ Object
Knocks each governed repo’s gate in turn.
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/carson/runtime/housekeep.rb', line 29 def housekeep_all!( json_output: false ) repos = config.govern_repos if repos.empty? result = { command: "housekeep", status: "error", error: "No governed repositories configured.", recovery: "Run carson onboard in each repo to register." } return housekeep_finish( result: result, exit_code: EXIT_ERROR, json_output: json_output ) end results = [] repos.each do |repo_path| entry = housekeep_one_entry( repo_path: repo_path, silent: json_output ) if entry[ :status ] == "ok" clear_batch_success( command: "housekeep", repo_path: repo_path ) else record_batch_skip( command: "housekeep", repo_path: repo_path, reason: entry[ :error ] || "housekeep failed" ) end results << entry end succeeded = results.count { it[ :status ] == "ok" } failed = results.count { it[ :status ] != "ok" } result = { command: "housekeep", status: failed.zero? ? "ok" : "partial", repos: results, succeeded: succeeded, failed: failed } housekeep_finish( result: result, exit_code: failed.zero? ? EXIT_OK : EXIT_ERROR, json_output: json_output, results: results, succeeded: succeeded, failed: failed ) end |
#housekeep_target!(target:, json_output: false) ⇒ Object
Resolves a target name to a governed repo, then serves it.
18 19 20 21 22 23 24 25 26 |
# File 'lib/carson/runtime/housekeep.rb', line 18 def housekeep_target!( target:, json_output: false ) repo_path = resolve_governed_repo( target: target ) unless repo_path result = { command: "housekeep", status: "error", error: "Not a governed repository: #{target}", recovery: "Run carson repos to see governed repositories." } return housekeep_finish( result: result, exit_code: EXIT_ERROR, json_output: json_output ) end housekeep_one( repo_path: repo_path, json_output: json_output ) end |
#reap_dead_worktrees! ⇒ Object
Removes dead worktrees — those whose content is on main or with merged PR evidence. Unblocks prune for the branches they hold. Two-layer dead check:
1. Content-absorbed: delegates to sweep_stale_worktrees! (shared, no gh needed).
2. Merged PR evidence: covers rebase/squash where main has since evolved
the same files (requires gh).
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/carson/runtime/housekeep.rb', line 59 def reap_dead_worktrees! # Layer 1: sweep agent-owned worktrees whose content is on main. sweep_stale_worktrees! # Layer 2: merged PR evidence for remaining worktrees. return unless gh_available? main_root = main_worktree_root worktree_list.each do |wt| path = wt.fetch( :path ) branch = wt.fetch( :branch, nil ) next if path == main_root next unless branch next if cwd_inside_worktree?( worktree_path: path ) # Missing directory: worktree was destroyed externally. # Prune the stale entry and delete the branch immediately. unless Dir.exist?( path ) git_run( "worktree", "prune" ) puts_verbose "reaped stale worktree entry: #{File.basename( path )} (branch: #{branch})" if !config.protected_branches.include?( branch ) git_run( "branch", "-D", branch ) puts_verbose "deleted branch: #{branch}" end next end tip_sha = git_capture!( "rev-parse", "--verify", branch ).strip rescue nil next unless tip_sha merged_pr, = merged_pr_for_branch( branch: branch, branch_tip_sha: tip_sha ) next if merged_pr.nil? # Remove the worktree (no --force: refuses if dirty working tree). _, _, rm_success, = git_run( "worktree", "remove", path ) next unless rm_success puts_verbose "reaped dead worktree: #{File.basename( path )} (branch: #{branch})" # Delete the local branch now that no worktree holds it. if !config.protected_branches.include?( branch ) git_run( "branch", "-D", branch ) puts_verbose "deleted branch: #{branch}" end end end |