carson 3.15.0 → 3.15.1
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.
- checksums.yaml +4 -4
- data/RELEASE.md +9 -0
- data/VERSION +1 -1
- data/lib/carson/runtime/housekeep.rb +50 -2
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b350c2bb611f2357a7ea9a422b8c1c836f551dc22a33c6ed70c9f0409425d208
|
|
4
|
+
data.tar.gz: 1333080091cb8e945df2c22e3349b4445124dc4ee856dd10de7b557a284c94df
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ba0030df2fde050f0fdd971970b4fe0c4053cad7d293076e6f11c6262feb012a7d7466a547a8812f4befbd6364bfed64e06af4308ab84a802611a3c15e16ee57
|
|
7
|
+
data.tar.gz: ca7d8bab1f94b3981d224d00aeedc388beba5c33f04f54494f5b9ef91e3f693b41440462a298e8c06146773b628a003d9b203ec2d0b3c06918502bfd961056f6
|
data/RELEASE.md
CHANGED
|
@@ -5,6 +5,15 @@ Release-note scope rule:
|
|
|
5
5
|
- `RELEASE.md` records only version deltas, breaking changes, and migration actions.
|
|
6
6
|
- Operational usage guides live in `MANUAL.md` and `API.md`.
|
|
7
7
|
|
|
8
|
+
## 3.15.1
|
|
9
|
+
|
|
10
|
+
### What changed
|
|
11
|
+
|
|
12
|
+
- **Dead worktree reaping** — `housekeep` now reaps dead worktrees before pruning. Unblocks prune for branches held by stale worktrees.
|
|
13
|
+
- Two-layer dead check: fast content-absorbed test, then definitive merged-PR evidence via GitHub API. Covers simple merges and rebase/squash cases where main has evolved.
|
|
14
|
+
- Safe removal only — refuses dirty working trees (`git worktree remove` without `--force`).
|
|
15
|
+
- Deletes the local branch after removal (unless protected).
|
|
16
|
+
|
|
8
17
|
## 3.15.0
|
|
9
18
|
|
|
10
19
|
### What changed
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.15.
|
|
1
|
+
3.15.1
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
# Housekeeping — sync
|
|
1
|
+
# Housekeeping — sync, reap dead worktrees, and prune for a repository.
|
|
2
2
|
# carson housekeep <repo> — serve one repo by name or path.
|
|
3
3
|
# carson housekeep — serve the repo you are standing in.
|
|
4
4
|
# carson housekeep --all — serve all governed repos.
|
|
5
5
|
require "json"
|
|
6
|
+
require "open3"
|
|
6
7
|
require "stringio"
|
|
7
8
|
|
|
8
9
|
module Carson
|
|
@@ -41,6 +42,50 @@ module Carson
|
|
|
41
42
|
housekeep_finish( result: result, exit_code: failed.zero? ? EXIT_OK : EXIT_ERROR, json_output: json_output, results: results, succeeded: succeeded, failed: failed )
|
|
42
43
|
end
|
|
43
44
|
|
|
45
|
+
# Removes dead worktrees — those with a merged PR and a clean working tree.
|
|
46
|
+
# Unblocks prune for the branches they hold.
|
|
47
|
+
# Two-layer dead check:
|
|
48
|
+
# 1. Fast: branch content is fully absorbed into main (covers simple cases).
|
|
49
|
+
# 2. Definitive: a merged PR exists for this branch (covers rebase/squash where
|
|
50
|
+
# main has since evolved the same files).
|
|
51
|
+
def reap_dead_worktrees!
|
|
52
|
+
return unless gh_available?
|
|
53
|
+
|
|
54
|
+
main_root = main_worktree_root
|
|
55
|
+
worktrees = worktree_list
|
|
56
|
+
|
|
57
|
+
worktrees.each do |wt|
|
|
58
|
+
path = wt.fetch( :path )
|
|
59
|
+
branch = wt.fetch( :branch, nil )
|
|
60
|
+
next if path == main_root
|
|
61
|
+
next unless branch
|
|
62
|
+
next if cwd_inside_worktree?( worktree_path: path )
|
|
63
|
+
|
|
64
|
+
# Dead check: absorbed into main, or merged PR evidence.
|
|
65
|
+
dead = branch_absorbed_into_main?( branch: branch )
|
|
66
|
+
unless dead
|
|
67
|
+
tip_sha = git_capture!( "rev-parse", "--verify", branch ).strip rescue nil
|
|
68
|
+
if tip_sha
|
|
69
|
+
merged_pr, = merged_pr_for_branch( branch: branch, branch_tip_sha: tip_sha )
|
|
70
|
+
dead = !merged_pr.nil?
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
next unless dead
|
|
74
|
+
|
|
75
|
+
# Remove the worktree (no --force: refuses if dirty working tree).
|
|
76
|
+
_, _, rm_success, = git_run( "worktree", "remove", path )
|
|
77
|
+
next unless rm_success
|
|
78
|
+
|
|
79
|
+
puts_verbose "reaped dead worktree: #{File.basename( path )} (branch: #{branch})"
|
|
80
|
+
|
|
81
|
+
# Delete the local branch now that no worktree holds it.
|
|
82
|
+
if !config.protected_branches.include?( branch )
|
|
83
|
+
git_run( "branch", "-D", branch )
|
|
84
|
+
puts_verbose "deleted branch: #{branch}"
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
44
89
|
private
|
|
45
90
|
|
|
46
91
|
# Runs sync + prune on one repo and returns the exit code directly.
|
|
@@ -64,7 +109,10 @@ module Carson
|
|
|
64
109
|
rt = Runtime.new( repo_root: repo_path, tool_root: tool_root, out: buf, err: err_buf, verbose: verbose? )
|
|
65
110
|
|
|
66
111
|
sync_status = rt.sync!
|
|
67
|
-
|
|
112
|
+
if sync_status == EXIT_OK
|
|
113
|
+
rt.reap_dead_worktrees!
|
|
114
|
+
prune_status = rt.prune!
|
|
115
|
+
end
|
|
68
116
|
|
|
69
117
|
ok = sync_status == EXIT_OK && prune_status == EXIT_OK
|
|
70
118
|
unless verbose? || silent
|