Skip to content

Instantly share code, notes, and snippets.

@bih
Created March 28, 2014 15:45
Show Gist options
  • Save bih/9835839 to your computer and use it in GitHub Desktop.
Save bih/9835839 to your computer and use it in GitHub Desktop.
Parse yo' Gemfile

Parse yo' Gemfile

Want to parse a Gemfile? This finely does it. How you may ask? This file replicates the entire Gemfile functions (aka source, gem and group) and then executes the Gemfile in Ruby.

Security

As it executes the Gemfile, it can potentially contain malicious Ruby code. This could import your project and perform commands and I would recommend executing it in a safe/sandbox environment. An example would be through an external server and use an API. This way it is very easy to replicate your software and it is totally harmless.

<3 Have fun.

Example

Example Gemfile:

source 'http://rubygems.org'

gem 'rake'
gem 'rails'

group :assets do
  gem 'jquery-rails', '1.2.3'
end

Returned value (as a Ruby Hash aka Hash.new):

{
  sources: [
    #<RubyGemSource:0x000000000000 @url="http://rubygems.org">
  ],
  gems: [
    #<RubyGem:0x000000000000 @name="rake" @rubygems_url="http://rubygems.org/gems/rake" @version=nil @group=nil>,
    #<RubyGem:0x000000000000 @name="rails" @rubygems_url="http://rubygems.org/gems/rails" @version=nil @group=nil>,
    #<RubyGem:0x000000000000 @name="jquery-rails" @rubygems_url="http://rubygems.org/gems/jquery-rails" @version="1.2.3" @group="assets">
  ]
}
# Each individual source
# Example: source 'http://rubygems.org'
class RubyGemSource
attr_accessor :url
def initialize(url)
self.url = url
end
end
# Each individual rubygem.
# Example: gem 'rails', '> 1.4.0'
class RubyGem
attr_accessor :name, :rubygems_url, :version, :group
def initialize(name, version = nil, group = nil)
self.name = name
self.rubygems_url = "http://rubygems.org/gem/#{name}"
self.version = version
self.group = group
end
def is_group?(name)
self.group.to_sym == name.to_sym
end
def parse_version(version)
Gem::Version.new(version)
end
end
# A list of all sources and gems.
$output = {
:sources => [],
:gems => []
}
# Fake the Gemfile functions (i.e. source '', gem '' and group do .. end) and bind them to the code above!
def source(url); $output[:sources].push(RubyGemSource.new(url)); end
def group(groupname, &block); $group = groupname.to_s; yield; $group = nil; end
def gem(name, version = nil); $output[:gems].push(RubyGem.new(name, version, $group)); end
# Let's get it started - Black Eyed Peas style.
url = "./Gemfile"
load(url)
# Gimme everything.
puts $output.inspect
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment