Skip to content

Commit

Permalink
Merge pull request #23 from sportngin/brew-gem-breakup
Browse files Browse the repository at this point in the history
Brew gem breakup
  • Loading branch information
nicksieger committed May 17, 2016
2 parents 43421fc + e102d97 commit 321d072
Show file tree
Hide file tree
Showing 17 changed files with 379 additions and 109 deletions.
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/.bundle/
/.yardoc
/Gemfile.lock
/_yardoc/
/coverage/
/doc/
/pkg/
/spec/reports/
/tmp/
2 changes: 2 additions & 0 deletions .rspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
--format documentation
--color
1 change: 1 addition & 0 deletions .ruby-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2.3.1
5 changes: 5 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
sudo: false
language: ruby
rvm:
- 2.2.2
before_install: gem install bundler -v 1.12.3
4 changes: 4 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
source 'https://rubygems.org'

# Specify your gem's dependencies in brew-gem.gemspec
gemspec
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,17 @@ sudo /usr/bin/gem update --system
Install
-------

There are two ways to install `brew-gem`, via Homebrew or via Rubygems. Usually
the Rubygems release will track ahead of the Homebrew recipe, so to receive the
latest features, use the Rubygems install instructions.

Via Rubygems:

gem install brew-gem
brew-gem install brew-gem

Via Homebrew:

brew install brew-gem


Expand Down
9 changes: 9 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
require "bundler/gem_tasks"
require "rspec/core/rake_task"

RSpec::Core::RakeTask.new(:spec) do |t|
# Specify RSPECOPTS=... on the rake command line to set extra RSpec flags
t.rspec_opts = ENV['RSPECOPTS'] if ENV['RSPECOPTS']
end

task :default => :spec
113 changes: 4 additions & 109 deletions bin/brew-gem
Original file line number Diff line number Diff line change
@@ -1,112 +1,7 @@
#!/usr/bin/env ruby

if !ARGV[0] || ARGV[0] == 'help'
abort "Please specify a gem name (e.g. brew gem command <name>)
install - Install a brew gem, accepts an optional version argument (e.g. brew gem install <name> <version>)
upgrade - Upgrade to the latest version of a brew gem
uninstall - Uninstall a brew gem"
end
BREW_GEM_HOME = File.expand_path('../..', __FILE__)

