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


这发生在 木偶的 束。

Gemfile  指定

gem "puppet", :path => File.dirname(__FILE__), :require => false

但是我安装的宝石之一 $GEM_HOME 出现在 $: 毕竟。

$ 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 而不是 3.7.3 我检查了git repo。

$ bundle exec irb
irb(main):001:0> require 'puppet'
=> true
irb(main):002:0> Facter.value(:puppetversion)
=> "3.7.5"

为什么Puppet没有从git树加载,我该如何进一步调试呢?

更新

木偶 .gemspec 可能会涉及。它的 聪明 关于指定版本。我现在担心Rubygems确实加载了已安装的 3.7.5 宝石这样 Puppet.version 如实地报告错误的价值,扔掉捆绑者。这可能是发生了什么?

更新2

正如评论中所建议的那样,我尝试静态设置路径和版本 Gemfile

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

至于结果,至少 bundler 在其观点中是一致的;-)

Could not find gem 'puppet (= 3.4.2) ruby' in source at /home/ffrank/git/puppet.
Source contains 'puppet' at: 3.7.3
Run `bundle install` to install missing gems.

10271
2018-04-17 20:53


起源

您使用的是什么版本的捆绑包?这听起来像捆绑器关于2个标记版本的已知问题。 - Chase Gilliam
@ChaseGilliam我可以用bundler重现 1.7.4 和 1.9.4,不幸的是。 - Felix Frank
尝试给它一个像gem“puppet”的绝对路径,:path =>“/ home / puppy / puppet-git-clone” - Chase Gilliam
@ChaseGilliam效果相同。我用它来刺激 bundle update --verbose 并将通过一个小的发现更新问题。 - Felix Frank
以这种方式报告版本是相当典型的,我怀疑这是问题所在。也许尝试在gemfile中指定版本。 - Chase Gilliam


答案:


快速解决方法是添加 -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

看起来这应该是默认行为,因此捆绑器中可能存在错误。


4
2018-05-01 03:07



我喜欢它的简单性。不打电话的时候 ruby 直接,这也将做到: RUBYLIB=lib bundle exec puppet agent --version。 - 但是这种解决方法感觉多余。如果没有其他答案可行,我会接受它。 - Felix Frank


只要你删除了你的 Gemfile.lock 并在尝试之前删除了所有其他版本的gem bundle exec ...虽然没有明确定义同一个问题,但这是一个已知的问题 Bundler 看一下这个:

并且应该在此合并的Pull请求中修复:

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

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


1
2018-04-27 08:09



好的电话,我有一种匍匐的怀疑 hiera 宝石,这取决于 puppet 宝石以某种方式参与其中。但是,将该补丁应用于bundler 1.9.4 没有解决问题。删除 Gemfile.lock 是无效的。该 3.7 宝石是 不 除去。如果没有安装具有不同版本的gem,则不存在整个问题。 - Felix Frank
很抱歉听到这个答案不是那个。发布另一个我遇到类似问题后想到的。 - digitalextremist


尝试这个 :

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

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

为什么你需要虚假?


1
2018-04-28 07:29



该 :require 来自上游。删除它对结果没有影响。 - Felix Frank


在你之前的回答中说了之后,试试这个:

gemspec 到你的 Gemfile 靠近顶部。

如果你这样做,后续 gem ... 电话会覆盖 gemspec 这最终设定版本。

在这里添加:

source ENV['GEM_SOURCE'] || "https://rubygems.org"
gemspec # and let me know if this fixes it

1
2018-04-29 21:06



有趣。还是坏了,但现在我收到了这个警告: lib/puppet/version.rb:10: warning: already initialized constant PUPPETVERSION,来自git repo中的文件。 - Felix Frank
感谢所有的努力,但由于没有解决方案,我不能公平地奖励你。下次好运! - Felix Frank


就像我最近说的那样,我在自己的项目中发现了同样的问题。我通过解决方法解决了这个问题。这个想法本身就是我在这里给出的,我并不是说它是最有效或无错误的方式。这种方法的一种变体对我有用。

它涉及劫持 Gemfile 也许吧 gemspec,取决于现实中的罪犯 - 这一部分仍然未知。我最近的回答,我给出的第二种方法可以解决这个问题。如果没有,您可能需要一个解决方法。 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.33.7.5 ...只需插入你想要的那个。将从依赖项中清除任何其他版本 Bundler 正在与...合作。


1
2018-04-30 09:16



Undefined local variable or method 'dsl' for Gemfile - Felix Frank
更新了。实际上 self 不 dsl。对于那个很抱歉。这是一个例子 Bundler::Dsl - digitalextremist
产生错误。同 --verbose 它说 Gemfile:85:in 'eval_gemfile': undefined method 'each' for #<Bundler::Dependency:0x00000001b594f0> (NoMethodError) 从 $HOME/gems/gems/bundler-1.9.4/lib/bundler/dsl.rb:32:in 'instance_eval' - Felix Frank


我过去遇到了同样的问题,我认为你可以在没有'require:false'参数的情况下指定你的gem,它会查找特定于Ge​​mfile的版本。

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

如果使用'gem'指定'require'选项并运行irb命令 bundle exec irb 它总是加载已声明的宝石的最新版本 require: false 选项。


1



这基本上是WebQube的答案。这样做根本没有用。 bundler 坚持认为 Source contains 'puppet' at: 3.7.3 - Felix Frank