Skip to content

Commit

Permalink
Support thor install <uri> to install remote thor files
Browse files Browse the repository at this point in the history
The previous code suggested that this was supported, but it was not
really working as expected.
  • Loading branch information
deivid-rodriguez committed Jun 17, 2022
1 parent 8c9817d commit 59ad393
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 39 deletions.
45 changes: 27 additions & 18 deletions lib/thor/runner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
require "pathname"

class Thor::Runner < Thor #:nodoc:
autoload :OpenURI, "open-uri"

map "-T" => :list, "-i" => :install, "-u" => :update, "-v" => :version

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

# If a directory name is provided as the argument, look for a 'main.thor'
# command in said directory.
begin
if File.directory?(File.expand_path(name))
base = File.join(name, "main.thor")
package = :directory
contents = open(base, &:read)
else
base = name
package = :file
contents = open(name, &:read)
is_uri = name =~ %r{^https?\://}

if is_uri
base = name
package = :file
require "open-uri"
begin
contents = URI.send(:open, name, &:read) # Using `send` for Ruby 2.4- support
rescue OpenURI::HTTPError
raise Error, "Error opening URI '#{name}'"
end
else
# If a directory name is provided as the argument, look for a 'main.thor'
# command in said directory.
begin
if File.directory?(File.expand_path(name))
base = File.join(name, "main.thor")
package = :directory
contents = open(base, &:read)
else
base = name
package = :file
contents = open(name, &:read)
end
rescue Errno::ENOENT
raise Error, "Error opening file '#{name}'"
end
rescue OpenURI::HTTPError
raise Error, "Error opening URI '#{name}'"
rescue Errno::ENOENT
raise Error, "Error opening file '#{name}'"
end

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

location = if options[:relative] || name =~ %r{^https?://}
location = if options[:relative] || is_uri
name
else
File.expand_path(name)
Expand Down
64 changes: 43 additions & 21 deletions spec/runner_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,11 @@ def when_no_thorfiles_exist
end

describe "commands" do
let(:location) { "#{File.dirname(__FILE__)}/fixtures/command.thor" }
before do
@location = "#{File.dirname(__FILE__)}/fixtures/command.thor"
@original_yaml = {
"random" => {
:location => @location,
:location => location,
:filename => "4a33b894ffce85d7b412fc1b36f88fe0",
:namespaces => %w(amazing)
}
Expand Down Expand Up @@ -214,31 +214,53 @@ def when_no_thorfiles_exist
end

describe "install/update" do
before do
allow(FileUtils).to receive(:mkdir_p)
allow(FileUtils).to receive(:touch)
allow(Thor::LineEditor).to receive(:readline).and_return("Y")
context "with local thor files" do
before do
allow(FileUtils).to receive(:mkdir_p)
allow(FileUtils).to receive(:touch)
allow(Thor::LineEditor).to receive(:readline).and_return("Y")

path = File.join(Thor::Util.thor_root, Digest::MD5.hexdigest(location + "random"))
expect(File).to receive(:open).with(path, "w")
end

path = File.join(Thor::Util.thor_root, Digest::MD5.hexdigest(@location + "random"))
expect(File).to receive(:open).with(path, "w")
end

it "updates existing thor files" do
path = File.join(Thor::Util.thor_root, @original_yaml["random"][:filename])
if File.directory? path
expect(FileUtils).to receive(:rm_rf).with(path)
else
expect(File).to receive(:delete).with(path)
it "updates existing thor files" do
path = File.join(Thor::Util.thor_root, @original_yaml["random"][:filename])
if File.directory? path
expect(FileUtils).to receive(:rm_rf).with(path)
else
expect(File).to receive(:delete).with(path)
end
silence_warnings do
silence(:stdout) { Thor::Runner.start(%w(update random)) }
end
end
silence_warnings do
silence(:stdout) { Thor::Runner.start(%w(update random)) }

it "installs thor files" do
ARGV.replace %W(install #{location})
silence_warnings do
silence(:stdout) { Thor::Runner.start }
end
end
end

it "installs thor files" do
ARGV.replace %W(install #{@location})
silence_warnings do
silence(:stdout) { Thor::Runner.start }
context "with remote thor files" do
let(:location) { "https://example.com/Thorfile" }

it "installs thor files" do
allow(Thor::LineEditor).to receive(:readline).and_return("Y", "random")
stub_request(:get, location).to_return(:body => "class Foo < Thor; end")
path = File.join(Thor::Util.thor_root, Digest::MD5.hexdigest(location + "random"))
expect(File).to receive(:open).with(path, "w")
expect { silence(:stdout) { Thor::Runner.start(%W(install #{location})) } }.not_to raise_error
end

it "shows proper errors" do
expect(Thor::Runner).to receive :exit
expect(URI).to receive(:open).with(location).and_raise(OpenURI::HTTPError.new("foo", StringIO.new))
content = capture(:stderr) { Thor::Runner.start(%W(install #{location})) }
expect(content).to include("Error opening URI '#{location}'")
end
end
end
Expand Down

0 comments on commit 59ad393

Please sign in to comment.