Skip to content
This repository has been archived by the owner on Nov 9, 2017. It is now read-only.

Commit

Permalink
Added rpg-parse-gemfile command
Browse files Browse the repository at this point in the history
  • Loading branch information
Rich Meyers committed Sep 26, 2011
1 parent 94eda48 commit 7390014
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -39,6 +39,7 @@ rpg-resolve.html
rpg-status.html
rpg-package-install
rpg-package-register
rpg-parse-gemfile
rpg-parse-package-list
rpg-solve
rpg-unpack
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Expand Up @@ -28,7 +28,7 @@ PROGRAMPROGRAMS = \
rpg-outdated rpg-package-list rpg-package-register rpg-package-install \
rpg-unpack rpg-package-spec rpg-parse-index rpg-shit-list \
rpg-prepare rpg-complete rpg-help rpg-package-index rpg-dependencies \
rpg-leaves rpg-manifest rpg-solve rpg-diff
rpg-leaves rpg-manifest rpg-solve rpg-diff rpg-parse-gemfile

DEADPROGRAMS = \
rpg-update rpg-status rpg-parse-package-list rpg-version-test
Expand Down
108 changes: 108 additions & 0 deletions rpg-parse-gemfile.rb
@@ -0,0 +1,108 @@
#!/usr/bin/env ruby
# The `rpg-parse-gemfile` program reads a Bundler Gemfile and writes a
# list of packages on standard output suitable for feeding to `rpg-install`.
#
# Usage
# -----
#
# Given a project with a Gemfile, it is possible to install its dependencies
# by running:
#
# rpg install $(rpg parse-gemfile /path/to/Gemfile)
#
# Caveats
# -------
#
# At this time only top-level gem statements are actually supported.
# All options are ignored. All groups other than the top-level group are
# ignored. All other statements are ignored.
#
# Bundler uses dependency declarations in all groups when resolving
# dependencies, even in groups that are not being installed.
# See http://yehudakatz.com/2010/05/09/the-how-and-why-of-bundler-groups/,
# section "Consistency". This may render a Gemfile unresolvable if, for
# example, the test group specifies conflicting or broken dependencies, even
# for users who don't want to install the test group. rpg ignores all groups
# that are not being installed during dependency resolution. As a consequence,
# rpg and Bundler may install different sets of packages from the same Gemfile.
USAGE = <<BANNER
Usage: rpg-parse-gemfile [PATH]
Convert Bundler Gemfile to a list of packages suitable for installation.
Reads a Gemfile located at specified PATH, or standard input, and writes
a list of packages suitable for feeding to rpg-install on standard output.
Try: rpg install $(rpg parse-gemfile /path/to/Gemfile)
BANNER

if ARGV.include?('--help') || ARGV.length > 1 || ARGV.empty? && STDIN.tty?
puts USAGE
exit 2
end

class GemfileParser
def initialize
@packages = []
end

def parse(gemfile_text, file=nil)
eval(gemfile_text, nil, file)
end

def method_missing(name, *args)
#puts "Ignoring #{name}"
end

def gem(name, *args)
unless args.first.is_a?(Hash)
version = args.shift
end
options = args.shift || {}
@packages << {
:name => name, :version => version, :options => options,
:group => @in_group,
}
end

def group(name)
if @in_group
raise ArgumentError, 'Nested groups are not supported'
end
@in_group = name
yield
@in_group = nil
end

def print
@packages.each do |package|
next if package[:group]
version_op, version_value = canonicalize_version(package[:version])
puts "#{package[:name]} #{version_op} #{version_value}"
end
end

def canonicalize_version(version)
if version.nil?
return ['>=', '0']
end
unless version =~ /^([>=~]*)(\d.+)$/
raise ArgumentError, "Invalid version specification: #{version}"
end
op, value = $1, $2
if op.empty?
op = '='
end
return [op, value]
end
end

if (file = ARGV.shift) && file != '-'
text = File.read(file)
else
file = '<stdin>'
text = STDIN.read
end

parser = GemfileParser.new
parser.parse(text, file)
parser.print

0 comments on commit 7390014

Please sign in to comment.