Skip to content

Commit

Permalink
Merge pull request #787 from deivid-rodriguez/support-uris
Browse files Browse the repository at this point in the history
Support `thor install <uri>` to install remote thor files
  • Loading branch information
rafaelfranca committed Feb 8, 2023
2 parents 264d8b5 + 439a593 commit 0e40ffa
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 40 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
65 changes: 43 additions & 22 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,52 @@ 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")

path = File.join(Thor::Util.thor_root, Digest::SHA256.hexdigest(@location + "random"))
expect(File).to receive(:open).with(path, "w")
end
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::SHA256.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::SHA256.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 0e40ffa

Please sign in to comment.