bonchi 0.2.0 → 0.3.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: f726dfa32881aaae2a225b30e26b3a31fe3bfa2714709a33738910c4a42d2daf
4
- data.tar.gz: 4ef9df6de06aecfc41d5bf69fe651114123bccb48b0fb9cc67ed8c26f1ab6bcb
3
+ metadata.gz: 137e1eebb563dfaf05a9e6928abeb3832ff8e6231f7e1b4ea176037b605b2489
4
+ data.tar.gz: 8f22938f47fbc5068cb0a40a02fd31c875b5cdc5b7e699b6049752060ec3accb
5
5
  SHA512:
6
- metadata.gz: 5388c61deec0daf249af8c2033772bf9c2b22d51a894b6cfb75f887d65d14c1bdf298d7e96d6c7513717b0d0676fcb0f5f5a7bf518227be3b380487afd8774f3
7
- data.tar.gz: 919fe02691d9f5b4c7ca3c2ac31c8cb365b6bb9533ac56470d2803d972881f3375ee3b72a64ecbb4e983e29898629d331f451808ee20b56e418df7d4ab91a671
6
+ metadata.gz: 47d60879e7c32a8e518c3719d78c6c952dcc850c9897f49e4da0b4370d3a3e07e2d1233cf4b15a8eaf257671eae02aad4fd7d89d40d5a86525b8bf6a3ab6157b
7
+ data.tar.gz: f6a8c72b294fd4c6e29dff35d20c085463e0411bab413971c934ca43b80b331caa095b726d1cace6305a9db20865a6ec3877de1cdaf89d9d98f3aa9bbef2b284
data/lib/bonchi/cli.rb CHANGED
@@ -183,7 +183,10 @@ module Bonchi
183
183
  end
184
184
  end
185
185
 
186
- WORKTREE_YML_TEMPLATE = <<~'YAML'
186
+ WORKTREE_YML_TEMPLATE = <<~YAML
187
+ # Worktree configuration for bonchi.
188
+ # See https://github.com/eval/bonchi
189
+
187
190
  # Files to copy from the main worktree before setup.
188
191
  # copy:
189
192
  # - .env.local
@@ -192,9 +195,21 @@ module Bonchi
192
195
  # ports:
193
196
  # - PORT
194
197
 
198
+ # Regex replacements in copied files. Env vars ($VAR) are expanded.
199
+ # Short form:
200
+ # replace:
201
+ # .env.local:
202
+ # - "^PORT=.*": "PORT=$PORT"
203
+ # Full form (with optional missing: warn, default: halt):
204
+ # replace:
205
+ # .env.local:
206
+ # - match: "^PORT=.*"
207
+ # with: "PORT=$PORT"
208
+ # missing: warn
209
+
195
210
  # Commands to run before the setup command (port env vars are available).
196
211
  # pre_setup:
197
- # - sed -i '' "s|^PORT=.*|PORT=$PORT|" .env.local
212
+ # - echo "preparing..."
198
213
 
199
214
  # The setup command to run (default: bin/setup).
200
215
  setup: bin/setup
@@ -0,0 +1,20 @@
1
+ module Bonchi
2
+ module Colors
3
+ private
4
+
5
+ def color(name)
6
+ return "" if ENV.key?("NO_COLOR")
7
+
8
+ case name
9
+ when :red then "\e[31m"
10
+ when :yellow then "\e[33m"
11
+ end
12
+ end
13
+
14
+ def reset
15
+ return "" if ENV.key?("NO_COLOR")
16
+
17
+ "\e[0m"
18
+ end
19
+ end
20
+ end
data/lib/bonchi/config.rb CHANGED
@@ -2,14 +2,25 @@ require "yaml"
2
2
 
3
3
  module Bonchi
4
4
  class Config
5
- attr_reader :copy, :ports, :pre_setup, :setup
5
+ include Colors
6
+
7
+ KNOWN_KEYS = %w[copy ports replace pre_setup setup].freeze
8
+
9
+ attr_reader :copy, :ports, :replace, :pre_setup, :setup
6
10
 
7
11
  def initialize(path)
8
12
  data = YAML.load_file(path)
13
+
14
+ unknown = data.keys - KNOWN_KEYS
15
+ unknown.each { |k| warn "#{color(:yellow)}Warning:#{reset} unknown key '#{k}' in .worktree.yml, ignoring" }
16
+
9
17
  @copy = Array(data["copy"])
10
18
  @ports = Array(data["ports"])
19
+ @replace = data["replace"] || {}
11
20
  @pre_setup = Array(data["pre_setup"])
12
21
  @setup = data["setup"] || "bin/setup"
22
+
23
+ validate!
13
24
  end
14
25
 
15
26
  def self.from_main_worktree
@@ -19,5 +30,29 @@ module Bonchi
19
30
 
20
31
  new(path)
21
32
  end
33
+
34
+ private
35
+
36
+ def validate!
37
+ unless @replace.is_a?(Hash)
38
+ abort "#{color(:red)}Error:#{reset} 'replace' must be a mapping of filename to list of replacements"
39
+ end
40
+
41
+ @replace.each do |file, entries|
42
+ unless entries.is_a?(Array)
43
+ abort "#{color(:red)}Error:#{reset} 'replace.#{file}' must be a list of replacements"
44
+ end
45
+
46
+ entries.each do |entry|
47
+ unless entry.is_a?(Hash)
48
+ abort "#{color(:red)}Error:#{reset} each replacement in 'replace.#{file}' must be a mapping"
49
+ end
50
+ end
51
+ end
52
+
53
+ unless @setup.is_a?(String)
54
+ abort "#{color(:red)}Error:#{reset} 'setup' must be a string"
55
+ end
56
+ end
22
57
  end
