planter-cli 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|