command = ARGV[0]
name = ARGV[1]
gems = `gem list --remote "^#{name}$"`.lines
unless gems.detect { |f| f =~ /^#{name} \(([^\s,]+).*\)/ }
abort "Could not find a valid gem '#{name}'"
end
version = ARGV[2] || $1

klass = 'Gem' + name.capitalize.gsub(/[-_.\s]([a-zA-Z0-9])/) { $1.upcase }.gsub('+', 'x')
user_gemrc = "#{ENV['HOME']}/.gemrc"

require 'erb'
template = ERB.new(File.read(__FILE__).split(/^__END__$/, 2)[1].strip)

require 'tempfile'
filename = File.join Dir.tmpdir, "gem-#{name}.rb"

begin
open(filename, 'w') do |f|
f.puts template.result(binding)
end

system "brew #{command} #{filename}"
ensure
File.unlink filename
end

__END__
require 'formula'
require 'fileutils'

class RubyGemsDownloadStrategy < AbstractDownloadStrategy
def fetch
ohai "Fetching <%= name %> from gem source"
HOMEBREW_CACHE.cd do
system "gem", "fetch", "<%= name %>", "--version", resource.version
end
end

def cached_location
Pathname.new("#{HOMEBREW_CACHE}/<%= name %>-#{resource.version}.gem")
end

def clear_cache
cached_location.unlink if cached_location.exist?
end
end

class <%= klass %> < Formula
url "<%= name %>", :using => RubyGemsDownloadStrategy
version "<%= version %>"

def install
# Copy user's RubyGems config to temporary build home.
buildpath_gemrc = "#{ENV['HOME']}/.gemrc"
if File.exists?('<%= user_gemrc %>') && !File.exists?(buildpath_gemrc)
FileUtils.cp('<%= user_gemrc %>', buildpath_gemrc)
end

# set GEM_HOME and GEM_PATH to make sure we package all the dependent gems
# together without accidently picking up other gems on the gem path since
# they might not be there if, say, we change to a different rvm gemset
ENV['GEM_HOME']="#{prefix}"
ENV['GEM_PATH']="#{prefix}"
system "gem", "install", cached_download,
"--no-ri",
"--no-rdoc",
"--no-wrapper",
"--no-user-install",
"--install-dir", prefix,
"--bindir", bin

bin.rmtree if bin.exist?
bin.mkpath

brew_gem_prefix = prefix+"gems/<%= name %>-#{version}"

completion_for_bash = Dir[
"#{brew_gem_prefix}/completion{s,}/<%= name %>.{bash,sh}",
"#{brew_gem_prefix}/**/<%= name %>_completion{s,}.{bash,sh}"
].first
bash_completion.install completion_for_bash if completion_for_bash

completion_for_zsh = Dir[
"#{brew_gem_prefix}/completions/<%= name %>.zsh",
"#{brew_gem_prefix}/**/<%= name %>_completion{s,}.zsh"
].first
zsh_completion.install completion_for_zsh if completion_for_zsh

ruby_libs = Dir.glob("#{prefix}/gems/*/lib")
Pathname.glob("#{brew_gem_prefix}/bin/*").each do |file|
(bin+file.basename).open('w') do |f|
f << <<-RUBY
#!/usr/bin/ruby
ENV['GEM_HOME']="#{prefix}"
ENV['GEM_PATH']="#{prefix}"
$:.unshift(#{ruby_libs.map(&:inspect).join(",")})
load "#{file}"
RUBY
end
end
end
end
$LOAD_PATH.unshift(File.join(BREW_GEM_HOME, 'lib'))
require 'brew/gem'
Brew::Gem::CLI.run(ARGV)
33 changes: 33 additions & 0 deletions brew-gem.gemspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'brew/gem/version'

Gem::Specification.new do |spec|
spec.name = "brew-gem"
spec.version = Brew::Gem::VERSION
spec.authors = ["Nick Sieger"]
spec.email = ["[email protected]"]

spec.summary = %q{Generate Homebrew formulas to install standalone ruby gems.}
spec.description = %q{This gem can be installed with "brew install brew-gem" and used to install gems with "brew gem install <gem>".}
spec.homepage = "https://github.com/sportngin/brew-gem"

# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
# to allow pushing to a single host or delete this section to allow pushing to any host.
if spec.respond_to?(:metadata)
spec.metadata['allowed_push_host'] = "https://rubygems.org/"
else
raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
end

spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]

spec.add_development_dependency "bundler", "~> 1.12"
spec.add_development_dependency "rake", "~> 10.0"
spec.add_development_dependency "rspec", "~> 3.0"
spec.add_development_dependency "aruba", "~> 0.14.0"
end
7 changes: 7 additions & 0 deletions lib/brew/gem.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module Brew
module Gem
end
end

require "brew/gem/cli"
require "brew/gem/version"
73 changes: 73 additions & 0 deletions lib/brew/gem/cli.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
require 'erb'
require 'tempfile'

module Brew::Gem::CLI
module_function

COMMANDS = {
"install" => ("Install a brew gem, accepts an optional version argument\n" +
" (e.g. brew gem install <name> [version])"),
"upgrade" => "Upgrade to the latest version of a brew gem",
"uninstall" => "Uninstall a brew gem",
"info" => "Show information for an installed gem",
"help" => "This message"
}

def help_msg
(["Please specify a gem name (e.g. brew gem command <name>)"] +
COMMANDS.map {|name, desc| " #{name} - #{desc}"}).join("\n")
end

def fetch_version(name, version = nil)
gems = `gem list --remote "^#{name}$"`.lines

unless gems.detect { |f| f =~ /^#{name} \(([^\s,]+).*\)/ }
abort "Could not find a valid gem '#{name}'"
end

version ||= $1
version
end

def process_args(args)
abort help_msg unless args[0]
abort "unknown command: #{args[0]}\n#{help_msg}" unless COMMANDS.keys.include?(args[0])

if args[0] == 'help'
STDERR.puts help_msg
exit 0
end

args[0..2]
end

def expand_formula(name, version)
klass = 'Gem' + name.capitalize.gsub(/[-_.\s]([a-zA-Z0-9])/) { $1.upcase }.gsub('+', 'x')
user_gemrc = "#{ENV['HOME']}/.gemrc"
template_file = File.expand_path('../formula.rb.erb', __FILE__)
template = ERB.new(File.read(template_file))
template.result(binding)
end

def with_temp_formula(name, version)
filename = File.join Dir.tmpdir, "gem-#{name}.rb"

open(filename, 'w') do |f|
f.puts expand_formula(name, version)
end

yield filename
ensure
File.unlink filename
end

def run(args = ARGV)
command, name, supplied_version = process_args(args)

version = fetch_version(name, supplied_version)

with_temp_formula(name, version) do |filename|
system "brew #{command} #{filename}"
end
end
end
77 changes: 77 additions & 0 deletions lib/brew/gem/formula.rb.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# -*- ruby -*-

require 'formula'
require 'fileutils'

class RubyGemsDownloadStrategy < AbstractDownloadStrategy
def fetch
ohai "Fetching <%= name %> from gem source"
HOMEBREW_CACHE.cd do
system "gem", "fetch", "<%= name %>", "--version", resource.version
end
end

def cached_location
Pathname.new("#{HOMEBREW_CACHE}/<%= name %>-#{resource.version}.gem")
end

def clear_cache
cached_location.unlink if cached_location.exist?
end
end

class <%= klass %> < Formula
url "<%= name %>", :using => RubyGemsDownloadStrategy
version "<%= version %>"
def install
# Copy user's RubyGems config to temporary build home.
buildpath_gemrc = "#{ENV['HOME']}/.gemrc"
if File.exists?('<%= user_gemrc %>') && !File.exists?(buildpath_gemrc)
FileUtils.cp('<%= user_gemrc %>', buildpath_gemrc)
end
# set GEM_HOME and GEM_PATH to make sure we package all the dependent gems
# together without accidently picking up other gems on the gem path since
# they might not be there if, say, we change to a different rvm gemset
ENV['GEM_HOME']="#{prefix}"
ENV['GEM_PATH']="#{prefix}"
system "gem", "install", cached_download,
"--no-ri",
"--no-rdoc",
"--no-wrapper",
"--no-user-install",
"--install-dir", prefix,
"--bindir", bin
bin.rmtree if bin.exist?
bin.mkpath
brew_gem_prefix = prefix+"gems/<%= name %>-#{version}"
completion_for_bash = Dir[
"#{brew_gem_prefix}/completion{s,}/<%= name %>.{bash,sh}",
"#{brew_gem_prefix}/**/<%= name %>_completion{s,}.{bash,sh}"
].first
bash_completion.install completion_for_bash if completion_for_bash

completion_for_zsh = Dir[
"#{brew_gem_prefix}/completions/<%= name %>.zsh",
"#{brew_gem_prefix}/**/<%= name %>_completion{s,}.zsh"
].first
zsh_completion.install completion_for_zsh if completion_for_zsh

ruby_libs = Dir.glob("#{prefix}/gems/*/lib")
Pathname.glob("#{brew_gem_prefix}/bin/*").each do |file|
(bin+file.basename).open('w') do |f|
f << <<-RUBY
#!/usr/bin/ruby
ENV['GEM_HOME']="#{prefix}"
ENV['GEM_PATH']="#{prefix}"
$:.unshift(#{ruby_libs.map(&:inspect).join(",")})
load "#{file}"
RUBY
end
end
end
end
5 changes: 5 additions & 0 deletions lib/brew/gem/version.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module Brew
module Gem
VERSION = "0.7.0"
end
end
17 changes: 17 additions & 0 deletions spec/brew/gem/cli_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
require 'spec_helper'

RSpec.describe Brew::Gem::CLI do
context "#expand_formula" do
subject(:formula) { described_class.expand_formula("foo-bar", "1.2.3") }

it "generates valid Ruby" do
IO.popen("ruby -c -", "r+") { |f| f.puts formula }
expect($?).to be_success
end

it { is_expected.to match(/class GemFooBar < Formula/) }

it { is_expected.to match(/version "1\.2\.3"/) }
end

end
Loading

0 comments on commit 321d072

Please sign in to comment.