23
58
  end
data/lib/bonchi/git.rb CHANGED
@@ -4,6 +4,11 @@ module Bonchi
4
4
  module Git
5
5
  module_function
6
6
 
7
+ def current_branch(worktree = nil)
8
+ dir = worktree || Dir.pwd
9
+ `git -C #{dir.shellescape} rev-parse --abbrev-ref HEAD`.strip
10
+ end
11
+
7
12
  def repo_name
8
13
  url = `git remote get-url origin 2>/dev/null`.strip
9
14
  base = url.empty? ? `git rev-parse --show-toplevel`.strip : url
data/lib/bonchi/setup.rb CHANGED
@@ -3,6 +3,8 @@ require "shellwords"
3
3
 
4
4
  module Bonchi
5
5
  class Setup
6
+ include Colors
7
+
6
8
  def initialize(worktree: nil)
7
9
  @worktree = worktree || Dir.pwd
8
10
  @main_worktree = Git.main_worktree
@@ -10,19 +12,23 @@ module Bonchi
10
12
 
11
13
  def run(args = [])
12
14
  if @worktree == @main_worktree
13
- abort "Error: already in the main worktree"
15
+ abort "#{color(:red)}Error:#{reset} already in the main worktree"
14
16
  end
15
17
 
16
18
  config = Config.from_main_worktree
17
- abort "Error: .worktree.yml not found in main worktree" unless config
19
+ abort "#{color(:red)}Error:#{reset} .worktree.yml not found in main worktree" unless config
18
20
 
19
- ENV["MAIN_WORKTREE"] = @main_worktree
20
- ENV["WORKTREE"] = @worktree
21
+ ENV["WORKTREE_MAIN"] = @main_worktree
22
+ ENV["WORKTREE_LINKED"] = @worktree
23
+ ENV["WORKTREE_BRANCH"] = Git.current_branch(@worktree)
24
+ ENV["WORKTREE_BRANCH_SLUG"] = ENV["WORKTREE_BRANCH"].gsub(/[^a-zA-Z0-9_]/, "_")
25
+ ENV["WORKTREE_ROOT"] ||= GlobalConfig.new.worktree_root
21
26
 
22
27
  puts "Setting up worktree from: #{@main_worktree}"
23
28
 
24
29
  allocate_ports(config.ports) if config.ports.any?
25
30
  copy_files(config.copy)
31
+ replace_in_files(config.replace) if config.replace.any?
26
32
  run_pre_setup(config.pre_setup)
27
33
  exec_setup(config.setup, args)
28
34
  end
@@ -42,8 +48,45 @@ module Bonchi
42
48
  FileUtils.cp(src, File.join(@worktree, file))
43
49
  puts "Copied #{file}"
44
50
  else
45
- puts "Warning: #{file} not found in main worktree, skipping"
51
+ puts "#{color(:yellow)}Warning:#{reset} #{file} not found in main worktree, skipping"
52
+ end
53
+ end
54
+ end
55
+
56
+ def replace_in_files(replacements)
57
+ replacements.each do |file, entries|
58
+ path = File.join(@worktree, file)
59
+ abort "#{color(:red)}Error:#{reset} #{file} not found" unless File.exist?(path)
60
+
61
+ content = File.read(path)
62
+ entries.each do |entry|
63
+ if entry.is_a?(Hash) && entry.key?("match")
64
+ pattern = entry["match"]
65
+ replacement = entry["with"]
66
+ missing = entry["missing"] || "halt"
67
+ elsif entry.is_a?(Hash)
68
+ pattern, replacement = entry.first
69
+ missing = "halt"
70
+ else
71
+ abort "#{color(:red)}Error:#{reset} invalid replace entry in #{file}: #{entry.inspect}"
72
+ end
73
+
74
+ expanded = replacement.gsub(/\$(\w+)/) { ENV[$1] || abort("#{color(:red)}Error:#{reset} $#{$1} not set") }
75
+ regex = Regexp.new(pattern)
76
+
77
+ unless content.match?(regex)
78
+ if missing == "warn"
79
+ puts "#{color(:yellow)}Warning:#{reset} pattern #{pattern} not found in #{file}, skipping"
80
+ next
81
+ else
82
+ abort "#{color(:red)}Error:#{reset} pattern #{pattern} not found in #{file}"
83
+ end
84
+ end
85
+
86
+ content = content.gsub(regex, expanded)
87
+ puts "Replaced #{pattern} in #{file}"
46
88
  end
89
+ File.write(path, content)
47
90
  end
48
91
  end
49
92
 
@@ -1,3 +1,3 @@
1
1
  module Bonchi
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
data/lib/bonchi.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require_relative "bonchi/version"
2
+ require_relative "bonchi/colors"
2
3
  require_relative "bonchi/global_config"
3
4
  require_relative "bonchi/git"
4
5
  require_relative "bonchi/config"
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.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gert Goet
@@ -34,6 +34,7 @@ files:
34
34
  - exe/bonchi
35
35
  - lib/bonchi.rb
36
36
  - lib/bonchi/cli.rb
37
+ - lib/bonchi/colors.rb
37
38
  - lib/bonchi/config.rb
38
39
  - lib/bonchi/git.rb
39
40
  - lib/bonchi/global_config.rb