Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

executable file 162 lines (142 sloc) 4.554 kB
#!/usr/bin/env ruby
# vim: fileencoding=utf-8
# vim: ts=2 sw=2 sts=2 et
require 'rubygems'
require 'bundler'
require 'fileutils'
require 'logger'
# Rewrite git sources in Gemfile and lock files to paths
#
# Usage: transform_git_source path/to/dir_w_Gemfile path/to/git/checkout
def `(cmd)
@logger.debug "executing #{cmd}"
result = super
raise RuntimeError, "error while attempting to execute #{cmd}" unless $?.exitstatus == 0
result
end
def checkout(spec, path)
unless path.join('.git').exist?
path.parent.mkpath
path.rmtree if path.exist?
%x(git clone --no-checkout #{spec.source.uri} #{path})
end
Dir.chdir(path) do
%x(git fetch --quiet --tags #{spec.source.uri})
# This is gross, but why do they keep this private?
revision = spec.source.send(:revision)
%x(git reset --hard #{revision})
end
end
# Derived from Bundler::Definition#to_lock
# Copyright Bundler contributors
# Portions copyright (c) 2010 André Arko
# Portions copyright (c) 2009 Engine Yard
def to_lock(specs, platforms, dependencies)
out = ""
specs.map {|s| s.source}.sort_by { |s| s.class.to_s }.uniq.each do |source|
# Add the source header
out << source.to_lock
# Find all specs for this source
specs.
select { |s| s.source == source }.
# This needs to be sorted by full name so that
# gems with the same name, but different platform
# are ordered consistantly
sort_by { |s| s.full_name }.
each do |spec|
next if spec.name == 'bundler'
out << spec.to_lock
end
out << "\n"
end
out << "PLATFORMS\n"
platforms.map { |p| p.to_s }.sort.each do |p|
out << " #{p}\n"
end
out << "\n"
out << "DEPENDENCIES\n"
handled = []
dependencies.
sort_by { |d| d.to_s }.
each do |dep|
next if handled.include?(dep.name)
out << dep.to_lock
handled << dep.name
end
out
end
def rewrite_lockfile(lockfile, checkout_base)
parser = Bundler::LockfileParser.new(lockfile.read)
candidates = parser.specs.select { |s| Bundler::Source::Git === s.source }
if candidates.empty?
@logger.info 'Nothing to see here, move along'
return
end
gemsrc = parser.sources.find { |s| Bundler::Source::Rubygems === s } ||
Bundler::Source::Rubygems.from_lock('remote' => 'http://rubygems.org')
lockfile.parent.join('vendor', 'cache').mkpath
candidates.each do |spec|
# TODO: shall i sanitize spec.name?
checkout_dir = checkout_base.join(spec.name)
checkout(spec, checkout_dir)
# TODO error handling
gem_dir = Pathname.glob("#{checkout_dir}/**/#{spec.name}.gemspec")[0].parent
Dir.chdir(gem_dir) do |dir|
%x(gem build #{spec.name}.gemspec)
gempath = gem_dir.join("#{spec.name}-#{spec.version}.gem")
FileUtils.link([gempath.to_s], lockfile.parent.join('vendor', 'cache').to_s, :verbose => true)
end
spec.source = gemsrc
# make the dependency have "no specified source"
parser.dependencies.find { |d| d.name == spec.name }.source = nil
end
lockfile.open('w') do |f|
f.puts to_lock(parser.specs, parser.platforms, parser.dependencies)
end
end
# We don't attempt to be a full ruby parser, only rewrite Gemfiles we wrote
def rewrite_gemfile(gemfile, checkout_base)
out = ''
probe = Object.new
class << probe
attr_reader :name, :version, :options, :path
def gem(name, *args)
@name = name
@options = args.last.is_a?(Hash) ? args.pop : {}
@version = args
unless @options.include?(:git)
raise ArgumentError, ':git option expected, none found'
end
end
end
gemfile.each_line do |line|
case line
when /^\s*gem.*:git/
if line =~ /#.*:git/ && line !~ /^[^#]+:git/
out << line
next
end
probe.instance_eval(line)
out << "gem #{probe.name.inspect}"
out << ", #{probe.version.map(&:inspect).join(', ')}" unless probe.version.empty?
out << "\n"
else
out << line
end
end
gemfile.open('w') { |f| f.write(out) }
end
if __FILE__ == $0
unless ARGV.length == 2
puts <<-USAGE
Incorrect number of arguments! Usage:
#{File.basename(__FILE__)} path/to/dir_with_Gemfile path/to/place/git/checkouts
USAGE
exit 1
end
@logger = Logger.new(STDERR)
project_dir, checkout_base = ARGV.map { |x| Pathname.new(x).expand_path }
ENV['BUNDLE_GEMFILE'] = project_dir.join('Gemfile').to_s
rewrite_lockfile(project_dir.join('Gemfile.lock'), checkout_base)
rewrite_gemfile(project_dir.join('Gemfile'), checkout_base)
end
Jump to Line
Something went wrong with that request. Please try again.