Skip to content

Commit 439a593

Browse files
Support thor install <uri> to install remote thor files
The previous code suggested that this was supported, but it was not really working as expected.
1 parent 937c443 commit 439a593

File tree

2 files changed

+70
-40
lines changed

2 files changed

+70
-40
lines changed

lib/thor/runner.rb

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
require "pathname"
77

88
class Thor::Runner < Thor #:nodoc:
9-
autoload :OpenURI, "open-uri"
10-
119
map "-T" => :list, "-i" => :install, "-u" => :update, "-v" => :version
1210

1311
def self.banner(command, all = false, subcommand = false)
@@ -48,22 +46,33 @@ def method_missing(meth, *args)
4846
def install(name) # rubocop:disable Metrics/MethodLength
4947
initialize_thorfiles
5048

51-
# If a directory name is provided as the argument, look for a 'main.thor'
52-
# command in said directory.
53-
begin
54-
if File.directory?(File.expand_path(name))
55-
base = File.join(name, "main.thor")
56-
package = :directory
57-
contents = open(base, &:read)
58-
else
59-
base = name
60-
package = :file
61-
contents = open(name, &:read)
49+
is_uri = name =~ %r{^https?\://}
50+
51+
if is_uri
52+
base = name
53+
package = :file
54+
require "open-uri"
55+
begin
56+
contents = URI.send(:open, name, &:read) # Using `send` for Ruby 2.4- support
57+
rescue OpenURI::HTTPError
58+
raise Error, "Error opening URI '#{name}'"
59+
end
60+
else
61+
# If a directory name is provided as the argument, look for a 'main.thor'
62+
# command in said directory.
63+
begin
64+
if File.directory?(File.expand_path(name))
65+
base = File.join(name, "main.thor")
66+
package = :directory
67+
contents = open(base, &:read)
68+
else
69+
base = name
70+
package = :file
71+
contents = open(name, &:read)
72+
end
73+
rescue Errno::ENOENT
74+
raise Error, "Error opening file '#{name}'"
6275
end
63-
rescue OpenURI::HTTPError
64-
raise Error, "Error opening URI '#{name}'"
65-
rescue Errno::ENOENT
66-
raise Error, "Error opening file '#{name}'"
6776
end
6877

6978
say "Your Thorfile contains:"
@@ -84,7 +93,7 @@ def install(name) # rubocop:disable Metrics/MethodLength
8493
as = basename if as.empty?
8594
end
8695

87-
location = if options[:relative] || name =~ %r{^https?://}
96+
location = if options[:relative] || is_uri
8897
name
8998
else
9099
File.expand_path(name)

spec/runner_spec.rb

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,11 @@ def when_no_thorfiles_exist
118118
end
119119

120120
describe "commands" do
121+
let(:location) { "#{File.dirname(__FILE__)}/fixtures/command.thor" }
121122
before do
122-
@location = "#{File.dirname(__FILE__)}/fixtures/command.thor"
123123
@original_yaml = {
124124
"random" => {
125-
:location => @location,
125+
:location => location,
126126
:filename => "4a33b894ffce85d7b412fc1b36f88fe0",
127127
:namespaces => %w(amazing)
128128
}
@@ -214,31 +214,52 @@ def when_no_thorfiles_exist
214214
end
215215

216216
describe "install/update" do
217-
before do
218-
allow(FileUtils).to receive(:mkdir_p)
219-
allow(FileUtils).to receive(:touch)
220-
allow(Thor::LineEditor).to receive(:readline).and_return("Y")
221-
222-
path = File.join(Thor::Util.thor_root, Digest::SHA256.hexdigest(@location + "random"))
223-
expect(File).to receive(:open).with(path, "w")
224-
end
217+
context "with local thor files" do
218+
before do
219+
allow(FileUtils).to receive(:mkdir_p)
220+
allow(FileUtils).to receive(:touch)
221+
allow(Thor::LineEditor).to receive(:readline).and_return("Y")
222+
223+
path = File.join(Thor::Util.thor_root, Digest::SHA256.hexdigest(location + "random"))
224+
expect(File).to receive(:open).with(path, "w")
225+
end
225226

226-
it "updates existing thor files" do
227-
path = File.join(Thor::Util.thor_root, @original_yaml["random"][:filename])
228-
if File.directory? path
229-
expect(FileUtils).to receive(:rm_rf).with(path)
230-
else
231-
expect(File).to receive(:delete).with(path)
227+
it "updates existing thor files" do
228+
path = File.join(Thor::Util.thor_root, @original_yaml["random"][:filename])
229+
if File.directory? path
230+
expect(FileUtils).to receive(:rm_rf).with(path)
231+
else
232+
expect(File).to receive(:delete).with(path)
233+
end
234+
silence_warnings do
235+
silence(:stdout) { Thor::Runner.start(%w(update random)) }
236+
end
232237
end
233-
silence_warnings do
234-
silence(:stdout) { Thor::Runner.start(%w(update random)) }
238+
239+
it "installs thor files" do
240+
ARGV.replace %W(install #{location})
241+
silence_warnings do
242+
silence(:stdout) { Thor::Runner.start }
243+
end
235244
end
236245
end
237246

238-
it "installs thor files" do
239-
ARGV.replace %W(install #{@location})
240-
silence_warnings do
241-
silence(:stdout) { Thor::Runner.start }
247+
context "with remote thor files" do
248+
let(:location) { "https://example.com/Thorfile" }
249+
250+
it "installs thor files" do
251+
allow(Thor::LineEditor).to receive(:readline).and_return("Y", "random")
252+
stub_request(:get, location).to_return(:body => "class Foo < Thor; end")
253+
path = File.join(Thor::Util.thor_root, Digest::SHA256.hexdigest(location + "random"))
254+
expect(File).to receive(:open).with(path, "w")
255+
expect { silence(:stdout) { Thor::Runner.start(%W(install #{location})) } }.not_to raise_error
256+
end
257+
258+
it "shows proper errors" do
259+
expect(Thor::Runner).to receive :exit
260+
expect(URI).to receive(:open).with(location).and_raise(OpenURI::HTTPError.new("foo", StringIO.new))
261+
content = capture(:stderr) { Thor::Runner.start(%W(install #{location})) }
262+
expect(content).to include("Error opening URI '#{location}'")
242263
end
243264
end
244265
end

0 commit comments

Comments
 (0)