Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support thor install <uri> to install remote thor files #787

Merged
merged 1 commit into from
Feb 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 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,6 +46,18 @@ def method_missing(meth, *args)
def install(name) # rubocop:disable Metrics/MethodLength
initialize_thorfiles

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
Expand All @@ -60,11 +70,10 @@ def install(name) # rubocop:disable Metrics/MethodLength
package = :file
contents = open(name, &:read)
end
rescue OpenURI::HTTPError
raise Error, "Error opening URI '#{name}'"
rescue Errno::ENOENT
raise Error, "Error opening file '#{name}'"
end
end

say "Your Thorfile contains:"
say contents
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
29 changes: 25 additions & 4 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,12 +214,13 @@ def when_no_thorfiles_exist
end

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

Expand All @@ -236,11 +237,31 @@ def when_no_thorfiles_exist
end

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

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
end
end