bonchi 0.1.0 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2f1b9e3fb0df2276375aff9ca6d5f416fc2396602570c41d0a2f925f3528cdc1
4
- data.tar.gz: 23b137fbe286b1c8a2845348ae8bb30d1c9200851ed7eee0c99face39e3fb7b8
3
+ metadata.gz: f726dfa32881aaae2a225b30e26b3a31fe3bfa2714709a33738910c4a42d2daf
4
+ data.tar.gz: 4ef9df6de06aecfc41d5bf69fe651114123bccb48b0fb9cc67ed8c26f1ab6bcb
5
5
  SHA512:
6
- metadata.gz: 8f132bd0f26283c4bab9f506553882eee5685e77def350e76c537a180beb44f399fa8540d542ab5be06f85fc8579b1378dde351c887c8291f4cbdeeb9a08f7df
7
- data.tar.gz: 71b5b5c3fda5a36dfdce6bb3b16a12401b838663bf57f22e8fdf25193372db458e4598f98c2d09ddbc91882d4567b1fdba6d029cfceae96054ea0b179502cfee
6
+ metadata.gz: 5388c61deec0daf249af8c2033772bf9c2b22d51a894b6cfb75f887d65d14c1bdf298d7e96d6c7513717b0d0676fcb0f5f5a7bf518227be3b380487afd8774f3
7
+ data.tar.gz: 919fe02691d9f5b4c7ca3c2ac31c8cb365b6bb9533ac56470d2803d972881f3375ee3b72a64ecbb4e983e29898629d331f451808ee20b56e418df7d4ab91a671
data/lib/bonchi/cli.rb CHANGED
@@ -14,6 +14,13 @@ module Bonchi
14
14
  map "-v" => :version
15
15
 
16
16
  desc "create BRANCH [BASE]", "Create new branch + worktree"
17
+ long_desc <<~DESC
18
+ Create a new branch and worktree. BASE defaults to the repository's default branch
19
+ (e.g. main). If a worktree for BRANCH already exists, switches to it instead.
20
+
21
+ When a .worktree.yml exists in the main worktree, setup runs automatically
22
+ (copy files, allocate ports, run pre_setup and setup commands). Skip with --no-setup.
23
+ DESC
17
24
  option :setup, type: :boolean, default: true, desc: "Run setup after creating worktree"
18
25
  def create(branch, base = nil)
19
26
  base ||= Git.default_base_branch
@@ -22,27 +29,34 @@ module Bonchi
22
29
  existing = Git.worktree_path_for(branch)
23
30
  if existing
24
31
  puts "Worktree already exists: #{existing}"
25
- puts "BONCHI_CD:#{existing}"
32
+ signal_cd(existing)
26
33
  return
27
34
  end
28
35
 
29
36
  Git.worktree_add_new_branch(path, branch, base)
30
37
  puts "Worktree created at: #{path}"
31
38
 
39
+ signal_cd(path)
40
+
32
41
  if options[:setup] && Config.from_main_worktree
33
42
  puts ""
34
43
  Setup.new(worktree: path).run
35
- else
36
- puts "BONCHI_CD:#{path}"
37
44
  end
38
45
  end
39
46
 
40
47
  desc "switch BRANCH", "Switch to existing branch in worktree"
48
+ long_desc <<~DESC
49
+ Create a worktree for an existing branch and cd into it.
50
+ If a worktree for BRANCH already exists, switches to it instead.
51
+
52
+ The branch must already exist locally or on the remote.
53
+ To create a new branch, use `bonchi create` instead.
54
+ DESC
41
55
  def switch(branch)
42
56
  existing = Git.worktree_path_for(branch)
43
57
  if existing
44
58
  puts "Worktree already exists: #{existing}"
45
- puts "BONCHI_CD:#{existing}"
59
+ signal_cd(existing)
46
60
  return
47
61
  end
48
62
 
@@ -54,10 +68,17 @@ module Bonchi
54
68
  Git.worktree_add(path, branch)
55
69
  puts "Worktree created at: #{path}"
56
70
 
57
- puts "BONCHI_CD:#{path}"
71
+ signal_cd(path)
58
72
  end
59
73
 
60
74
  desc "pr NUMBER_OR_URL", "Checkout GitHub PR in worktree"
75
+ long_desc <<~DESC
76
+ Fetch a GitHub pull request and check it out in a new worktree.
77
+ Accepts a PR number (e.g. 123) or a full GitHub PR URL.
78
+
79
+ The worktree branch will be named pr-<number>.
80
+ If the worktree already exists, switches to it instead.
81
+ DESC
61
82
  def pr(input)
62
83
  pr_number = extract_pr_number(input)
63
84
  branch = "pr-#{pr_number}"
@@ -66,7 +87,7 @@ module Bonchi
66
87
  existing = Git.worktree_path_for(branch)
67
88
  if existing
68
89
  puts "Worktree already exists: #{existing}"
69
- puts "BONCHI_CD:#{existing}"
90
+ signal_cd(existing)
70
91
  return
71
92
  end
72
93
 
