planter-cli 0.0.3 → 0.0.4
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/.gitignore +2 -1
- data/.rubocop.yml +4 -6
- data/Rakefile +2 -2
- data/bin/plant +6 -0
- data/lib/planter/array.rb +34 -0
- data/lib/planter/color.rb +1 -1
- data/lib/planter/errors.rb +14 -0
- data/lib/planter/file.rb +87 -4
- data/lib/planter/filelist.rb +35 -7
- data/lib/planter/hash.rb +65 -84
- data/lib/planter/plant.rb +2 -10
- data/lib/planter/prompt.rb +6 -3
- data/lib/planter/script.rb +24 -12
- data/lib/planter/string.rb +134 -29
- data/lib/planter/version.rb +1 -1
- data/lib/planter.rb +56 -33
- data/spec/config.yml +2 -0
- data/spec/planter/array_spec.rb +28 -0
- data/spec/planter/file_entry_spec.rb +40 -0
- data/spec/planter/file_spec.rb +19 -0
- data/spec/planter/filelist_spec.rb +15 -0
- data/spec/planter/hash_spec.rb +83 -0
- data/spec/planter/plant_spec.rb +1 -0
- data/spec/planter/script_spec.rb +80 -0
- data/spec/planter/string_spec.rb +215 -2
- data/spec/planter/symbol_spec.rb +23 -0
- data/spec/planter.yml +6 -0
- data/spec/planter_spec.rb +67 -0
- data/spec/scripts/test.sh +3 -0
- data/spec/scripts/test_fail.sh +3 -0
- data/spec/spec_helper.rb +8 -2
- data/spec/templates/test/_planter.yml +12 -0
- data/spec/templates/test/_scripts/test.sh +3 -0
- data/spec/templates/test/_scripts/test_fail.sh +3 -0
- data/spec/test_out/image.png +0 -0
- data/spec/test_out/test2.rb +5 -0
- data/src/_README.md +13 -1
- metadata +37 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5318772de94f6948e72fcf61709d9b0cf42c3518a775e47eaa816e8d432cf0f0
|
4
|
+
data.tar.gz: fcc04239c8d4c74af78f7da138d862f3a01ee053740cda5ad28e8e1019c11a29
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 55fd5cdd6bbede37bd171df3c6686fc4ca14c869895cf122f7a38997b46121516e32342ab7f8625b26762fba668cd73611c0edeac101fdf3d2d6ec325460dbfa
|
7
|
+
data.tar.gz: 865480b6ed5efda83cba2b0314bf1afd685eed88c2c930e6b705e4fb104da3fadc0afd85211ea2a4930370d0c786df342a6dbf7c4f0ab371b9122f6df895150b
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -23,10 +23,6 @@ Style/MutableConstant:
|
|
23
23
|
Style/SpecialGlobalVars:
|
24
24
|
Enabled: false
|
25
25
|
|
26
|
-
Security/YAMLLoad:
|
27
|
-
Exclude:
|
28
|
-
- 'lib/**/*.rb'
|
29
|
-
|
30
26
|
Style/StringLiterals:
|
31
27
|
Enabled: true
|
32
28
|
EnforcedStyle: single_quotes
|
@@ -67,8 +63,7 @@ Metrics/ModuleLength:
|
|
67
63
|
Max: 174
|
68
64
|
|
69
65
|
Security/YAMLLoad:
|
70
|
-
|
71
|
-
- '**/*.rb'
|
66
|
+
Enabled: false
|
72
67
|
|
73
68
|
Style/ModuleFunction:
|
74
69
|
Exclude:
|
@@ -76,3 +71,6 @@ Style/ModuleFunction:
|
|
76
71
|
|
77
72
|
Style/RaiseArgs:
|
78
73
|
EnforcedStyle: compact
|
74
|
+
|
75
|
+
Style/SlicingWithRange:
|
76
|
+
Enabled: false
|
data/Rakefile
CHANGED
@@ -107,10 +107,10 @@ task :dockertest, :version, :login, :attempt do |_, args|
|
|
107
107
|
dir_args = dirs.map { |s, d| " -v '#{s}:#{d}'" }.join(' ')
|
108
108
|
exec "docker run #{dir_args} -it #{img} /bin/bash -l" if args[:login]
|
109
109
|
|
110
|
-
spinner = TTY::Spinner.new("[:spinner] Running tests (#{
|
110
|
+
spinner = TTY::Spinner.new("[:spinner] Running tests (#{version})...", hide_cursor: true)
|
111
111
|
|
112
112
|
spinner.auto_spin
|
113
|
-
|
113
|
+
`docker run --rm #{dir_args} -it #{img}`
|
114
114
|
# raise DockerError.new('Error running docker image') unless $?.success?
|
115
115
|
|
116
116
|
# commit = puts `bash -c "docker commit $(docker ps -a|grep #{img}|awk '{print $1}'|head -n 1) #{img}"`.strip
|
data/bin/plant
CHANGED
@@ -22,6 +22,7 @@ options = {
|
|
22
22
|
# min: 1
|
23
23
|
# max: 5
|
24
24
|
Planter.variables = {}
|
25
|
+
Planter.base_dir = ENV['PLANTER_DIR'] || File.expand_path('~/.config/planter')
|
25
26
|
Planter::Color.coloring = $stdout.isatty
|
26
27
|
|
27
28
|
opts = OptionParser.new
|
@@ -53,6 +54,10 @@ opts.on('-o', '--overwrite', 'Overwrite existing files') do
|
|
53
54
|
Planter.overwrite = true
|
54
55
|
end
|
55
56
|
|
57
|
+
opts.on_tail('--base-dir', 'Use an alternate base directory for config and templates') do |opt|
|
58
|
+
Planter.base_dir = opt
|
59
|
+
end
|
60
|
+
|
56
61
|
opts.on_tail('-d', '--debug', 'Display version number') do
|
57
62
|
Planter.debug = true
|
58
63
|
end
|
@@ -100,6 +105,7 @@ elsif ARGV.count.zero?
|
|
100
105
|
end
|
101
106
|
|
102
107
|
ARGV.each do |template|
|
108
|
+
Planter.spinner.update(title: 'Initializing configuration')
|
103
109
|
Planter.config = template
|
104
110
|
app = Planter::Plant.new
|
105
111
|
app.plant
|
data/lib/planter/array.rb
CHANGED
@@ -24,5 +24,39 @@ module Planter
|
|
24
24
|
end.join('{dw}/')
|
25
25
|
out << '{dw}]{x}'
|
26
26
|
end
|
27
|
+
|
28
|
+
##
|
29
|
+
## Stringify keys in an array of hashes or arrays
|
30
|
+
##
|
31
|
+
## @return [Array] Array with nested hash keys stringified
|
32
|
+
##
|
33
|
+
def stringify_keys
|
34
|
+
each_with_object([]) do |v, arr|
|
35
|
+
arr << if v.is_a?(Hash)
|
36
|
+
v.stringify_keys
|
37
|
+
elsif v.is_a?(Array)
|
38
|
+
v.map { |x| x.is_a?(Hash) || x.is_a?(Array) ? x.stringify_keys : x }
|
39
|
+
else
|
40
|
+
v
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
##
|
46
|
+
## Symbolize keys in an array of hashes or arrays
|
47
|
+
##
|
48
|
+
## @return [Array] Array with nested hash keys symbolized
|
49
|
+
##
|
50
|
+
def symbolize_keys
|
51
|
+
each_with_object([]) do |v, arr|
|
52
|
+
arr << if v.is_a?(Hash)
|
53
|
+
v.symbolize_keys
|
54
|
+
elsif v.is_a?(Array)
|
55
|
+
v.map { |x| x.is_a?(Hash) || x.is_a?(Array) ? x.symbolize_keys : x }
|
56
|
+
else
|
57
|
+
v
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
27
61
|
end
|
28
62
|
end
|
data/lib/planter/color.rb
CHANGED
data/lib/planter/errors.rb
CHANGED
@@ -7,6 +7,7 @@ module Planter
|
|
7
7
|
EXIT_CODES = {
|
8
8
|
argument: 12,
|
9
9
|
canceled: 1,
|
10
|
+
script: 10,
|
10
11
|
config: 127,
|
11
12
|
git: 129
|
12
13
|
}.deep_freeze
|
@@ -55,5 +56,18 @@ module Planter
|
|
55
56
|
super(msg)
|
56
57
|
end
|
57
58
|
end
|
59
|
+
|
60
|
+
#
|
61
|
+
# Script error
|
62
|
+
#
|
63
|
+
class ScriptError < StandardError
|
64
|
+
def initialize(msg = nil)
|
65
|
+
msg = msg ? "Script: #{msg}" : 'Script error'
|
66
|
+
Planter.spinner.error('(Error)')
|
67
|
+
Planter.notify(msg, :error, exit_code: EXIT_CODES[:script])
|
68
|
+
|
69
|
+
super(msg)
|
70
|
+
end
|
71
|
+
end
|
58
72
|
end
|
59
73
|
end
|
data/lib/planter/file.rb
CHANGED
@@ -2,10 +2,93 @@
|
|
2
2
|
|
3
3
|
# Main module
|
4
4
|
module Planter
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
# File helpers
|
6
|
+
class ::File
|
7
|
+
#
|
8
|
+
# Test if file is text
|
9
|
+
#
|
10
|
+
# @param name [String] file path
|
11
|
+
#
|
12
|
+
# @return [Boolean] File is text
|
13
|
+
#
|
14
|
+
def self.text?(name)
|
15
|
+
!binary?(name)
|
16
|
+
end
|
17
|
+
|
18
|
+
#
|
19
|
+
# Test if file is binary
|
20
|
+
#
|
21
|
+
# @param name [String] File path
|
22
|
+
#
|
23
|
+
# @return [Boolean] file is binary
|
24
|
+
#
|
25
|
+
def self.binary?(name)
|
26
|
+
return true if name.nil? || name.empty? || !File.exist?(name)
|
27
|
+
|
28
|
+
ascii = control = binary = 0
|
29
|
+
|
30
|
+
bytes = File.open(name, 'rb') { |io| io.read(1024) }
|
31
|
+
return true if bytes.nil? || bytes.empty?
|
32
|
+
|
33
|
+
bytes.each_byte do |bt|
|
34
|
+
case bt
|
35
|
+
when 0...32
|
36
|
+
control += 1
|
37
|
+
when 32...128
|
38
|
+
ascii += 1
|
39
|
+
else
|
40
|
+
binary += 1
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
first_test = binary.to_f / ascii > 0.05
|
45
|
+
|
46
|
+
first_test || second_test(name)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Allowable text file types
|
50
|
+
TEXT_TYPES = %w[text ansi xml json yaml csv empty].freeze
|
51
|
+
|
52
|
+
#
|
53
|
+
# Secondary test with file command
|
54
|
+
#
|
55
|
+
# @param name [String] file path
|
56
|
+
#
|
57
|
+
# @return [Boolean] file is binary according to file command
|
58
|
+
#
|
59
|
+
def self.second_test(name)
|
60
|
+
if TTY::Which.exist?('file')
|
61
|
+
file_type, status = Open3.capture2e('file', name)
|
62
|
+
file_type = file_type.split(':')[1..-1].join(':').strip
|
63
|
+
if file_type =~ /Apple binary property list/ && TTY::Which.exist?('plutil')
|
64
|
+
`plutil -convert xml1 "#{name}"`
|
65
|
+
File.binary?(name)
|
66
|
+
else
|
67
|
+
status.success? && !text_type?(file_type)
|
68
|
+
end
|
69
|
+
else
|
70
|
+
false
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
#
|
75
|
+
# Tertiary test for binary file
|
76
|
+
#
|
77
|
+
# @param name [String] file path
|
78
|
+
#
|
79
|
+
# @return [Boolean] file is binary according to mdls
|
80
|
+
#
|
81
|
+
def self.third_test(name)
|
82
|
+
if TTY::Which.exist?('mdls')
|
83
|
+
file_type, status = Open3.capture2e('mdls', '-name', 'kMDItemContentTypeTree', name)
|
84
|
+
status.success? && !text_type?(file_type)
|
85
|
+
else
|
86
|
+
false
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.text_type?(name)
|
91
|
+
TEXT_TYPES.any? { |type| name.downcase.include?(type) } || name.empty?
|
8
92
|
end
|
9
|
-
false
|
10
93
|
end
|
11
94
|
end
|
data/lib/planter/filelist.rb
CHANGED
@@ -10,7 +10,7 @@ module Planter
|
|
10
10
|
##
|
11
11
|
## @param path [String] The base path for template
|
12
12
|
##
|
13
|
-
def initialize(path)
|
13
|
+
def initialize(path = Planter.base_dir)
|
14
14
|
@basedir = File.realdirpath(path)
|
15
15
|
|
16
16
|
search_path = File.join(@basedir, '**/*')
|
@@ -30,9 +30,9 @@ module Planter
|
|
30
30
|
end
|
31
31
|
|
32
32
|
##
|
33
|
-
## Public method for copying files based on their operator
|
33
|
+
## Public method for copying @files to target based on their operator
|
34
34
|
##
|
35
|
-
## @return [Boolean] success
|
35
|
+
## @return [Boolean] success or failure
|
36
36
|
##
|
37
37
|
def copy
|
38
38
|
@files.each do |file|
|
@@ -89,36 +89,53 @@ module Planter
|
|
89
89
|
end
|
90
90
|
|
91
91
|
##
|
92
|
-
## Copy tagged merge sections from source to target
|
92
|
+
## Copy tagged merge sections from source to target. If merge tags do not exist in the file,
|
93
|
+
## append the entire file contents to the target.
|
93
94
|
##
|
94
95
|
## @param entry [FileEntry] The file entry
|
95
96
|
##
|
97
|
+
## @return [Boolean] success
|
98
|
+
##
|
96
99
|
def merge(entry)
|
97
100
|
return copy_file(entry) if File.directory?(entry.file)
|
98
101
|
|
102
|
+
# Get the file type
|
99
103
|
type = `file #{entry.file}`
|
100
104
|
case type.sub(/^#{Regexp.escape(entry.file)}: /, '').split(/:/).first
|
101
105
|
when /Apple binary property list/
|
106
|
+
# Convert to XML1 format
|
102
107
|
`plutil -convert xml1 #{entry.file}`
|
103
108
|
`plutil -convert xml1 #{entry.target}`
|
104
109
|
content = IO.read(entry.file)
|
105
110
|
when /data/
|
111
|
+
# Simply copy the file
|
106
112
|
return copy_file(entry)
|
107
113
|
else
|
114
|
+
# Copy the file if it is binary
|
108
115
|
return copy_file(entry) if File.binary?(entry.file)
|
109
116
|
|
117
|
+
# Read the file content
|
110
118
|
content = IO.read(entry.file)
|
111
119
|
end
|
112
120
|
|
121
|
+
# Get the merge sections from the file, delimited by merge and /merge
|
113
122
|
merges = content.scan(%r{(?<=\A|\n).{,4}merge *\n(.*?)\n.{,4}/merge}m)
|
114
123
|
&.map { |m| m[0].strip.apply_variables.apply_regexes }
|
124
|
+
# If no merge sections are found, use the entire file
|
115
125
|
merges = [content] if !merges || merges.empty?
|
116
|
-
|
117
|
-
|
126
|
+
|
127
|
+
# Get the existing content of the target file
|
128
|
+
target_content = IO.read(entry.target)
|
129
|
+
|
130
|
+
# Remove any merges that already exist in the target file
|
131
|
+
merges.delete_if { |m| target_content =~ /#{Regexp.escape(m)}/ }
|
132
|
+
|
133
|
+
# If there are any merge sections left, merge them with the target file
|
118
134
|
if merges.count.positive?
|
119
|
-
File.open(entry.target, 'w') { |f| f.puts "#{
|
135
|
+
File.open(entry.target, 'w') { |f| f.puts "#{target_content.chomp}\n\n#{merges.join("\n\n")}" }
|
120
136
|
Planter.notify("Merged #{entry.file} => #{entry.target} (#{merges.count} merges)", :debug)
|
121
137
|
else
|
138
|
+
# If there are no merge sections left, copy the file instead
|
122
139
|
copy_file(entry)
|
123
140
|
end
|
124
141
|
end
|
@@ -129,14 +146,25 @@ module Planter
|
|
129
146
|
## @param file [FileEntry] The file entry
|
130
147
|
## @param overwrite [Boolean] Force overwrite
|
131
148
|
##
|
149
|
+
## @return [Boolean] success
|
150
|
+
##
|
132
151
|
def copy_file(file, overwrite: false)
|
152
|
+
# Check if the target file already exists
|
153
|
+
# If it does and overwrite is true, or Planter.overwrite is true,
|
154
|
+
# or if the file doesn't exist, then copy the file
|
133
155
|
if !File.exist?(file.target) || overwrite || Planter.overwrite
|
156
|
+
# Make sure the target directory exists
|
134
157
|
FileUtils.mkdir_p(File.dirname(file.target))
|
158
|
+
# Copy the file if it isn't a directory
|
135
159
|
FileUtils.cp(file.file, file.target) unless File.directory?(file.file)
|
160
|
+
# Log a message to the console
|
136
161
|
Planter.notify("Copied #{file.file} => #{file.target}", :debug)
|
162
|
+
# Return true to indicate success
|
137
163
|
true
|
138
164
|
else
|
165
|
+
# Log a message to the console
|
139
166
|
Planter.notify("Skipped #{file.file} => #{file.target}", :debug)
|
167
|
+
# Return false to indicate that the copy was skipped
|
140
168
|
false
|
141
169
|
end
|
142
170
|
end
|
data/lib/planter/hash.rb
CHANGED
@@ -1,103 +1,84 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Hash helpers
|
4
|
-
|
5
|
-
##
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
else
|
16
|
-
v
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
##
|
22
|
-
## Turn all keys into symbols
|
23
|
-
##
|
24
|
-
## @return [Hash] hash with symbolized keys
|
25
|
-
##
|
26
|
-
def symbolize_keys
|
27
|
-
each_with_object({}) do |(k, v), hsh|
|
28
|
-
hsh[k.to_sym] = if v.is_a?(Hash)
|
29
|
-
v.symbolize_keys
|
30
|
-
elsif v.is_a?(Array)
|
31
|
-
v.map(&:symbolize_keys)
|
4
|
+
module Planter
|
5
|
+
## Hash helpers
|
6
|
+
class ::Hash
|
7
|
+
## Turn all keys into string
|
8
|
+
##
|
9
|
+
## @return [Hash] copy of the hash where all its keys are strings
|
10
|
+
##
|
11
|
+
def stringify_keys
|
12
|
+
each_with_object({}) do |(k, v), hsh|
|
13
|
+
hsh[k.to_s] = if v.is_a?(Hash) || v.is_a?(Array)
|
14
|
+
v.stringify_keys
|
32
15
|
else
|
33
16
|
v
|
34
17
|
end
|
18
|
+
end
|
35
19
|
end
|
36
|
-
end
|
37
20
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
v1
|
51
|
-
else
|
52
|
-
v2
|
21
|
+
##
|
22
|
+
## Turn all keys into symbols
|
23
|
+
##
|
24
|
+
## @return [Hash] hash with symbolized keys
|
25
|
+
##
|
26
|
+
def symbolize_keys
|
27
|
+
each_with_object({}) do |(k, v), hsh|
|
28
|
+
hsh[k.to_sym] = if v.is_a?(Hash) || v.is_a?(Array)
|
29
|
+
v.symbolize_keys
|
30
|
+
else
|
31
|
+
v
|
32
|
+
end
|
53
33
|
end
|
54
34
|
end
|
55
|
-
merge(second.to_h, &merger)
|
56
|
-
end
|
57
35
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
36
|
+
##
|
37
|
+
## Deep merge a hash
|
38
|
+
##
|
39
|
+
## @param second [Hash] The hash to merge into self
|
40
|
+
##
|
41
|
+
def deep_merge(second)
|
42
|
+
merger = proc do |_, v1, v2|
|
43
|
+
if v1.is_a?(Hash) && v2.is_a?(Hash)
|
44
|
+
v1.merge(v2, &merger)
|
45
|
+
elsif v1.is_a?(Array) && v2.is_a?(Array)
|
46
|
+
v1 | v2
|
47
|
+
elsif [:undefined, nil, :nil].include?(v2)
|
48
|
+
v1
|
49
|
+
else
|
50
|
+
v2
|
51
|
+
end
|
52
|
+
end
|
53
|
+
merge(second.to_h, &merger)
|
67
54
|
end
|
68
55
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
end
|
56
|
+
##
|
57
|
+
## Freeze all values in a hash
|
58
|
+
##
|
59
|
+
## @return [Hash] Hash with all values frozen
|
60
|
+
##
|
61
|
+
def deep_freeze
|
62
|
+
chilled = {}
|
63
|
+
each do |k, v|
|
64
|
+
chilled[k] = v.is_a?(Hash) ? v.deep_freeze : v.freeze
|
65
|
+
end
|
80
66
|
|
81
|
-
|
82
|
-
## Unfreeze a hash and all nested values
|
83
|
-
##
|
84
|
-
## @return [Hash] unfrozen hash
|
85
|
-
##
|
86
|
-
def deep_thaw
|
87
|
-
chilled = {}
|
88
|
-
each do |k, v|
|
89
|
-
chilled[k] = v.is_a?(Hash) ? v.deep_thaw : v.dup
|
67
|
+
chilled.freeze
|
90
68
|
end
|
91
69
|
|
92
|
-
|
93
|
-
|
70
|
+
##
|
71
|
+
## Unfreeze a hash and all nested values
|
72
|
+
##
|
73
|
+
## @return [Hash] unfrozen hash
|
74
|
+
##
|
75
|
+
def deep_thaw
|
76
|
+
chilled = {}
|
77
|
+
each do |k, v|
|
78
|
+
chilled[k] = v.is_a?(Hash) ? v.deep_thaw : v.dup
|
79
|
+
end
|
94
80
|
|
95
|
-
|
96
|
-
|
97
|
-
##
|
98
|
-
## @return [Hash] unfrozen hash
|
99
|
-
##
|
100
|
-
def deep_thaw!
|
101
|
-
replace deep_thaw
|
81
|
+
chilled.dup
|
82
|
+
end
|
102
83
|
end
|
103
84
|
end
|
data/lib/planter/plant.rb
CHANGED
@@ -13,7 +13,7 @@ module Planter
|
|
13
13
|
Planter.variables = variables if variables.is_a?(Hash)
|
14
14
|
Planter.config = template if template
|
15
15
|
|
16
|
-
@basedir = File.join(Planter
|
16
|
+
@basedir = File.join(Planter.base_dir, 'templates', Planter.template)
|
17
17
|
@target = Planter.target || Dir.pwd
|
18
18
|
|
19
19
|
@git = Planter.config[:git_init] || false
|
@@ -177,15 +177,7 @@ module Planter
|
|
177
177
|
files = Dir.glob('**/*', File::FNM_DOTMATCH).reject { |f| File.directory?(f) || f =~ /^(\.git|config\.yml)/ }
|
178
178
|
|
179
179
|
files.each do |file|
|
180
|
-
|
181
|
-
case type.sub(/^#{Regexp.escape(file)}: /, '').split(/:/).first
|
182
|
-
when /Apple binary property list/
|
183
|
-
`plutil -convert xml1 #{file}`
|
184
|
-
when /data/
|
185
|
-
next
|
186
|
-
else
|
187
|
-
next if File.binary?(file)
|
188
|
-
end
|
180
|
+
next if File.binary?(file)
|
189
181
|
|
190
182
|
content = IO.read(file)
|
191
183
|
new_content = content.apply_variables.apply_regexes
|
data/lib/planter/prompt.rb
CHANGED
@@ -34,7 +34,7 @@ module Planter
|
|
34
34
|
def ask
|
35
35
|
return nil if @prompt.nil?
|
36
36
|
|
37
|
-
return @value.to_s.apply_variables.apply_regexes.coerce(@type) if @value
|
37
|
+
return @value.to_s.apply_variables.apply_regexes.coerce(@type) if @value && @type != :date
|
38
38
|
|
39
39
|
res = case @type
|
40
40
|
when :integer
|
@@ -133,7 +133,7 @@ module Planter
|
|
133
133
|
## @return [String] the single-line response
|
134
134
|
##
|
135
135
|
def read_line(prompt: nil)
|
136
|
-
prompt ||=
|
136
|
+
prompt ||= @prompt
|
137
137
|
default = @default ? " {bw}[#{@default}]" : ''
|
138
138
|
Planter.notify("{by}#{prompt}#{default}")
|
139
139
|
|
@@ -249,7 +249,7 @@ module Planter
|
|
249
249
|
return default unless $stdout.isatty
|
250
250
|
|
251
251
|
# If --defaults is set, return default
|
252
|
-
return default if Planter.accept_defaults
|
252
|
+
return default if Planter.accept_defaults || ENV['PLANTER_DEBUG']
|
253
253
|
|
254
254
|
# clear the buffer
|
255
255
|
if ARGV&.length
|
@@ -316,6 +316,9 @@ module Planter
|
|
316
316
|
default_response
|
317
317
|
end
|
318
318
|
|
319
|
+
# if PLANTER_DEBUG is set, answer default
|
320
|
+
return true if ENV['PLANTER_DEBUG']
|
321
|
+
|
319
322
|
# if this isn't an interactive shell, answer default
|
320
323
|
return default unless $stdout.isatty
|
321
324
|
|
data/lib/planter/script.rb
CHANGED
@@ -13,15 +13,24 @@ module Planter
|
|
13
13
|
## @param script [String] The script name
|
14
14
|
##
|
15
15
|
def initialize(template_dir, output_dir, script)
|
16
|
-
found = find_script(template_dir,
|
17
|
-
|
16
|
+
found = find_script(template_dir, script)
|
17
|
+
raise ScriptError.new("Script #{script} not found") unless found
|
18
|
+
|
18
19
|
@script = found
|
20
|
+
make_executable
|
21
|
+
|
22
|
+
raise ScriptError.new("Output directory #{output_dir} not found") unless File.directory?(output_dir)
|
19
23
|
|
20
|
-
Planter.notify("Directory #{output_dir} not found", :error, exit_code: 10) unless File.directory?(output_dir)
|
21
24
|
@template_directory = template_dir
|
22
25
|
@directory = output_dir
|
23
26
|
end
|
24
27
|
|
28
|
+
## Make a script executable if it's not already
|
29
|
+
def make_executable
|
30
|
+
File.chmod(0o755, @script) unless File.executable?(@script)
|
31
|
+
File.executable?(@script)
|
32
|
+
end
|
33
|
+
|
25
34
|
##
|
26
35
|
## Locate a script in either the base directory or template directory
|
27
36
|
##
|
@@ -31,13 +40,15 @@ module Planter
|
|
31
40
|
## @return [String] Path to script
|
32
41
|
##
|
33
42
|
def find_script(template_dir, script)
|
34
|
-
parts = Shellwords.split(script)
|
35
|
-
|
43
|
+
parts = Shellwords.split(script)
|
44
|
+
script_name = parts[0]
|
45
|
+
args = parts[1..-1].join(' ')
|
46
|
+
return script if File.exist?(script_name)
|
36
47
|
|
37
|
-
if File.exist?(File.join(template_dir, '_scripts',
|
38
|
-
return "#{File.join(template_dir, '_scripts',
|
39
|
-
elsif File.exist?(File.join(
|
40
|
-
return "#{File.join(
|
48
|
+
if File.exist?(File.join(template_dir, '_scripts', script_name))
|
49
|
+
return "#{File.join(template_dir, '_scripts', script_name)} #{args}".strip
|
50
|
+
elsif File.exist?(File.join(Planter.base_dir, 'scripts', script_name))
|
51
|
+
return "#{File.join(Planter.base_dir, 'scripts', script_name)} #{args}".strip
|
41
52
|
end
|
42
53
|
|
43
54
|
nil
|
@@ -49,9 +60,10 @@ module Planter
|
|
49
60
|
## @return [Boolean] true if success?
|
50
61
|
##
|
51
62
|
def run
|
52
|
-
|
53
|
-
|
54
|
-
Planter.notify("
|
63
|
+
stdout, stderr, status = Open3.capture3(@script, @template_directory, @directory)
|
64
|
+
Planter.notify("STDOUT:\n#{stdout}", :debug) unless stdout.empty?
|
65
|
+
Planter.notify("STDERR:\n#{stderr}", :debug) unless stderr.empty?
|
66
|
+
raise ScriptError.new("Error running #{@script}") unless status.success?
|
55
67
|
|
56
68
|
true
|
57
69
|
end
|