我如何告诉Bundler将git存储库视为rubygem源?

时间:2017-03-17 09:11:44

标签: ruby git rubygems bundler gemfile

我有一个依赖私有宝石的项目和来自rubygems.org的项目。 众所周知,人们可以通过以下方式明确地从git存储库加载gem:

gem 'mygem', :git => git@git.myserver.com:myuser/mygem.git'

但是,这种行为是不可取的,因为我必须为我在gemspec中指定的每个依赖项添加这样的行。此外,这样Bundler将只检查master分支中最新提交的gemspec,如果它不满足需求而失败,而不是在存储库中搜索符合版本要求的(标记的)提交。依赖性。

例如,如果我在gemspec中指定了spec.add_development_dependency "mygem", "~> 1.0.12",那么首次尝试在我的Gemfile中指定mygem的源代码为gem 'mygem', :git => '...', :tag => '1.0.12'。但是如果标签1.0.13的新提交被释放呢?我总是需要手动将Gemfile中的标签说明符调整到最不合适的版本。 当使用gem服务器时,Bundler可以下载specs4.8.gz文件,其中包含所有可用gem和版本的索引列表 - 我想为git设置这种行为,而不需要额外的gem包服务器托管*。宝石文件。

以下是我为我的gemspec提出的建议:

Gem::Specification.new do |spec|
     spec.add_development_dependency "mygem", "~> 1.0.12", "<= 1.0.20"
     ...
     $hook = spec
end

...和我的Gemfile:

source 'https://rubygems.org'
gemspec

# This function scans a repository for a tagged commit fulfilling the requirements of dep
# somewhat equivalent to requesting for and reading in specs4.8.gz
def query_tags dep
    vers = `git tag -l 'v*.*.*'`.split(/\n+/) # store all gem version tags in an array
    vers.each { |ver| ver[0] = '' } # remove leading 'v'
    vers.sort_by{ |ver| Gem::Version.new(ver) } # sort the list
    vers.reverse_each do |ver| # find the latest compatible version
        return ver if dep.match?(dep.name, ver)
    end
    raise "No version in repository found fulfilling the requirements of " + dep.name + "!"
end

unless $hook.nil?
    $hook.dependencies.each do |dep| 
        `mkdir tmpindex` # create a git directory for storing tags
        repo = 'git@git.myserver.com:myuser/' + dep.name + '.git'
        `git -C ./tmpindex init --quiet`
        if system("git -C ./tmpindex remote add origin #{repo}") 
            # fetch all tags in the commit 
            if system("git -C ./tmpindex fetch --all --tags --prune --quiet")
                gem dep.name, :git => repo, :tag => 'v' + query_tags(dep)
            end
        end
        `rm -rf tmpindex`
    end
end

这种方法有一些缺点:

  • 每个捆绑操作(例如bundle exec)而不仅仅是安装或更新时,将扫描远程存储库中的标记,从而减慢所有内容。
  • 将扫描Github以查找属于rubygems上的gem的存储库,而不是私有存储库。因为它们无论如何都会失败,它会毫无意义地减慢一切。

有没有更优雅的方法来实现这一目标?我能对缺点做些什么?有没有明显的陷阱我没有考虑过?

0 个答案:

没有答案