This repository has been archived by the owner on Nov 9, 2017. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
/
rpg-parse-gemfile.rb
108 lines (96 loc) · 2.84 KB
/
rpg-parse-gemfile.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
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