Skip to content

Commit

Permalink
fix: output an informative error when the gemspec parsed is not valid…
Browse files Browse the repository at this point in the history
… Ruby
  • Loading branch information
jcouball committed Oct 30, 2024
1 parent 2147776 commit ea05a44
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 9 deletions.
2 changes: 1 addition & 1 deletion lib/bundler/gem_bytes/actions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def add_dependency(dependency_type, gem_name, version_constraint, force: false,
source = File.read(gemspec)
updated_source = Bundler::GemBytes::Gemspec::UpsertDependency.new(
dependency_type, gem_name, version_constraint, force: force
).call(source)
).call(source, path: gemspec)
File.write(gemspec, updated_source)
end
end
Expand Down
26 changes: 21 additions & 5 deletions lib/bundler/gem_bytes/gemspec/upsert_dependency.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ def initialize(dependency_type, gem_name, version_constraint, force: false)
# Returns the content of the gemspec file with the new/updated dependency
#
# @param code [String] The content of the gemspec file
# @param path [String] This should be the path to the gemspspec file
#
# path is used to generate error messages only
#
# @return [String] The updated gemspec content with the new/added dependency
#
Expand All @@ -112,12 +115,9 @@ def initialize(dependency_type, gem_name, version_constraint, force: false)
# updated_code = add_dependency.call(code)
# puts updated_code
#
#
def call(code)
ast = RuboCop::AST::ProcessedSource.new(code, ruby_version).ast
buffer = Parser::Source::Buffer.new('(string)', source: code)
def call(code, path: '(string)')
@found_gemspec_block = false
rewrite(buffer, ast).tap do |_result|
rewrite(*parse(code, path)).tap do |_result|
raise ArgumentError, 'Gem::Specification block not found' unless found_gemspec_block
end
end
Expand Down Expand Up @@ -161,6 +161,22 @@ def on_send(node)

private

# Parses the given code into an AST
# @param code [String] The code to parse
# @param path [String] The path to the file being parsed (used for error messages only)
# @return [Array<Parser::AST::Node, Parser::Source::Buffer>] The AST and buffer
# @api private
def parse(code, path)
buffer = Parser::Source::Buffer.new(path, source: code)
processed_source = RuboCop::AST::ProcessedSource.new(code, ruby_version, path)
unless processed_source.valid_syntax?
raise "Invalid syntax in #{path}\n#{processed_source.diagnostics.map(&:render).join("\n")}"
end

ast = processed_source.ast
[buffer, ast]
end

# Adds or updates the given dependency in the Gem::Specification block
# @param node [Parser::AST::Node] The block node within the AST
# @return [void]
Expand Down
6 changes: 3 additions & 3 deletions spec/features/actions_steps.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def command_err = @command_err
def command_status = @command_status
# rubocop:enable Style/TrivialAccessors

def run_command(command, raise_on_fail: true, failure_message: "#{command[0]} failed")
def run_command(command, raise_on_failure: true, failure_message: "#{command[0]} failed")
out_buffer = StringIO.new
out_pipe = ProcessExecuter::MonitoredPipe.new(out_buffer)
err_buffer = StringIO.new
Expand All @@ -43,7 +43,7 @@ def run_command(command, raise_on_fail: true, failure_message: "#{command[0]} fa
@command_err = err_buffer.string
@command_status = status

raise "#{failure_message}: #{command_err}" if raise_on_fail && !command_status.success?
raise "#{failure_message}: #{command_err}" if raise_on_failure && !command_status.success?
end
end

Expand Down Expand Up @@ -74,7 +74,7 @@ def run_command(command, raise_on_fail: true, failure_message: "#{command[0]} fa

step 'I run :command' do |command|
Dir.chdir(gem_project_dir) do
run_command(command.split, fail_on_error: false)
run_command(command.split, raise_on_failure: false)
end
end

Expand Down
10 changes: 10 additions & 0 deletions spec/lib/bundler/gem_bytes/gemspec/upsert_dependency_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@
describe '#call' do
subject { instance.call(gemspec) }

context 'when the gemspec is not valid Ruby code' do
let(:gemspec) { <<~GEMSPEC }
This is not valid Ruby code. Please fix this file to continue.
GEMSPEC

it 'raises an error' do
expect { subject }.to raise_error(RuntimeError, /Invalid syntax in \(string\)/)
end
end

context 'when the gemspec does not contain a Gem::Specification block' do
let(:gemspec) { <<~GEMSPEC }
puts 'Hello, world!'
Expand Down

0 comments on commit ea05a44

Please sign in to comment.