rubygems / bundler

Manage your Ruby application's gem dependencies
https://bundler.io
MIT License
4.88k stars 2k forks source link

NoMethodError: undefined method `prelease?' for nil:NilClass #3639

Closed rye closed 9 years ago

rye commented 9 years ago

Error details

NoMethodError: undefined method `prerelease?' for nil:NilClass
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/lib/bundler/index.rb:165:in `block in search_by_dependency'
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/lib/bundler/index.rb:165:in `each'
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/lib/bundler/index.rb:165:in `all?'
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/lib/bundler/index.rb:165:in `search_by_dependency'
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/lib/bundler/index.rb:78:in `local_search'
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/lib/bundler/index.rb:58:in `search'
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/lib/bundler/resolver.rb:255:in `search_for'
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/lib/bundler/resolver.rb:309:in `block in verify_gemfile_dependencies_are_found!'
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/lib/bundler/resolver.rb:307:in `each'
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/lib/bundler/resolver.rb:307:in `verify_gemfile_dependencies_are_found!'
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/lib/bundler/resolver.rb:199:in `start'
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/lib/bundler/resolver.rb:182:in `resolve'
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/lib/bundler/definition.rb:192:in `resolve'
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/lib/bundler/definition.rb:132:in `specs'
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/lib/bundler/definition.rb:121:in `resolve_remotely!'
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/lib/bundler/installer.rb:79:in `run'
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/lib/bundler/installer.rb:18:in `install'
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/lib/bundler/cli/install.rb:80:in `run'
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/lib/bundler/cli.rb:157:in `install'
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/lib/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command'
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/lib/bundler/vendor/thor/lib/thor.rb:359:in `dispatch'
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/lib/bundler/vendor/thor/lib/thor/base.rb:440:in `start'
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/lib/bundler/cli.rb:10:in `start'
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/bin/bundle:20:in `block in <top (required)>'
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/lib/bundler/friendly_errors.rb:7:in `with_friendly_errors'
  /home/kristofer/.local/lib/ruby/gems/2.2.0/gems/bundler-1.9.6/bin/bundle:18:in `<top (required)>'
  /home/kristofer/.local/bin/bundle:23:in `load'
  /home/kristofer/.local/bin/bundle:23:in `<main>'

Environment

Bundler   1.9.6
Rubygems  2.4.6
Ruby      2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
GEM_HOME  /home/kristofer/.local/lib/ruby/gems/2.2.0
GEM_PATH  /home/kristofer/.local/lib/ruby/gems/2.2.0:/home/kristofer/.gem/ruby/2.2.0
Git       2.1.0

Some further information:

I've got a Gemspec defined, but there isn't a version in it yet.

rye commented 9 years ago

I just added a version to the Gemspec and that solved the issue. This should probably be checked for.

indirect commented 9 years ago

Gemspecs aren't valid without versions, so we should probably throw a useful error here.

On Mon, May 11, 2015 at 9:22 AM, Kristofer Rye notifications@github.com wrote:

I just added a version to the Gemspec and that solved the issue. This should probably be checked for.

Reply to this email directly or view it on GitHub: https://github.com/bundler/bundler/issues/3639#issuecomment-100969120

rye commented 9 years ago

Exactly my thoughts. I haven't contributed to bundler yet, but I'd be glad to make it throw a useful error and submit that.

segiddins commented 9 years ago

Maybe for non-rubygems deps, we could call spec.validate(false)?

fotanus commented 9 years ago

If I got it right, Gem::Specification::validate only exists for ruby > 1.9. Since we have travis for older versions, I suppose we should keep compatible? If is that so, maybe we should create our own validate method, that takes in account only things that we actually need, like version?

segiddins commented 9 years ago

Or maybe we only validate when the method is available?

-Samuel E. Giddins

On May 11, 2015, at 5:28 PM, Felipe Tanus notifications@github.com wrote:

If I got it right, Gem::Specification::validate only exists for ruby > 1.9. Since we have travis for older versions, I suppose we should keep compatible? If is that so, maybe we should create our own validate method, that takes in account only things that we actually need, like version?

— Reply to this email directly or view it on GitHub.

rye commented 9 years ago

I like @fotanus' idea; just check to see if spec.version is non-nil, and, if not, complain. If there's anything else that we should check for, we can do that as well. The main goal is to eliminate the assumption that spec.version is valid.

indirect commented 9 years ago

@fotanus @rye the rubygems_integration.rb file handles the work of normalizing across different RubyGems versions. Create a valid_version? method there, and implement it as a call to #validate or a nil check if #validate isn't present.

fotanus commented 9 years ago

@indirect thanks for the guidance. I have been hacking this for some time now, and I don't think I found the correct place to put the test of a missing version. Is this right?

fotanus commented 9 years ago

I can get a message of, but it is always on the eval line instead on the line mentionated on the issue. So maybe my test got other related issue?

However, I can reproduce the issue with the correct offending line pointed by the OP by using this:

bundle gem test_no_version
cd test_no_version/
sed -i -e "/spec.version/d" test_no_version.gemspec
bundle
indirect commented 9 years ago

@fotanus in 654e44a, I used the #validate method to check on all specifications loaded by gemspec. I also added a test to make sure that the right error would be raised by the method. I hope that makes sense!

fotanus commented 9 years ago

Hi there,

yes, it makes sense! Thanks for showing me!

However, the spec I wrote still fails because of a nil version:

  1) bundle install from an existing gemspec should raise if there is no version on the gemspec
     Failure/Error: expect(error).to match(/version error message/)
       expected "[!] There was an error parsing `Gemfile`: There was a NoMethodError while loading noversion.gemspec: \nundefined method `prerelease?' for nil:NilClass from\n  /home/fotanus/code/bundler/tmp/noversion/noversion.gemspec:6:in `block in <main>'\n. Bundler cannot continue.\n\n #  from /home/fotanus/code/bundler/tmp/bundled_app/Gemfile:2\n #  -------------------------------------------\n #  source \"file:///home/fotanus/code/bundler/tmp/gems/remote2\"\n >  gemspec :path => '/home/fotanus/code/bundler/tmp/noversion'\n #  -------------------------------------------" to match /version error message/
       Diff:
       @@ -1,2 +1,11 @@
       -/version error message/
       +[!] There was an error parsing `Gemfile`: There was a NoMethodError while loading noversion.gemspec: 
       +undefined method `prerelease?' for nil:NilClass from
       +  /home/fotanus/code/bundler/tmp/noversion/noversion.gemspec:6:in `block in <main>'
       +. Bundler cannot continue.
       +
       + #  from /home/fotanus/code/bundler/tmp/bundled_app/Gemfile:2
       + #  -------------------------------------------
       + #  source "file:///home/fotanus/code/bundler/tmp/gems/remote2"
       + >  gemspec :path => '/home/fotanus/code/bundler/tmp/noversion'
       + #  -------------------------------------------

Is it silly to care about this case or should I try to fix it?

indirect commented 9 years ago

@fotanus I think it's probably okay to stop here. With commit 654e44a, Bundler produces this output:

$ bundle check

[!] There was an error parsing `Gemfile`: The gemspec at /Users/andre/src/bundler/testcases/3639/foo/foo.gemspec is not valid. The validation error was 'missing value for attribute version'. Bundler cannot continue.

 #  from /Users/andre/src/bundler/testcases/3639/foo/Gemfile:4
 #  -------------------------------------------
 #  # Specify your gem's dependencies in foo.gemspec
 >  gemspec
 #  -------------------------------------------

when run on a Gemfile containing just gemspec, in a folder with this foo.gemspec:

Gem::Specification.new do |spec|
  spec.name          = "foo"
end
fotanus commented 9 years ago

:+1: