我有一个依赖私有宝石的项目和来自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
这种方法有一些缺点:
有没有更优雅的方法来实现这一目标?我能对缺点做些什么?有没有明显的陷阱我没有考虑过?