Requiring version in gemspec from git source fails
kaspth opened this issue · comments
Using resque-pause from GitHub with gel fails with:
Fetching sources.....
Resolving dependencies...Traceback (most recent call last):
7: from -e:1:in `<main>'
6: from /Users/kaspth/.gem/ruby/2.6.0/gems/gel-0.3.0/lib/gel/gemspec_parser.rb:90:in `parse'
5: from /Users/kaspth/.gem/ruby/2.6.0/gems/gel-0.3.0/lib/gel/gemspec_parser.rb:90:in `chdir'
4: from /Users/kaspth/.gem/ruby/2.6.0/gems/gel-0.3.0/lib/gel/gemspec_parser.rb:91:in `block in parse'
3: from /Users/kaspth/.gem/ruby/2.6.0/gems/gel-0.3.0/lib/gel/gemspec_parser.rb:91:in `eval'
2: from /Users/kaspth/.local/gel/git/resque-pause-45d8b943d8586/resque-pause.gemspec:5:in `context'
1: from /Users/kaspth/.gem/ruby/2.6.0/gems/gel-0.3.0/lib/gel/gemspec_parser.rb:26:in `new'
/Users/kaspth/.local/gel/git/resque-pause-45d8b943d8586/resque-pause.gemspec:7:in `block in context': uninitialized constant Gel::GemspecParser::Context::Resque (NameError)
ERROR: Gemspec parse failed
Resque
isn't defined at the time because the earlier require "version"
ends up resolving to another activated gem's version.rb
(in my testing from base32) via
gel/lib/gel/compatibility/rubygems.rb
Line 197 in 1cf6653
Not sure what the right solution is here, if Gel needs to activate the gem before parsing the gemspecs.
Reproduction script
set -ex
mkdir -p holder
cd holder
cat << GEMFILE > Gemfile
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gem "resque-pause", github: "wandenberg/resque-pause"
GEMFILE
gel lock
Hmm.. this one might be tricky.
We can't activate the gem before the load the gemspec, because we're loading the gemspec in order to activate the gem: until we've done so, we don't even know the require_paths
, say.
That leaves us in a situation where a gem is supplying "version"
, and the local load path is attempting to override that by also supplying a file by the same name... which is a designed impossibility in Gel: the load path optimisations are built around the rule that the 'application' can't override a file that's supplied by a gem.
It's unfortunate there are multiple gems polluting the top-level require namespace like that. 😕
Solutions that come to mind:
- implement a custom resolve order for
require "version"
, on the assumption that this pattern is going to affect more gems, but may be unique to that particular filename -- feels like a band-aid, but limits the scope of the change - lock the environment to disallow all gem access inside gemspec (we don't know about any legitimately declared dependencies yet, because that's one of the things we're getting from the gemspec) -- more pure, but more likely to break on differently-odd gemspecs, like this
- declare those gemspecs to be malformed, and that we can't support them (notably this only affects a git/path reference -- the compiled
.gem
will contain a standard well-formed gemspec, notwithstanding the fact they're both exporting a file that's outside their respective namespaces)
Option 3 is looking pretty appealing at the moment.. how much of an adoption hurdle would that be for you? I see https://github.com/basecamp/resque-pause exists (and is presumably why you need the git reference in the first place); how do you feel about a bit of:
-$:.push File.expand_path("../lib", __FILE__)
-require "version"
+require File.expand_path("../lib/version", __FILE__)
Still not sure what to do about this one 😕