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 27, 2022
1 parent 937c443 commit 439a593
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?\://}

This comment has been minimized.

Copy link
@nobu

nobu Oct 29, 2023

Contributor

Should be \A instead of ^, in general.

This comment has been minimized.

Copy link
@deivid-rodriguez

deivid-rodriguez Oct 30, 2023

Author Contributor

Sure, I just respected the previous style that the code was using but \A seems fine.


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 439a593

Please sign in to comment.