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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e5445d6dfa3c8e0663006ce933f45f6e0717ccb4be51c67da0901c9606a5c70c
4
- data.tar.gz: 0ee188813bbc0bb274837b130231dd937f403484d1a26adccee36b8126d2ee3f
3
+ metadata.gz: 5318772de94f6948e72fcf61709d9b0cf42c3518a775e47eaa816e8d432cf0f0
4
+ data.tar.gz: fcc04239c8d4c74af78f7da138d862f3a01ee053740cda5ad28e8e1019c11a29
5
5
  SHA512:
6
- metadata.gz: 78a345ff2396c29c7beeadda989780003b5cc63174e4b9bcfcd0344350d8160fbb403231208ba1c3ca0d4bb66083711e675f5aad7dff5d14b226d59f31be6554
7
- data.tar.gz: 1dc8ab448b3674319f6a469439d7b8dd6657a9c85061358fee7c7280a1fe9bb5910e4bf5d69e3223511bfccbd77c9e09c666b1441619ec0489e25d9c934fc048
6
+ metadata.gz: 55fd5cdd6bbede37bd171df3c6686fc4ca14c869895cf122f7a38997b46121516e32342ab7f8625b26762fba668cd73611c0edeac101fdf3d2d6ec325460dbfa
7
+ data.tar.gz: 865480b6ed5efda83cba2b0314bf1afd685eed88c2c930e6b705e4fb104da3fadc0afd85211ea2a4930370d0c786df342a6dbf7c4f0ab371b9122f6df895150b
data/.gitignore CHANGED
@@ -41,4 +41,5 @@ Gemfile.lock
41
41
 
42
42
  # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
43
43
  .rvmrc
44
- test
44
+ /test
45
+ .history
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
- Exclude:
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 (#{args[:version]})...", hide_cursor: true)
110
+ spinner = TTY::Spinner.new("[:spinner] Running tests (#{version})...", hide_cursor: true)
111
111
 
112
112
  spinner.auto_spin
113
- res = `docker run --rm #{dir_args} -it #{img}`
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
@@ -81,7 +81,7 @@ module Planter
81
81
  [:default, '0;39']
82
82
  ].map(&:freeze).freeze
83
83
 
84
- # Array of attribute keys only
84
+ # @return [Array<String>] all available color names
85
85
  ATTRIBUTE_NAMES = ATTRIBUTES.transpose.first
86
86
 
87
87
  # Returns true if Color supports the +feature+.
@@ -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
- def File.binary?(name)
6
- IO.read(name) do |f|
7
- f.each_byte { |x| x.nonzero? or return true }
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
@@ -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
- new_content = IO.read(entry.target)
117
- merges.delete_if { |m| new_content =~ /#{Regexp.escape(m)}/ }
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 "#{new_content.chomp}\n\n#{merges.join("\n\n")}" }
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
- class ::Hash
5
- ## Turn all keys into string
6
- ##
7
- ## @return [Hash] copy of the hash where all its keys are strings
8
- ##
9
- def stringify_keys
10
- each_with_object({}) do |(k, v), hsh|
11
- hsh[k.to_s] = if v.is_a?(Hash)
12
- v.stringify_keys
13
- elsif v.is_a?(Array)
14
- v.map(&:symbolize_keys)
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
- ## Deep merge a hash
40
- ##
41
- ## @param second [Hash] The hash to merge into self
42
- ##
43
- def deep_merge(second)
44
- merger = proc do |_, v1, v2|
45
- if v1.is_a?(Hash) && v2.is_a?(Hash)
46
- v1.merge(v2, &merger)
47
- elsif v1.is_a?(Array) && v2.is_a?(Array)
48
- v1 | v2
49
- elsif [:undefined, nil, :nil].include?(v2)
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
- ## Freeze all values in a hash
60
- ##
61
- ## @return [Hash] Hash with all values frozen
62
- ##
63
- def deep_freeze
64
- chilled = {}
65
- each do |k, v|
66
- chilled[k] = v.is_a?(Hash) ? v.deep_freeze : v.freeze
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
- chilled.freeze
70
- end
71
-
72
- ##
73
- ## Destructive version of #deep_freeze
74
- ##
75
- ## @return [Hash] Hash with all values frozen
76
- ##
77
- def deep_freeze!
78
- replace deep_thaw.deep_freeze
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
- chilled.dup
93
- end
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
- ## Destructive version of #deep_thaw
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::BASE_DIR, 'templates', Planter.template)
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
- type = `file #{file}`
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
@@ -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 ||= read_lines @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
 
@@ -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, output_dir, script)
17
- Planter.notify("Script #{script} not found", :error, exit_code: 10) unless found
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).first
35
- return script if File.exist?(parts[0])
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', parts[0]))
38
- return "#{File.join(template_dir, '_scripts', parts[0])} #{parts[1..-1]}"
39
- elsif File.exist?(File.join(BASE_DIR, 'scripts', parts[0]))
40
- return "#{File.join(BASE_DIR, 'scripts', parts[0])} #{parts[1..-1]}"
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
- `#{@script} "#{@template_directory}" "#{@directory}"`
53
-
54
- Planter.notify("Error running #{File.basename(@script)}", :error, exit_code: 128) unless $?.success?
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