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 +4 -4
- data/lib/bonchi/cli.rb +17 -2
- data/lib/bonchi/colors.rb +20 -0
- data/lib/bonchi/config.rb +36 -1
- data/lib/bonchi/git.rb +5 -0
- data/lib/bonchi/setup.rb +48 -5
- data/lib/bonchi/version.rb +1 -1
- data/lib/bonchi.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 137e1eebb563dfaf05a9e6928abeb3832ff8e6231f7e1b4ea176037b605b2489
|
|
4
|
+
data.tar.gz: 8f22938f47fbc5068cb0a40a02fd31c875b5cdc5b7e699b6049752060ec3accb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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 = <<~
|
|
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
|
-
# -
|
|
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
|
-
|
|
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
|
|
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
|
|
19
|
+
abort "#{color(:red)}Error:#{reset} .worktree.yml not found in main worktree" unless config
|
|
18
20
|
|
|
19
|
-
ENV["
|
|
20
|
-
ENV["
|
|
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
|
|
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
|
|
data/lib/bonchi/version.rb
CHANGED
data/lib/bonchi.rb
CHANGED
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.
|
|
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
|