Ruby 为什么bundler使用多个gem位置?

Ruby 为什么bundler使用多个gem位置?,ruby,gem,rubygems,bundler,puppet,Ruby,Gem,Rubygems,Bundler,Puppet,这是捆绑式的 Gemfile 但是我在$GEM\u HOME中安装的一个GEM毕竟出现在$:中 $ bundle exec ruby -e 'puts $:' ... /home/puppy/puppet-git-clone/lib ... /usr/lib/ruby/vendor_ruby ... /home/puppy/gems/gems/puppet-3.7.5/lib ... 这本身并不是问题,但显然Ruby将加载Puppet3.7.5,而不是我从git回购中签出的3.7.3 $ bu

这是捆绑式的

Gemfile

但是我在
$GEM\u HOME
中安装的一个GEM毕竟出现在
$:

$ bundle exec ruby -e 'puts $:'
...
/home/puppy/puppet-git-clone/lib
...
/usr/lib/ruby/vendor_ruby
...
/home/puppy/gems/gems/puppet-3.7.5/lib
...
这本身并不是问题,但显然Ruby将加载Puppet
3.7.5
,而不是我从git回购中签出的
3.7.3

$ bundle exec irb
irb(main):001:0> require 'puppet'
=> true
irb(main):002:0> Facter.value(:puppetversion)
=> "3.7.5"
为什么Puppet不是从git树加载的,我如何进一步调试它

更新 木偶
.gempec
可能涉及其中。它是关于指定版本的。我现在担心Rubygems实际上加载了安装的
3.7.5
gem,这样
Puppet.version
就会如实地报告错误的值,从而抛出bundler。这就是发生的事吗

更新2 正如评论中所建议的,我尝试在
Gemfile
中静态设置路径和版本

gem "puppet", "3.4.2", :path => "/home/puppy/puppet-git-clone", :require => false
就结果而言,well-至少bundler的观点是一致的;-)


如果您在尝试
bundle exec
之前删除了
Gemfile.lock
并删除了所有其他版本的gem,则。。。虽然未明确定义为同一问题,但这是捆绑机的已知问题检查:

从这个合并的拉取请求开始,它应该被修复:

这将导致您的“首选来源”受到青睐和使用

(链接用作答案,因为它指的是现有的活动,而不是我可以在答案中放在这里的解决方案。不是仅链接的答案。)

尝试以下方法:

source "file://home/puppy/puppet-git-clone"

gem "puppet", "3.4.2", :path => "/home/puppy/puppet-git-clone"

为什么需要输入false?

在我上一个答案中所说的内容之后,尝试以下方法:

gempec
添加到顶部附近的
Gemfile
。 如果执行此操作,后续的
gem…
调用将覆盖最终设置版本的
gempec

将其添加到此处:
就像我最近说的,我在我自己的项目中发现了与你相同的问题。我已经解决了这个问题。这个想法本身就是我在这里给出的,我并不是说这是最有效或没有bug的方法。这种方法的一种变体对我有效

它包括劫持
Gemfile
,也许还包括
gempec
,这取决于罪犯的实际身份——这一部分还不清楚。我最近的回答,我给出的第二种方法已经可以解决这个问题了。如果没有,您可能需要解决方法。Bundler面临着许多长期的僵局


作为一项工作,插入一名馆长。 我建议,在
Gemfile
的末尾插入一个类似这样的处理器,自己策划
Bundler::Dsl
。我们可以完全专注于你想要解决的宝石,但任何宝石都可以解决

例如。。。这主要是一个概念,它可能运行,但可能有一个bug。你需要使它变硬。这将删除除预期版本之外的所有内容:

PUPPET_VERSION = 'version desired'
until(current = self.dependencies.find { |d| d.name == 'puppet' }) == 1
    current.each { |gem|
        if !gem.version == PUPPET_VERSION
            self.dependencies.delete(current)
        end
    }
end

我不确定你到底想要哪个版本。提到了三个版本,
3.7.3
3.7.5
。。。只要插上你想要的。任何其他版本都将从Bundler使用的依赖项中清除。

快速修复方法是将
-Ilib
添加到ruby命令中:

$ bundle exec ruby -e "require 'puppet'; puts Facter.value(:puppetversion)"
3.7.5

$ bundle exec ruby -Ilib -e "require 'puppet'; puts Facter.value(:puppetversion)"
3.7.3
如果我们比较加载路径,您可以看到添加
-Ilib
会导致第二个加载路径中不存在3.7.5:

$ diff <(bundle exec ruby -e 'puts $:') <(bundle exec ruby -Ilib -e 'puts $:') | grep 'puppet-'
< /Library/Ruby/Gems/2.0.0/gems/puppet-3.7.5/lib

$diff我过去也遇到过同样的问题,我认为您可以在不使用'require:false'参数的情况下指定gem,它将查找特定于Gemfile的版本

gem "puppet", "3.4.2", :path => "/home/puppy/puppet-git-clone"

如果您使用“gem”指定“require”选项,并使用
bundle exec irb
运行irb命令,它将始终加载使用
require:false
选项声明的gems的最新版本。

您使用的bundler版本是什么?这听起来像是bundler在2个带标签的版本之前出现的一个已知问题。@ChaseGilliam我可以用bundler
1.7.4
1.9.4
复制,不幸的是。尝试给它一个像gem“puppet”这样的绝对路径:path=>“/home/pupper/puppet git clone”@ChaseGilliam同样的效果。我使用
bundle update--verbose
四处搜索,并将用一个小发现更新问题。以这种方式报告版本是相当典型的,我怀疑这是问题所在。可以尝试在GEM文件中指定版本。
:require
来自上游。移除它对结果没有影响。好主意,我有一种潜移默化的怀疑,那就是
hiera
gem,它依赖于
puppet
gem。但是,将该修补程序应用于bundler
1.9.4
并不能解决该问题。删除
Gemfile.lock
无效。未删除
3.7
gem。如果没有安装不同版本的gem,那么整个问题就不存在了。很抱歉听到的不是这个答案。在遇到类似问题后,我发布了另一个我想到的。我喜欢它的简单性。当不直接调用ruby时,也会这样做:
RUBYLIB=lib bundle exec puppet代理--version
-但这种变通方法感觉是多余的。如果没有其他答案,我就要了。有趣。还是坏了,但是现在我得到了这个警告:
lib/puppet/version.rb:10:warning:constant PUPPETVERSION已经初始化了,来自git repo中的文件。感谢所有的努力,但是由于没有解决方案,我不能公平地授予你奖杯。祝你下次好运<代码>未定义的局部变量或Gemfile的方法“dsl”
更新了该方法。它实际上是
self
而不是
dsl
。很抱歉。它是
Bundler::Dsl
的一个实例,产生了一个错误。使用
--verbose
它说
Gemfile:85:in'eval_Gemfile:#(NoMethodError)
来自
$HOME/gems/gems/bundler-1.9.4/lib/bundler/dsl.rb:32:in'instance_eval'
这基本上是WebQube的答案。这样做是不可能的
$ bundle exec ruby -e "require 'puppet'; puts Facter.value(:puppetversion)"
3.7.5

$ bundle exec ruby -Ilib -e "require 'puppet'; puts Facter.value(:puppetversion)"
3.7.3
$ diff <(bundle exec ruby -e 'puts $:') <(bundle exec ruby -Ilib -e 'puts $:') | grep 'puppet-'
< /Library/Ruby/Gems/2.0.0/gems/puppet-3.7.5/lib
gem "puppet", "3.4.2", :path => "/home/puppy/puppet-git-clone"