@@ -74,12 +95,28 @@ module Bonchi
74
95
  Git.worktree_add(path, branch)
75
96
  puts "PR ##{pr_number} checked out at: #{path}"
76
97
 
77
- puts "BONCHI_CD:#{path}"
98
+ signal_cd(path)
78
99
  end
79
100
 
80
- desc "setup", "Run setup in current worktree (ports, copy, pre_setup, setup cmd)"
81
- def setup
82
- Setup.new.run
101
+ desc "init", "Generate a .worktree.yml in the current project"
102
+ long_desc <<~DESC
103
+ Generate a .worktree.yml config file in the current directory with
104
+ sensible defaults. Edit the file to customize which files to copy,
105
+ which ports to allocate, and what setup command to run.
106
+ DESC
107
+ def init
108
+ path = File.join(Dir.pwd, ".worktree.yml")
109
+ if File.exist?(path)
110
+ abort "Error: .worktree.yml already exists"
111
+ end
112
+
113
+ File.write(path, WORKTREE_YML_TEMPLATE)
114
+ puts "Created #{path}"
115
+ end
116
+
117
+ desc "setup [-- ARGS...]", "Run setup in current worktree (ports, copy, pre_setup, setup cmd)"
118
+ def setup(*args)
119
+ Setup.new.run(args)
83
120
  end
84
121
 
85
122
  desc "list", "List all worktrees"
@@ -88,6 +125,12 @@ module Bonchi
88
125
  end
89
126
 
90
127
  desc "remove BRANCH", "Remove a worktree"
128
+ long_desc <<~DESC
129
+ Remove a worktree and its directory. Refuses to remove worktrees
130
+ with uncommitted changes or untracked files (use `git worktree remove --force` to override).
131
+
132
+ Aliases: rm
133
+ DESC
91
134
  def remove(branch)
92
135
  path = Git.worktree_path_for(branch)
93
136
  abort "Error: No worktree found for branch: #{branch}" unless path
@@ -97,6 +140,13 @@ module Bonchi
97
140
  end
98
141
 
99
142
  desc "prune", "Prune stale worktree admin files"
143
+ long_desc <<~DESC
144
+ Clean up stale worktree tracking data. Git internally tracks worktrees in
145
+ .git/worktrees/. When a worktree directory is deleted manually (e.g. rm -rf)
146
+ instead of via `bonchi remove`, the tracking data becomes stale.
147
+
148
+ This runs `git worktree prune` to remove those orphaned entries.
149
+ DESC
100
150
  def prune
101
151
  Git.worktree_prune
102
152
  puts "Pruned stale worktree administrative files"
@@ -113,6 +163,15 @@ module Bonchi
113
163
 
114
164
  private
115
165
 
166
+ def signal_cd(path)
167
+ cd_file = ENV["BONCHI_CD_FILE"]
168
+ if cd_file
169
+ File.write(cd_file, path)
170
+ else
171
+ puts "cd #{path}"
172
+ end
173
+ end
174
+
116
175
  def extract_pr_number(input)
117
176
  case input
118
177
  when %r{^https://github.com/.*/pull/(\d+)}
@@ -124,15 +183,31 @@ module Bonchi
124
183
  end
125
184
  end
126
185
 
186
+ WORKTREE_YML_TEMPLATE = <<~'YAML'
187
+ # Files to copy from the main worktree before setup.
188
+ # copy:
189
+ # - .env.local
190
+
191
+ # Env var names to allocate unique ports for (from global pool).
192
+ # ports:
193
+ # - PORT
194
+
195
+ # Commands to run before the setup command (port env vars are available).
196
+ # pre_setup:
197
+ # - sed -i '' "s|^PORT=.*|PORT=$PORT|" .env.local
198
+
199
+ # The setup command to run (default: bin/setup).
200
+ setup: bin/setup
201
+ YAML
202
+
127
203
  SHELL_ENV = <<~'SHELL'
128
204
  bonchi() {
129
- local output
130
- output=$(command bonchi "$@")
205
+ local bonchi_cd_file="${TMPDIR:-/tmp}/bonchi_cd.$$"
206
+ BONCHI_CD_FILE="$bonchi_cd_file" command bonchi "$@"
131
207
  local exit_code=$?
132
- echo "$output"
133
- if [ $exit_code -eq 0 ]; then
134
- local cd_path=$(echo "$output" | grep "^BONCHI_CD:" | cut -d: -f2-)
135
- [ -n "$cd_path" ] && cd "$cd_path"
208
+ if [ $exit_code -eq 0 ] && [ -f "$bonchi_cd_file" ]; then
209
+ cd "$(cat "$bonchi_cd_file")"
210
+ rm -f "$bonchi_cd_file"
136
211
  fi
137
212
  return $exit_code
138
213
  }
@@ -1,3 +1,3 @@
1
1
  module Bonchi
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bonchi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gert Goet
@@ -51,7 +51,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '3.3'
54
+ version: '3.1'
55
55
  required_rubygems_version: !ruby/object:Gem::Requirement
56
56
  requirements:
57
57
  - - ">="