thor 0.19.4 → 1.2.1
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 +5 -5
- data/README.md +7 -9
- data/lib/thor/actions/create_file.rb +2 -1
- data/lib/thor/actions/create_link.rb +4 -2
- data/lib/thor/actions/directory.rb +7 -17
- data/lib/thor/actions/empty_directory.rb +9 -1
- data/lib/thor/actions/file_manipulation.rb +64 -16
- data/lib/thor/actions/inject_into_file.rb +27 -11
- data/lib/thor/actions.rb +38 -16
- data/lib/thor/base.rb +84 -41
- data/lib/thor/command.rb +30 -21
- data/lib/thor/core_ext/hash_with_indifferent_access.rb +18 -0
- data/lib/thor/error.rb +83 -0
- data/lib/thor/group.rb +4 -4
- data/lib/thor/invocation.rb +1 -0
- data/lib/thor/line_editor/basic.rb +2 -0
- 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/arguments.rb +7 -3
- data/lib/thor/parser/option.rb +22 -9
- data/lib/thor/parser/options.rb +45 -10
- data/lib/thor/parser.rb +4 -4
- data/lib/thor/rake_compat.rb +1 -0
- data/lib/thor/runner.rb +9 -6
- data/lib/thor/shell/basic.rb +96 -20
- data/lib/thor/shell/color.rb +10 -2
- data/lib/thor/shell/html.rb +3 -3
- data/lib/thor/shell.rb +5 -5
- data/lib/thor/util.rb +18 -2
- data/lib/thor/version.rb +1 -1
- data/lib/thor.rb +39 -15
- data/thor.gemspec +10 -2
- metadata +20 -11
- data/CHANGELOG.md +0 -163
- 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
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 30e79d2b0a96e87c8e6348467db577c6ad1e9acbbbac5d375417bc3e5a2b7698
|
4
|
+
data.tar.gz: 701f1ab842da90e599b96bd00d90481d716eb29e39e0283b5ff527c2033fc742
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 73b1ac80575d4422204cd8072950b5594739db3b6f3fde0f2f04359d51b1d4428524d25b9a3003ae9ec3f6be615cf635f3057bbc65558e6a17ba490ff045988b
|
7
|
+
data.tar.gz: eb7761a5e6f3674cb3231398145978b0eb53a6fa2c10e4cb9e99d8d523988efcefc8cae5dd163b8a3d6ead7424422d58b92311c200790ad6e2416e3f9757a90e
|
data/README.md
CHANGED
@@ -2,16 +2,8 @@ Thor
|
|
2
2
|
====
|
3
3
|
|
4
4
|
[][gem]
|
5
|
-
[][travis]
|
6
|
-
[][gemnasium]
|
7
|
-
[][codeclimate]
|
8
|
-
[][coveralls]
|
9
5
|
|
10
6
|
[gem]: https://rubygems.org/gems/thor
|
11
|
-
[travis]: http://travis-ci.org/erikhuda/thor
|
12
|
-
[gemnasium]: https://gemnasium.com/erikhuda/thor
|
13
|
-
[codeclimate]: https://codeclimate.com/github/erikhuda/thor
|
14
|
-
[coveralls]: https://coveralls.io/r/erikhuda/thor
|
15
7
|
|
16
8
|
Description
|
17
9
|
-----------
|
@@ -21,7 +13,13 @@ utilities. It removes the pain of parsing command line options, writing
|
|
21
13
|
build tool. The syntax is Rake-like, so it should be familiar to most Rake
|
22
14
|
users.
|
23
15
|
|
16
|
+
Please note: Thor, by design, is a system tool created to allow seamless file and url
|
17
|
+
access, which should not receive application user input. It relies on [open-uri][open-uri],
|
18
|
+
which combined with application user input would provide a command injection attack
|
19
|
+
vector.
|
20
|
+
|
24
21
|
[rake]: https://github.com/ruby/rake
|
22
|
+
[open-uri]: https://ruby-doc.org/stdlib-2.5.1/libdoc/open-uri/rdoc/index.html
|
25
23
|
|
26
24
|
Installation
|
27
25
|
------------
|
@@ -31,7 +29,7 @@ Usage and documentation
|
|
31
29
|
-----------------------
|
32
30
|
Please see the [wiki][] for basic usage and other documentation on using Thor. You can also checkout the [official homepage][homepage].
|
33
31
|
|
34
|
-
[wiki]: https://github.com/
|
32
|
+
[wiki]: https://github.com/rails/thor/wiki
|
35
33
|
[homepage]: http://whatisthor.com/
|
36
34
|
|
37
35
|
Contributing
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require_relative "empty_directory"
|
2
2
|
|
3
3
|
class Thor
|
4
4
|
module Actions
|
@@ -58,6 +58,7 @@ class Thor
|
|
58
58
|
|
59
59
|
def invoke!
|
60
60
|
invoke_with_conflict_check do
|
61
|
+
require "fileutils"
|
61
62
|
FileUtils.mkdir_p(File.dirname(destination))
|
62
63
|
File.open(destination, "wb") { |f| f.write render }
|
63
64
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require_relative "create_file"
|
2
2
|
|
3
3
|
class Thor
|
4
4
|
module Actions
|
@@ -33,11 +33,13 @@ 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!
|
40
41
|
invoke_with_conflict_check do
|
42
|
+
require "fileutils"
|
41
43
|
FileUtils.mkdir_p(File.dirname(destination))
|
42
44
|
# Create a symlink by default
|
43
45
|
config[:symbolic] = true if config[:symbolic].nil?
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require_relative "empty_directory"
|
2
2
|
|
3
3
|
class Thor
|
4
4
|
module Actions
|
@@ -56,7 +56,7 @@ 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
61
|
super(base, destination, {:recursive => true}.merge(config))
|
62
62
|
end
|
@@ -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
|
@@ -48,12 +48,14 @@ class Thor
|
|
48
48
|
|
49
49
|
def invoke!
|
50
50
|
invoke_with_conflict_check do
|
51
|
+
require "fileutils"
|
51
52
|
::FileUtils.mkdir_p(destination)
|
52
53
|
end
|
53
54
|
end
|
54
55
|
|
55
56
|
def revoke!
|
56
57
|
say_status :remove, :red
|
58
|
+
require "fileutils"
|
57
59
|
::FileUtils.rm_rf(destination) if !pretend? && exists?
|
58
60
|
given_destination
|
59
61
|
end
|
@@ -112,11 +114,17 @@ class Thor
|
|
112
114
|
if exists?
|
113
115
|
on_conflict_behavior(&block)
|
114
116
|
else
|
115
|
-
say_status :create, :green
|
116
117
|
yield unless pretend?
|
118
|
+
say_status :create, :green
|
117
119
|
end
|
118
120
|
|
119
121
|
destination
|
122
|
+
rescue Errno::EISDIR, Errno::EEXIST
|
123
|
+
on_file_clash_behavior
|
124
|
+
end
|
125
|
+
|
126
|
+
def on_file_clash_behavior
|
127
|
+
say_status :file_clash, :red
|
120
128
|
end
|
121
129
|
|
122
130
|
# What to do when the destination file already exists.
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require "erb"
|
2
|
-
require "open-uri"
|
3
2
|
|
4
3
|
class Thor
|
5
4
|
module Actions
|
@@ -24,14 +23,14 @@ class Thor
|
|
24
23
|
destination = args.first || source
|
25
24
|
source = File.expand_path(find_in_source_paths(source.to_s))
|
26
25
|
|
27
|
-
create_file destination, nil, config do
|
26
|
+
resulting_destination = create_file destination, nil, config do
|
28
27
|
content = File.binread(source)
|
29
28
|
content = yield(content) if block
|
30
29
|
content
|
31
30
|
end
|
32
31
|
if config[:mode] == :preserve
|
33
32
|
mode = File.stat(source).mode
|
34
|
-
chmod(
|
33
|
+
chmod(resulting_destination, mode, config)
|
35
34
|
end
|
36
35
|
end
|
37
36
|
|
@@ -61,6 +60,9 @@ class Thor
|
|
61
60
|
# destination. If a block is given instead of destination, the content of
|
62
61
|
# the url is yielded and used as location.
|
63
62
|
#
|
63
|
+
# +get+ relies on open-uri, so passing application user input would provide
|
64
|
+
# a command injection attack vector.
|
65
|
+
#
|
64
66
|
# ==== Parameters
|
65
67
|
# source<String>:: the address of the given content.
|
66
68
|
# destination<String>:: the relative path to the destination root.
|
@@ -78,8 +80,13 @@ class Thor
|
|
78
80
|
config = args.last.is_a?(Hash) ? args.pop : {}
|
79
81
|
destination = args.first
|
80
82
|
|
81
|
-
|
82
|
-
|
83
|
+
render = if source =~ %r{^https?\://}
|
84
|
+
require "open-uri"
|
85
|
+
URI.send(:open, source) { |input| input.binmode.read }
|
86
|
+
else
|
87
|
+
source = File.expand_path(find_in_source_paths(source.to_s))
|
88
|
+
open(source) { |input| input.binmode.read }
|
89
|
+
end
|
83
90
|
|
84
91
|
destination ||= if block_given?
|
85
92
|
block.arity == 1 ? yield(render) : yield
|
@@ -113,7 +120,15 @@ class Thor
|
|
113
120
|
context = config.delete(:context) || instance_eval("binding")
|
114
121
|
|
115
122
|
create_file destination, nil, config do
|
116
|
-
|
123
|
+
match = ERB.version.match(/(\d+\.\d+\.\d+)/)
|
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
|
129
|
+
content = capturable_erb.tap do |erb|
|
130
|
+
erb.filename = source
|
131
|
+
end.result(context)
|
117
132
|
content = yield(content) if block
|
118
133
|
content
|
119
134
|
end
|
@@ -134,7 +149,10 @@ class Thor
|
|
134
149
|
return unless behavior == :invoke
|
135
150
|
path = File.expand_path(path, destination_root)
|
136
151
|
say_status :chmod, relative_to_original_destination_root(path), config.fetch(:verbose, true)
|
137
|
-
|
152
|
+
unless options[:pretend]
|
153
|
+
require "fileutils"
|
154
|
+
FileUtils.chmod_R(mode, path)
|
155
|
+
end
|
138
156
|
end
|
139
157
|
|
140
158
|
# Prepend text to a file. Since it depends on insert_into_file, it's reversible.
|
@@ -192,9 +210,9 @@ class Thor
|
|
192
210
|
#
|
193
211
|
# ==== Examples
|
194
212
|
#
|
195
|
-
# inject_into_class "app/controllers/application_controller.rb", ApplicationController, " filter_parameter :password\n"
|
213
|
+
# inject_into_class "app/controllers/application_controller.rb", "ApplicationController", " filter_parameter :password\n"
|
196
214
|
#
|
197
|
-
# inject_into_class "app/controllers/application_controller.rb", ApplicationController do
|
215
|
+
# inject_into_class "app/controllers/application_controller.rb", "ApplicationController" do
|
198
216
|
# " filter_parameter :password\n"
|
199
217
|
# end
|
200
218
|
#
|
@@ -204,13 +222,37 @@ class Thor
|
|
204
222
|
insert_into_file(path, *(args << config), &block)
|
205
223
|
end
|
206
224
|
|
225
|
+
# Injects text right after the module definition. Since it depends on
|
226
|
+
# insert_into_file, it's reversible.
|
227
|
+
#
|
228
|
+
# ==== Parameters
|
229
|
+
# path<String>:: path of the file to be changed
|
230
|
+
# module_name<String|Class>:: the module to be manipulated
|
231
|
+
# data<String>:: the data to append to the class, can be also given as a block.
|
232
|
+
# config<Hash>:: give :verbose => false to not log the status.
|
233
|
+
#
|
234
|
+
# ==== Examples
|
235
|
+
#
|
236
|
+
# inject_into_module "app/helpers/application_helper.rb", "ApplicationHelper", " def help; 'help'; end\n"
|
237
|
+
#
|
238
|
+
# inject_into_module "app/helpers/application_helper.rb", "ApplicationHelper" do
|
239
|
+
# " def help; 'help'; end\n"
|
240
|
+
# end
|
241
|
+
#
|
242
|
+
def inject_into_module(path, module_name, *args, &block)
|
243
|
+
config = args.last.is_a?(Hash) ? args.pop : {}
|
244
|
+
config[:after] = /module #{module_name}\n|module #{module_name} .*\n/
|
245
|
+
insert_into_file(path, *(args << config), &block)
|
246
|
+
end
|
247
|
+
|
207
248
|
# Run a regular expression replacement on a file.
|
208
249
|
#
|
209
250
|
# ==== Parameters
|
210
251
|
# path<String>:: path of the file to be changed
|
211
252
|
# flag<Regexp|String>:: the regexp or string to be replaced
|
212
253
|
# replacement<String>:: the replacement, can be also given as a block
|
213
|
-
# config<Hash>:: give :verbose => false to not log the status
|
254
|
+
# config<Hash>:: give :verbose => false to not log the status, and
|
255
|
+
# :force => true, to force the replacement regardles of runner behavior.
|
214
256
|
#
|
215
257
|
# ==== Example
|
216
258
|
#
|
@@ -221,9 +263,10 @@ class Thor
|
|
221
263
|
# end
|
222
264
|
#
|
223
265
|
def gsub_file(path, flag, *args, &block)
|
224
|
-
return unless behavior == :invoke
|
225
266
|
config = args.last.is_a?(Hash) ? args.pop : {}
|
226
267
|
|
268
|
+
return unless behavior == :invoke || config.fetch(:force, false)
|
269
|
+
|
227
270
|
path = File.expand_path(path, destination_root)
|
228
271
|
say_status :gsub, relative_to_original_destination_root(path), config.fetch(:verbose, true)
|
229
272
|
|
@@ -269,7 +312,7 @@ class Thor
|
|
269
312
|
def comment_lines(path, flag, *args)
|
270
313
|
flag = flag.respond_to?(:source) ? flag.source : flag
|
271
314
|
|
272
|
-
gsub_file(path, /^(\s*)([
|
315
|
+
gsub_file(path, /^(\s*)([^#\n]*#{flag})/, '\1# \2', *args)
|
273
316
|
end
|
274
317
|
|
275
318
|
# Removes a file at the given location.
|
@@ -288,7 +331,10 @@ class Thor
|
|
288
331
|
path = File.expand_path(path, destination_root)
|
289
332
|
|
290
333
|
say_status :remove, relative_to_original_destination_root(path), config.fetch(:verbose, true)
|
291
|
-
|
334
|
+
if !options[:pretend] && (File.exist?(path) || File.symlink?(path))
|
335
|
+
require "fileutils"
|
336
|
+
::FileUtils.rm_rf(path)
|
337
|
+
end
|
292
338
|
end
|
293
339
|
alias_method :remove_dir, :remove_file
|
294
340
|
|
@@ -305,8 +351,10 @@ class Thor
|
|
305
351
|
with_output_buffer { yield(*args) }
|
306
352
|
end
|
307
353
|
|
308
|
-
def with_output_buffer(buf = "") #:nodoc:
|
309
|
-
|
354
|
+
def with_output_buffer(buf = "".dup) #:nodoc:
|
355
|
+
raise ArgumentError, "Buffer can not be a frozen object" if buf.frozen?
|
356
|
+
old_buffer = output_buffer
|
357
|
+
self.output_buffer = buf
|
310
358
|
yield
|
311
359
|
output_buffer
|
312
360
|
ensure
|
@@ -319,7 +367,7 @@ class Thor
|
|
319
367
|
def set_eoutvar(compiler, eoutvar = "_erbout")
|
320
368
|
compiler.put_cmd = "#{eoutvar}.concat"
|
321
369
|
compiler.insert_cmd = "#{eoutvar}.concat"
|
322
|
-
compiler.pre_cmd = ["#{eoutvar} = ''"]
|
370
|
+
compiler.pre_cmd = ["#{eoutvar} = ''.dup"]
|
323
371
|
compiler.post_cmd = [eoutvar]
|
324
372
|
end
|
325
373
|
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! The supplied flag value not found!' }
|
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
|
@@ -45,15 +50,23 @@ 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
|
53
56
|
replacement + '\0'
|
54
57
|
end
|
55
58
|
|
56
|
-
|
59
|
+
if exists?
|
60
|
+
if replace!(/#{flag}/, content, config[:force])
|
61
|
+
say_status(:invoke)
|
62
|
+
else
|
63
|
+
say_status(:unchanged, warning: WARNINGS[:unchanged_no_flag], color: :red)
|
64
|
+
end
|
65
|
+
else
|
66
|
+
unless pretend?
|
67
|
+
raise Thor::Error, "The file #{ destination } does not appear to exist"
|
68
|
+
end
|
69
|
+
end
|
57
70
|
end
|
58
71
|
|
59
72
|
def revoke!
|
@@ -72,7 +85,7 @@ class Thor
|
|
72
85
|
|
73
86
|
protected
|
74
87
|
|
75
|
-
def say_status(behavior)
|
88
|
+
def say_status(behavior, warning: nil, color: nil)
|
76
89
|
status = if behavior == :invoke
|
77
90
|
if flag == /\A/
|
78
91
|
:prepend
|
@@ -81,21 +94,24 @@ class Thor
|
|
81
94
|
else
|
82
95
|
:insert
|
83
96
|
end
|
97
|
+
elsif warning
|
98
|
+
warning
|
84
99
|
else
|
85
100
|
:subtract
|
86
101
|
end
|
87
102
|
|
88
|
-
super(status, config[:verbose])
|
103
|
+
super(status, (color || config[:verbose]))
|
89
104
|
end
|
90
105
|
|
91
106
|
# Adds the content to the file.
|
92
107
|
#
|
93
108
|
def replace!(regexp, string, force)
|
94
|
-
|
95
|
-
content = File.binread(destination)
|
109
|
+
content = File.read(destination)
|
96
110
|
if force || !content.include?(replacement)
|
97
|
-
content.gsub!(regexp, string)
|
98
|
-
|
111
|
+
success = content.gsub!(regexp, string)
|
112
|
+
|
113
|
+
File.open(destination, "wb") { |file| file.write(content) } unless pretend?
|
114
|
+
success
|
99
115
|
end
|
100
116
|
end
|
101
117
|
end
|
data/lib/thor/actions.rb
CHANGED
@@ -1,18 +1,16 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
require "thor/actions/empty_directory"
|
8
|
-
require "thor/actions/file_manipulation"
|
9
|
-
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"
|
10
7
|
|
11
8
|
class Thor
|
12
9
|
module Actions
|
13
10
|
attr_accessor :behavior
|
14
11
|
|
15
12
|
def self.included(base) #:nodoc:
|
13
|
+
super(base)
|
16
14
|
base.extend ClassMethods
|
17
15
|
end
|
18
16
|
|
@@ -114,8 +112,10 @@ class Thor
|
|
114
112
|
# the script started).
|
115
113
|
#
|
116
114
|
def relative_to_original_destination_root(path, remove_dot = true)
|
117
|
-
|
118
|
-
if path.
|
115
|
+
root = @destination_stack[0]
|
116
|
+
if path.start_with?(root) && [File::SEPARATOR, File::ALT_SEPARATOR, nil, ''].include?(path[root.size..root.size])
|
117
|
+
path = path.dup
|
118
|
+
path[0...root.size] = '.'
|
119
119
|
remove_dot ? (path[2..-1] || "") : path
|
120
120
|
else
|
121
121
|
path
|
@@ -141,7 +141,7 @@ class Thor
|
|
141
141
|
end
|
142
142
|
end
|
143
143
|
|
144
|
-
message = "Could not find #{file.inspect} in any of your source paths. "
|
144
|
+
message = "Could not find #{file.inspect} in any of your source paths. ".dup
|
145
145
|
|
146
146
|
unless self.class.source_root
|
147
147
|
message << "Please invoke #{self.class.name}.source_root(PATH) with the PATH containing your templates. "
|
@@ -161,6 +161,8 @@ class Thor
|
|
161
161
|
# to the block you provide. The path is set back to the previous path when
|
162
162
|
# the method exits.
|
163
163
|
#
|
164
|
+
# Returns the value yielded by the block.
|
165
|
+
#
|
164
166
|
# ==== Parameters
|
165
167
|
# dir<String>:: the directory to move to.
|
166
168
|
# config<Hash>:: give :verbose => true to log and use padding.
|
@@ -175,18 +177,22 @@ class Thor
|
|
175
177
|
|
176
178
|
# If the directory doesnt exist and we're not pretending
|
177
179
|
if !File.exist?(destination_root) && !pretend
|
180
|
+
require "fileutils"
|
178
181
|
FileUtils.mkdir_p(destination_root)
|
179
182
|
end
|
180
183
|
|
184
|
+
result = nil
|
181
185
|
if pretend
|
182
186
|
# In pretend mode, just yield down to the block
|
183
|
-
block.arity == 1 ? yield(destination_root) : yield
|
187
|
+
result = block.arity == 1 ? yield(destination_root) : yield
|
184
188
|
else
|
185
|
-
|
189
|
+
require "fileutils"
|
190
|
+
FileUtils.cd(destination_root) { result = block.arity == 1 ? yield(destination_root) : yield }
|
186
191
|
end
|
187
192
|
|
188
193
|
@destination_stack.pop
|
189
194
|
shell.padding -= 1 if verbose
|
195
|
+
result
|
190
196
|
end
|
191
197
|
|
192
198
|
# Goes to the root and execute the given block.
|
@@ -216,7 +222,8 @@ class Thor
|
|
216
222
|
shell.padding += 1 if verbose
|
217
223
|
|
218
224
|
contents = if is_uri
|
219
|
-
|
225
|
+
require "open-uri"
|
226
|
+
URI.open(path, "Accept" => "application/x-thor-template", &:read)
|
220
227
|
else
|
221
228
|
open(path, &:read)
|
222
229
|
end
|
@@ -251,7 +258,22 @@ class Thor
|
|
251
258
|
|
252
259
|
say_status :run, desc, config.fetch(:verbose, true)
|
253
260
|
|
254
|
-
|
261
|
+
return if options[:pretend]
|
262
|
+
|
263
|
+
env_splat = [config[:env]] if config[:env]
|
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
|
272
|
+
end
|
273
|
+
|
274
|
+
abort if !success && config.fetch(:abort_on_failure, self.class.exit_on_failure?)
|
275
|
+
|
276
|
+
result
|
255
277
|
end
|
256
278
|
|
257
279
|
# Executes a ruby script (taking into account WIN32 platform quirks).
|