thor 0.20.3 → 1.3.2
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/README.md +3 -9
- data/lib/thor/actions/create_file.rb +4 -3
- data/lib/thor/actions/create_link.rb +3 -2
- data/lib/thor/actions/directory.rb +8 -18
- data/lib/thor/actions/empty_directory.rb +1 -1
- data/lib/thor/actions/file_manipulation.rb +22 -24
- data/lib/thor/actions/inject_into_file.rb +34 -13
- data/lib/thor/actions.rb +39 -30
- data/lib/thor/base.rb +196 -49
- data/lib/thor/command.rb +34 -18
- data/lib/thor/core_ext/hash_with_indifferent_access.rb +10 -0
- data/lib/thor/error.rb +14 -22
- data/lib/thor/group.rb +13 -2
- data/lib/thor/invocation.rb +2 -1
- data/lib/thor/line_editor/basic.rb +1 -1
- data/lib/thor/line_editor/readline.rb +6 -6
- data/lib/thor/line_editor.rb +2 -2
- data/lib/thor/nested_context.rb +29 -0
- data/lib/thor/parser/argument.rb +17 -1
- data/lib/thor/parser/arguments.rb +35 -15
- data/lib/thor/parser/option.rb +45 -13
- data/lib/thor/parser/options.rb +79 -11
- data/lib/thor/parser.rb +4 -4
- data/lib/thor/rake_compat.rb +3 -2
- data/lib/thor/runner.rb +43 -32
- data/lib/thor/shell/basic.rb +68 -162
- data/lib/thor/shell/color.rb +9 -43
- data/lib/thor/shell/column_printer.rb +29 -0
- data/lib/thor/shell/html.rb +7 -49
- data/lib/thor/shell/lcs_diff.rb +49 -0
- data/lib/thor/shell/table_printer.rb +118 -0
- data/lib/thor/shell/terminal.rb +42 -0
- data/lib/thor/shell/wrapped_printer.rb +38 -0
- data/lib/thor/shell.rb +5 -5
- data/lib/thor/util.rb +25 -8
- data/lib/thor/version.rb +1 -1
- data/lib/thor.rb +182 -17
- data/thor.gemspec +22 -10
- metadata +25 -11
- data/CHANGELOG.md +0 -204
- data/lib/thor/core_ext/io_binary_read.rb +0 -12
- data/lib/thor/core_ext/ordered_hash.rb +0 -129
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9b49f263d36f84d82f17f16852671ff9e2f529ea0adec4b664a2b8660923d091
|
4
|
+
data.tar.gz: 2df9cade7c368e064377ec0f38737d5b379b38265f23d878cb4976588b94564c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c4cca8a5e388509dd8a45a6484c13fa80d89f15c7bfde65ccc3d48d3f86c299269ce6019af1dfe3d2f6f172aff5ae7d7ef8f49ca69de189dcd721d5c9d48269f
|
7
|
+
data.tar.gz: 85b9b4834a91e7fab98ee9f555461cee740bebcbcee3e0efffc9d117d1b8dce6f9967db594225cd32a3d82462b5edc2d6e4c77bb4ef799d6253f3e66f4f88042
|
data/README.md
CHANGED
@@ -2,14 +2,8 @@ Thor
|
|
2
2
|
====
|
3
3
|
|
4
4
|
[][gem]
|
5
|
-
[][travis]
|
6
|
-
[][codeclimate]
|
7
|
-
[][coveralls]
|
8
5
|
|
9
6
|
[gem]: https://rubygems.org/gems/thor
|
10
|
-
[travis]: http://travis-ci.org/erikhuda/thor
|
11
|
-
[codeclimate]: https://codeclimate.com/github/erikhuda/thor
|
12
|
-
[coveralls]: https://coveralls.io/r/erikhuda/thor
|
13
7
|
|
14
8
|
Description
|
15
9
|
-----------
|
@@ -21,7 +15,7 @@ users.
|
|
21
15
|
|
22
16
|
Please note: Thor, by design, is a system tool created to allow seamless file and url
|
23
17
|
access, which should not receive application user input. It relies on [open-uri][open-uri],
|
24
|
-
which combined with application user input would provide a command injection attack
|
18
|
+
which, combined with application user input, would provide a command injection attack
|
25
19
|
vector.
|
26
20
|
|
27
21
|
[rake]: https://github.com/ruby/rake
|
@@ -33,9 +27,9 @@ Installation
|
|
33
27
|
|
34
28
|
Usage and documentation
|
35
29
|
-----------------------
|
36
|
-
Please see the [wiki][] for basic usage and other documentation on using Thor. You can also
|
30
|
+
Please see the [wiki][] for basic usage and other documentation on using Thor. You can also check out the [official homepage][homepage].
|
37
31
|
|
38
|
-
[wiki]: https://github.com/
|
32
|
+
[wiki]: https://github.com/rails/thor/wiki
|
39
33
|
[homepage]: http://whatisthor.com/
|
40
34
|
|
41
35
|
Contributing
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require_relative "empty_directory"
|
2
2
|
|
3
3
|
class Thor
|
4
4
|
module Actions
|
@@ -43,7 +43,8 @@ class Thor
|
|
43
43
|
# Boolean:: true if it is identical, false otherwise.
|
44
44
|
#
|
45
45
|
def identical?
|
46
|
-
|
46
|
+
# binread uses ASCII-8BIT, so to avoid false negatives, the string must use the same
|
47
|
+
exists? && File.binread(destination) == String.new(render).force_encoding("ASCII-8BIT")
|
47
48
|
end
|
48
49
|
|
49
50
|
# Holds the content to be added to the file.
|
@@ -60,7 +61,7 @@ class Thor
|
|
60
61
|
invoke_with_conflict_check do
|
61
62
|
require "fileutils"
|
62
63
|
FileUtils.mkdir_p(File.dirname(destination))
|
63
|
-
File.open(destination, "wb") { |f| f.write render }
|
64
|
+
File.open(destination, "wb", config[:perm]) { |f| f.write render }
|
64
65
|
end
|
65
66
|
given_destination
|
66
67
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require_relative "create_file"
|
2
2
|
|
3
3
|
class Thor
|
4
4
|
module Actions
|
@@ -33,7 +33,8 @@ class Thor
|
|
33
33
|
# Boolean:: true if it is identical, false otherwise.
|
34
34
|
#
|
35
35
|
def identical?
|
36
|
-
|
36
|
+
source = File.expand_path(render, File.dirname(destination))
|
37
|
+
exists? && File.identical?(source, destination)
|
37
38
|
end
|
38
39
|
|
39
40
|
def invoke!
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require_relative "empty_directory"
|
2
2
|
|
3
3
|
class Thor
|
4
4
|
module Actions
|
@@ -56,9 +56,9 @@ class Thor
|
|
56
56
|
attr_reader :source
|
57
57
|
|
58
58
|
def initialize(base, source, destination = nil, config = {}, &block)
|
59
|
-
@source = File.expand_path(base.find_in_source_paths(source.to_s))
|
59
|
+
@source = File.expand_path(Dir[Util.escape_globs(base.find_in_source_paths(source.to_s))].first)
|
60
60
|
@block = block
|
61
|
-
super(base, destination, {:
|
61
|
+
super(base, destination, {recursive: true}.merge(config))
|
62
62
|
end
|
63
63
|
|
64
64
|
def invoke!
|
@@ -96,22 +96,12 @@ class Thor
|
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
end
|
103
|
-
|
104
|
-
def files(lookup)
|
105
|
-
Dir[lookup]
|
106
|
-
end
|
107
|
-
else
|
108
|
-
def file_level_lookup(previous_lookup)
|
109
|
-
File.join(previous_lookup, "*")
|
110
|
-
end
|
99
|
+
def file_level_lookup(previous_lookup)
|
100
|
+
File.join(previous_lookup, "*")
|
101
|
+
end
|
111
102
|
|
112
|
-
|
113
|
-
|
114
|
-
end
|
103
|
+
def files(lookup)
|
104
|
+
Dir.glob(lookup, File::FNM_DOTMATCH)
|
115
105
|
end
|
116
106
|
end
|
117
107
|
end
|
@@ -10,7 +10,6 @@ class Thor
|
|
10
10
|
# destination<String>:: the relative path to the destination root.
|
11
11
|
# config<Hash>:: give :verbose => false to not log the status, and
|
12
12
|
# :mode => :preserve, to preserve the file mode from the source.
|
13
|
-
|
14
13
|
#
|
15
14
|
# ==== Examples
|
16
15
|
#
|
@@ -23,14 +22,14 @@ class Thor
|
|
23
22
|
destination = args.first || source
|
24
23
|
source = File.expand_path(find_in_source_paths(source.to_s))
|
25
24
|
|
26
|
-
create_file destination, nil, config do
|
25
|
+
resulting_destination = create_file destination, nil, config do
|
27
26
|
content = File.binread(source)
|
28
27
|
content = yield(content) if block
|
29
28
|
content
|
30
29
|
end
|
31
30
|
if config[:mode] == :preserve
|
32
31
|
mode = File.stat(source).mode
|
33
|
-
chmod(
|
32
|
+
chmod(resulting_destination, mode, config)
|
34
33
|
end
|
35
34
|
end
|
36
35
|
|
@@ -66,12 +65,15 @@ class Thor
|
|
66
65
|
# ==== Parameters
|
67
66
|
# source<String>:: the address of the given content.
|
68
67
|
# destination<String>:: the relative path to the destination root.
|
69
|
-
# config<Hash>:: give :verbose => false to not log the status
|
68
|
+
# config<Hash>:: give :verbose => false to not log the status, and
|
69
|
+
# :http_headers => <Hash> to add headers to an http request.
|
70
70
|
#
|
71
71
|
# ==== Examples
|
72
72
|
#
|
73
73
|
# get "http://gist.github.com/103208", "doc/README"
|
74
74
|
#
|
75
|
+
# get "http://gist.github.com/103208", "doc/README", :http_headers => {"Content-Type" => "application/json"}
|
76
|
+
#
|
75
77
|
# get "http://gist.github.com/103208" do |content|
|
76
78
|
# content.split("\n").first
|
77
79
|
# end
|
@@ -80,14 +82,14 @@ class Thor
|
|
80
82
|
config = args.last.is_a?(Hash) ? args.pop : {}
|
81
83
|
destination = args.first
|
82
84
|
|
83
|
-
if source =~ %r{^https?\://}
|
85
|
+
render = if source =~ %r{^https?\://}
|
84
86
|
require "open-uri"
|
87
|
+
URI.send(:open, source, config.fetch(:http_headers, {})) { |input| input.binmode.read }
|
85
88
|
else
|
86
89
|
source = File.expand_path(find_in_source_paths(source.to_s))
|
90
|
+
File.open(source) { |input| input.binmode.read }
|
87
91
|
end
|
88
92
|
|
89
|
-
render = open(source) { |input| input.binmode.read }
|
90
|
-
|
91
93
|
destination ||= if block_given?
|
92
94
|
block.arity == 1 ? yield(render) : yield
|
93
95
|
else
|
@@ -120,12 +122,7 @@ class Thor
|
|
120
122
|
context = config.delete(:context) || instance_eval("binding")
|
121
123
|
|
122
124
|
create_file destination, nil, config do
|
123
|
-
|
124
|
-
capturable_erb = if match && match[1] >= "2.2.0" # Ruby 2.6+
|
125
|
-
CapturableERB.new(::File.binread(source), :trim_mode => "-", :eoutvar => "@output_buffer")
|
126
|
-
else
|
127
|
-
CapturableERB.new(::File.binread(source), nil, "-", "@output_buffer")
|
128
|
-
end
|
125
|
+
capturable_erb = CapturableERB.new(::File.binread(source), trim_mode: "-", eoutvar: "@output_buffer")
|
129
126
|
content = capturable_erb.tap do |erb|
|
130
127
|
erb.filename = source
|
131
128
|
end.result(context)
|
@@ -210,9 +207,9 @@ class Thor
|
|
210
207
|
#
|
211
208
|
# ==== Examples
|
212
209
|
#
|
213
|
-
# inject_into_class "app/controllers/application_controller.rb", ApplicationController, " filter_parameter :password\n"
|
210
|
+
# inject_into_class "app/controllers/application_controller.rb", "ApplicationController", " filter_parameter :password\n"
|
214
211
|
#
|
215
|
-
# inject_into_class "app/controllers/application_controller.rb", ApplicationController do
|
212
|
+
# inject_into_class "app/controllers/application_controller.rb", "ApplicationController" do
|
216
213
|
# " filter_parameter :password\n"
|
217
214
|
# end
|
218
215
|
#
|
@@ -233,9 +230,9 @@ class Thor
|
|
233
230
|
#
|
234
231
|
# ==== Examples
|
235
232
|
#
|
236
|
-
# inject_into_module "app/helpers/application_helper.rb", ApplicationHelper, " def help; 'help'; end\n"
|
233
|
+
# inject_into_module "app/helpers/application_helper.rb", "ApplicationHelper", " def help; 'help'; end\n"
|
237
234
|
#
|
238
|
-
# inject_into_module "app/helpers/application_helper.rb", ApplicationHelper do
|
235
|
+
# inject_into_module "app/helpers/application_helper.rb", "ApplicationHelper" do
|
239
236
|
# " def help; 'help'; end\n"
|
240
237
|
# end
|
241
238
|
#
|
@@ -251,7 +248,8 @@ class Thor
|
|
251
248
|
# path<String>:: path of the file to be changed
|
252
249
|
# flag<Regexp|String>:: the regexp or string to be replaced
|
253
250
|
# replacement<String>:: the replacement, can be also given as a block
|
254
|
-
# config<Hash>:: give :verbose => false to not log the status
|
251
|
+
# config<Hash>:: give :verbose => false to not log the status, and
|
252
|
+
# :force => true, to force the replacement regardless of runner behavior.
|
255
253
|
#
|
256
254
|
# ==== Example
|
257
255
|
#
|
@@ -262,9 +260,10 @@ class Thor
|
|
262
260
|
# end
|
263
261
|
#
|
264
262
|
def gsub_file(path, flag, *args, &block)
|
265
|
-
return unless behavior == :invoke
|
266
263
|
config = args.last.is_a?(Hash) ? args.pop : {}
|
267
264
|
|
265
|
+
return unless behavior == :invoke || config.fetch(:force, false)
|
266
|
+
|
268
267
|
path = File.expand_path(path, destination_root)
|
269
268
|
say_status :gsub, relative_to_original_destination_root(path), config.fetch(:verbose, true)
|
270
269
|
|
@@ -275,9 +274,8 @@ class Thor
|
|
275
274
|
end
|
276
275
|
end
|
277
276
|
|
278
|
-
# Uncomment all lines matching a given regex.
|
279
|
-
#
|
280
|
-
# between the comment hash and the beginning of the line.
|
277
|
+
# Uncomment all lines matching a given regex. Preserves indentation before
|
278
|
+
# the comment hash and removes the hash and any immediate following space.
|
281
279
|
#
|
282
280
|
# ==== Parameters
|
283
281
|
# path<String>:: path of the file to be changed
|
@@ -291,7 +289,7 @@ class Thor
|
|
291
289
|
def uncomment_lines(path, flag, *args)
|
292
290
|
flag = flag.respond_to?(:source) ? flag.source : flag
|
293
291
|
|
294
|
-
gsub_file(path, /^(\s*)#[[:blank:]]
|
292
|
+
gsub_file(path, /^(\s*)#[[:blank:]]?(.*#{flag})/, '\1\2', *args)
|
295
293
|
end
|
296
294
|
|
297
295
|
# Comment all lines matching a given regex. It will leave the space
|
@@ -329,7 +327,7 @@ class Thor
|
|
329
327
|
path = File.expand_path(path, destination_root)
|
330
328
|
|
331
329
|
say_status :remove, relative_to_original_destination_root(path), config.fetch(:verbose, true)
|
332
|
-
if !options[:pretend] && File.exist?(path)
|
330
|
+
if !options[:pretend] && (File.exist?(path) || File.symlink?(path))
|
333
331
|
require "fileutils"
|
334
332
|
::FileUtils.rm_rf(path)
|
335
333
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require_relative "empty_directory"
|
2
2
|
|
3
3
|
class Thor
|
4
4
|
module Actions
|
@@ -21,9 +21,14 @@ class Thor
|
|
21
21
|
# gems.split(" ").map{ |gem| " config.gem :#{gem}" }.join("\n")
|
22
22
|
# end
|
23
23
|
#
|
24
|
+
WARNINGS = {unchanged_no_flag: "File unchanged! Either the supplied flag value not found or the content has already been inserted!"}
|
25
|
+
|
24
26
|
def insert_into_file(destination, *args, &block)
|
25
27
|
data = block_given? ? block : args.shift
|
26
|
-
|
28
|
+
|
29
|
+
config = args.shift || {}
|
30
|
+
config[:after] = /\z/ unless config.key?(:before) || config.key?(:after)
|
31
|
+
|
27
32
|
action InjectIntoFile.new(self, destination, data, config)
|
28
33
|
end
|
29
34
|
alias_method :inject_into_file, :insert_into_file
|
@@ -32,7 +37,7 @@ class Thor
|
|
32
37
|
attr_reader :replacement, :flag, :behavior
|
33
38
|
|
34
39
|
def initialize(base, destination, data, config)
|
35
|
-
super(base, destination, {:
|
40
|
+
super(base, destination, {verbose: true}.merge(config))
|
36
41
|
|
37
42
|
@behavior, @flag = if @config.key?(:after)
|
38
43
|
[:after, @config.delete(:after)]
|
@@ -45,8 +50,6 @@ class Thor
|
|
45
50
|
end
|
46
51
|
|
47
52
|
def invoke!
|
48
|
-
say_status :invoke
|
49
|
-
|
50
53
|
content = if @behavior == :after
|
51
54
|
'\0' + replacement
|
52
55
|
else
|
@@ -54,7 +57,13 @@ class Thor
|
|
54
57
|
end
|
55
58
|
|
56
59
|
if exists?
|
57
|
-
replace!(/#{flag}/, content, config[:force])
|
60
|
+
if replace!(/#{flag}/, content, config[:force])
|
61
|
+
say_status(:invoke)
|
62
|
+
elsif replacement_present?
|
63
|
+
say_status(:unchanged, color: :blue)
|
64
|
+
else
|
65
|
+
say_status(:unchanged, warning: WARNINGS[:unchanged_no_flag], color: :red)
|
66
|
+
end
|
58
67
|
else
|
59
68
|
unless pretend?
|
60
69
|
raise Thor::Error, "The file #{ destination } does not appear to exist"
|
@@ -78,7 +87,7 @@ class Thor
|
|
78
87
|
|
79
88
|
protected
|
80
89
|
|
81
|
-
def say_status(behavior)
|
90
|
+
def say_status(behavior, warning: nil, color: nil)
|
82
91
|
status = if behavior == :invoke
|
83
92
|
if flag == /\A/
|
84
93
|
:prepend
|
@@ -87,21 +96,33 @@ class Thor
|
|
87
96
|
else
|
88
97
|
:insert
|
89
98
|
end
|
99
|
+
elsif warning
|
100
|
+
warning
|
101
|
+
elsif behavior == :unchanged
|
102
|
+
:unchanged
|
90
103
|
else
|
91
104
|
:subtract
|
92
105
|
end
|
93
106
|
|
94
|
-
super(status, config[:verbose])
|
107
|
+
super(status, (color || config[:verbose]))
|
108
|
+
end
|
109
|
+
|
110
|
+
def content
|
111
|
+
@content ||= File.read(destination)
|
112
|
+
end
|
113
|
+
|
114
|
+
def replacement_present?
|
115
|
+
content.include?(replacement)
|
95
116
|
end
|
96
117
|
|
97
118
|
# Adds the content to the file.
|
98
119
|
#
|
99
120
|
def replace!(regexp, string, force)
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
121
|
+
if force || !replacement_present?
|
122
|
+
success = content.gsub!(regexp, string)
|
123
|
+
|
124
|
+
File.open(destination, "wb") { |file| file.write(content) } unless pretend?
|
125
|
+
success
|
105
126
|
end
|
106
127
|
end
|
107
128
|
end
|
data/lib/thor/actions.rb
CHANGED
@@ -1,17 +1,16 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
require "thor/actions/file_manipulation"
|
8
|
-
require "thor/actions/inject_into_file"
|
1
|
+
require_relative "actions/create_file"
|
2
|
+
require_relative "actions/create_link"
|
3
|
+
require_relative "actions/directory"
|
4
|
+
require_relative "actions/empty_directory"
|
5
|
+
require_relative "actions/file_manipulation"
|
6
|
+
require_relative "actions/inject_into_file"
|
9
7
|
|
10
8
|
class Thor
|
11
9
|
module Actions
|
12
10
|
attr_accessor :behavior
|
13
11
|
|
14
12
|
def self.included(base) #:nodoc:
|
13
|
+
super(base)
|
15
14
|
base.extend ClassMethods
|
16
15
|
end
|
17
16
|
|
@@ -47,17 +46,17 @@ class Thor
|
|
47
46
|
# Add runtime options that help actions execution.
|
48
47
|
#
|
49
48
|
def add_runtime_options!
|
50
|
-
class_option :force, :
|
51
|
-
:
|
49
|
+
class_option :force, type: :boolean, aliases: "-f", group: :runtime,
|
50
|
+
desc: "Overwrite files that already exist"
|
52
51
|
|
53
|
-
class_option :pretend, :
|
54
|
-
:
|
52
|
+
class_option :pretend, type: :boolean, aliases: "-p", group: :runtime,
|
53
|
+
desc: "Run but do not make any changes"
|
55
54
|
|
56
|
-
class_option :quiet, :
|
57
|
-
:
|
55
|
+
class_option :quiet, type: :boolean, aliases: "-q", group: :runtime,
|
56
|
+
desc: "Suppress status output"
|
58
57
|
|
59
|
-
class_option :skip, :
|
60
|
-
:
|
58
|
+
class_option :skip, type: :boolean, aliases: "-s", group: :runtime,
|
59
|
+
desc: "Skip files that already exist"
|
61
60
|
end
|
62
61
|
end
|
63
62
|
|
@@ -114,9 +113,9 @@ class Thor
|
|
114
113
|
#
|
115
114
|
def relative_to_original_destination_root(path, remove_dot = true)
|
116
115
|
root = @destination_stack[0]
|
117
|
-
if path.start_with?(root) && [File::SEPARATOR, File::ALT_SEPARATOR, nil,
|
116
|
+
if path.start_with?(root) && [File::SEPARATOR, File::ALT_SEPARATOR, nil, ""].include?(path[root.size..root.size])
|
118
117
|
path = path.dup
|
119
|
-
path[0...root.size] =
|
118
|
+
path[0...root.size] = "."
|
120
119
|
remove_dot ? (path[2..-1] || "") : path
|
121
120
|
else
|
122
121
|
path
|
@@ -162,6 +161,8 @@ class Thor
|
|
162
161
|
# to the block you provide. The path is set back to the previous path when
|
163
162
|
# the method exits.
|
164
163
|
#
|
164
|
+
# Returns the value yielded by the block.
|
165
|
+
#
|
165
166
|
# ==== Parameters
|
166
167
|
# dir<String>:: the directory to move to.
|
167
168
|
# config<Hash>:: give :verbose => true to log and use padding.
|
@@ -174,22 +175,24 @@ class Thor
|
|
174
175
|
shell.padding += 1 if verbose
|
175
176
|
@destination_stack.push File.expand_path(dir, destination_root)
|
176
177
|
|
177
|
-
# If the directory
|
178
|
+
# If the directory doesn't exist and we're not pretending
|
178
179
|
if !File.exist?(destination_root) && !pretend
|
179
180
|
require "fileutils"
|
180
181
|
FileUtils.mkdir_p(destination_root)
|
181
182
|
end
|
182
183
|
|
184
|
+
result = nil
|
183
185
|
if pretend
|
184
186
|
# In pretend mode, just yield down to the block
|
185
|
-
block.arity == 1 ? yield(destination_root) : yield
|
187
|
+
result = block.arity == 1 ? yield(destination_root) : yield
|
186
188
|
else
|
187
189
|
require "fileutils"
|
188
|
-
FileUtils.cd(destination_root) { block.arity == 1 ? yield(destination_root) : yield }
|
190
|
+
FileUtils.cd(destination_root) { result = block.arity == 1 ? yield(destination_root) : yield }
|
189
191
|
end
|
190
192
|
|
191
193
|
@destination_stack.pop
|
192
194
|
shell.padding -= 1 if verbose
|
195
|
+
result
|
193
196
|
end
|
194
197
|
|
195
198
|
# Goes to the root and execute the given block.
|
@@ -220,9 +223,9 @@ class Thor
|
|
220
223
|
|
221
224
|
contents = if is_uri
|
222
225
|
require "open-uri"
|
223
|
-
open(path, "Accept" => "application/x-thor-template", &:read)
|
226
|
+
URI.open(path, "Accept" => "application/x-thor-template", &:read)
|
224
227
|
else
|
225
|
-
open(path, &:read)
|
228
|
+
File.open(path, &:read)
|
226
229
|
end
|
227
230
|
|
228
231
|
instance_eval(contents, path)
|
@@ -257,13 +260,19 @@ class Thor
|
|
257
260
|
|
258
261
|
return if options[:pretend]
|
259
262
|
|
260
|
-
|
263
|
+
env_splat = [config[:env]] if config[:env]
|
261
264
|
|
262
|
-
if config[:
|
263
|
-
|
264
|
-
|
265
|
+
if config[:capture]
|
266
|
+
require "open3"
|
267
|
+
result, status = Open3.capture2e(*env_splat, command.to_s)
|
268
|
+
success = status.success?
|
269
|
+
else
|
270
|
+
result = system(*env_splat, command.to_s)
|
271
|
+
success = result
|
265
272
|
end
|
266
273
|
|
274
|
+
abort if !success && config.fetch(:abort_on_failure, self.class.exit_on_failure?)
|
275
|
+
|
267
276
|
result
|
268
277
|
end
|
269
278
|
|
@@ -275,7 +284,7 @@ class Thor
|
|
275
284
|
#
|
276
285
|
def run_ruby_script(command, config = {})
|
277
286
|
return unless behavior == :invoke
|
278
|
-
run command, config.merge(:
|
287
|
+
run command, config.merge(with: Thor::Util.ruby_command)
|
279
288
|
end
|
280
289
|
|
281
290
|
# Run a thor command. A hash of options can be given and it's converted to
|
@@ -306,7 +315,7 @@ class Thor
|
|
306
315
|
args.push Thor::Options.to_switches(config)
|
307
316
|
command = args.join(" ").strip
|
308
317
|
|
309
|
-
run command, :
|
318
|
+
run command, with: :thor, verbose: verbose, pretend: pretend, capture: capture
|
310
319
|
end
|
311
320
|
|
312
321
|
protected
|
@@ -314,7 +323,7 @@ class Thor
|
|
314
323
|
# Allow current root to be shared between invocations.
|
315
324
|
#
|
316
325
|
def _shared_configuration #:nodoc:
|
317
|
-
super.merge!(:
|
326
|
+
super.merge!(destination_root: destination_root)
|
318
327
|
end
|
319
328
|
|
320
329
|
def _cleanup_options_and_set(options, key) #:nodoc:
|