yeah it's all consolidated now

This commit is contained in:
John Bintz 2012-06-05 15:29:27 -04:00
parent 033ba8a54c
commit 1a5f0142df
5 changed files with 144 additions and 138 deletions

View File

@ -3,7 +3,7 @@
I like to do these things in all my projects:
* Have all my tests run before committing. I don't like buying ice cream for the team on test failures.
* If I'm developing gems alongside this project, I use a `Gemfile.erb` to get around the "one gem, one source" issue in
* If I'm developing gems alongside this project, I use a `Gemfile.penchant` to get around the "one gem, one source" issue in
current versions of Bundler.
* If I'm moving to different machines or (heaven forbid!) having other developers work on the project, I want to make
getting all those local gems as easy as possible.
@ -14,27 +14,36 @@ This gem makes that easier!
Installs a bunch of scripts into the `scripts` directory of your project:
* `gemfile` which switches between `Gemfile.erb` environments
* `gemfile` which switches between `Gemfile.penchant` environments
* `install-git-hooks` which will do just what it says
* `hooks`, several git hooks that the prior script symlinks into .git/hooks for you
* `initialize-environment`, which bootstraps your local environment so you can get up and running
## Gemfile.erb?!
## Gemfile.penchant?!
Yeah, it's a `Gemfile` with ERB in it:
Yeah, it's a `Gemfile` with some extras:
``` erb
<% env :local do %>
gem 'guard', :path => '../guard'
<% end %>
``` ruby
source :rubygems
<% env :remote do %>
gem 'guard', :git => 'git://github.com/johnbintz/guard.git'
<% end %>
gem 'rails', '3.2.3'
gems 'rake', 'nokogiri', 'rack-rewrite'
<% no_deployment do %>
gem 'os-specific-things'
<% end %>
no_deployment do
group :development, :test do
gem 'rspec', '~> 2.6.0'
dev_gems = %w{flowerbox guard-flowerbox}
env :local do
gems dev_gems, :path => '../%s'
end
env :remote do
gems dev_gems, :git => 'git://github.com/johnbintz/%s.git'
end
end
end
```
Use `script/gemfile local` to get at the local ones, and `script/gemfile remote` to get at the remote ones.
@ -49,8 +58,8 @@ remote servers. *Very* helpful when you have OS-specific gems and are developing
and deploying on another, or if you don't want to deal with the dependencies for your testing
frameworks:
``` erb
<% no_deployment do %>
``` ruby
no_deployment do
require 'rbconfig'
case RbConfig::CONFIG['host_os']
when /darwin/
@ -64,7 +73,7 @@ frameworks:
group :test do
# ... all your testing libraries you won't need on the deployed end ...
end
<% end %>
end
```
Run `penchant gemfile ENV --deployment` to get this behavior. This is run by default when the
@ -74,8 +83,8 @@ pre-commit git hook runs, but only after the default Rake task passes.
Get new developers up to speed fast! `script/initialize-environment` does the following when run:
* Check out any remote repos found in `Gemfile.erb` to the same directory where your current project lives.
That way, you can have your `Gemfile.erb` set up as above and everything works cleanly.
* Check out any remote repos found in `Gemfile.penchant` to the same directory where your current project lives.
That way, you can have your `Gemfile.penchant` set up as above and everything works cleanly.
* Runs `script/gemfile remote` to set your project to using remote repositories.
* Runs `rake bootstrap` for the project if it exists.

View File

@ -30,7 +30,7 @@ class PenchantCLI < Thor
method_options :dir => 'script'
def convert
install
FileUtils.mv 'Gemfile', 'Gemfile.erb'
FileUtils.mv 'Gemfile', 'Gemfile.penchant'
gemfile(:remote)
end
@ -52,7 +52,7 @@ class PenchantCLI < Thor
gemfile = Penchant::Gemfile.new
if !gemfile.has_gemfile?
puts "No Gemfile or Gemfile.erb, exiting."
puts "No Gemfile or Gemfile.penchant, exiting."
exit 1
end
system %{bundle}

View File

@ -49,7 +49,7 @@ Feature: Gemfiles
Scenario: Use a gem list for an operation
Given I have the file "Gemfile.erb" with the content:
"""
<% with_gem_list 'test' do %>
<% gems 'test' do %>
<% env :local, :path => '../%s' do %>
<%= gem %>
<% end %>
@ -65,7 +65,7 @@ Feature: Gemfiles
Scenario: Let gem get additional info
Given I have the file "Gemfile.erb" with the content:
"""
<% with_gem_list 'test' do %>
<% gems 'test' do %>
<%= gem :path => '../%s' %>
<% end %>
"""
@ -74,38 +74,24 @@ Feature: Gemfiles
"""
# generated by penchant, environment: local
gem 'test', :path => %{../test}
gem 'test', {:path=>"../test"}
"""
Scenario: Use a gem list without a block
Given I have the file "Gemfile.erb" with the content:
"""
<% with_gem_list 'test', :path => '../%s' %>
<% gems 'test', :path => '../%s' %>
"""
When I rebuild the Gemfile for "local" mode
Then the file "Gemfile" should have the following content:
"""
# generated by penchant, environment: local
gem 'test', :path => %{../test}
gem 'test', {:path=>"../test"}
"""
Scenario: Use a gem list with an array
Given I have the file "Gemfile.erb" with the content:
"""
<% with_gem_list [ 'test' ], :path => '../%s' %>
"""
When I rebuild the Gemfile for "local" mode
Then the file "Gemfile" should have the following content:
"""
# generated by penchant, environment: local
gem 'test', :path => %{../test}
"""
Scenario: Use another gem list with an array
Given I have the file "Gemfile.erb" with the content:
"""
<% gems [ 'test' ], :path => '../%s' %>
@ -114,7 +100,7 @@ Feature: Gemfiles
Then the file "Gemfile" should have the following content:
"""
# generated by penchant, environment: local
gem 'test', :path => %{../test}
gem 'test', {:path=>"../test"}
"""

View File

@ -49,7 +49,6 @@ Feature: Gemfiles
gem "three", {:path=>"../three"}
"""
@wip
Scenario: Use an env block
Given I have the file "Gemfile.penchant" with the content:
"""

View File

@ -74,31 +74,128 @@ module Penchant
gemfile_header['deployment mode'] != nil
end
class ERBFile
end
class FileProcessor
attr_reader :environment, :is_deployment
class PenchantFile
def self.result(data, *args)
new(data).result(*args)
end
def self.handle_result(&block)
if block
@handle_result = block
else
@handle_result
end
end
def initialize(data)
@data = data
end
attr_reader :environment, :is_deployment
def result(_env, _is_deployment)
@environment = _env.to_s.to_sym
@is_deployment = _is_deployment
@output = []
instance_eval(@data)
handle_result(@data)
@output.join("\n")
end
def env(*args)
yield if args.include?(environment)
end
def no_deployment
yield if !is_deployment
end
protected
def args_to_string(args)
args.inspect[1..-2]
end
def split_args(args)
template = {}
while args.last.instance_of?(Hash)
template.merge!(args.pop)
end
[ args, template ]
end
def call_and_indent_output(block)
index = @output.length
block.call
index.upto(@output.length - 1) do |i|
@output[i] = " " + @output[i]
end
end
def process_options(gem_name, template = {})
Hash[
template.collect { |key, value|
value = value % gem_name if value.respond_to?(:%)
[ key, value ]
}.sort
]
end
end
class ERBFile < FileProcessor
def handle_result(data)
@output << ERB.new(data, nil, nil, '@_erbout').result(binding)
end
def env(check, template = {}, &block)
if check.to_s == @env.to_s
original_erbout = @_erbout.dup
output = instance_eval(&block).lines.to_a
output.each do |line|
if gem_name = line[%r{gem ['"]([^'"]+)['"]}, 1]
line.replace(line.rstrip + process_options(gem_name, template) + "\n")
end
end
@_erbout = original_erbout + output.join
end
end
def gems(*gems)
template = {}
template = gems.pop if gems.last.instance_of?(Hash)
gems.flatten.each do |gem|
@_current_gem = gem
if block_given?
yield
else
@_erbout += gem(template) + "\n"
end
end
end
def gem(template = {})
output = "gem '#{@_current_gem}'"
options = process_options(@_current_gem, template)
if !options.empty?
output += ", #{options.inspect}"
end
output
end
end
class PenchantFile < FileProcessor
def handle_result(data)
instance_eval(data)
end
def gem(*args)
gem_name, template = split_args(args)
@ -135,47 +232,6 @@ module Penchant
def source(*args)
@output << %{source #{args_to_string(args)}}
end
def env(*args)
yield if args.include?(environment)
end
def no_deployment
yield if !is_deployment
end
private
def args_to_string(args)
args.inspect[1..-2]
end
def split_args(args)
template = {}
while args.last.instance_of?(Hash)
template.merge!(args.pop)
end
[ args, template ]
end
def call_and_indent_output(block)
index = @output.length
block.call
index.upto(@output.length - 1) do |i|
@output[i] = " " + @output[i]
end
end
def process_options(gem_name, template = {})
Hash[
template.collect { |key, value|
value = value % gem_name if value.respond_to?(:%)
[ key, value ]
}.sort
]
end
end
def switch_to!(gemfile_env = nil, deployment = false)
@ -214,64 +270,20 @@ module Penchant
end
def process(template)
case File.extname(processable_gemfile_path)
builder = case File.extname(processable_gemfile_path)
when '.penchant'
PenchantFile.result(template, @env, @is_deployment)
PenchantFile
when '.erb'
ERB.new(template, nil, nil, '@_erbout').result(binding).lines.to_a
ERBFile
end
builder.result(template, @env, @is_deployment)
end
def template
File.read(processable_gemfile_path)
end
def env(check, template = {}, &block)
if check.to_s == @env.to_s
original_erbout = @_erbout.dup
output = instance_eval(&block).lines.to_a
output.each do |line|
if gem_name = line[%r{gem ['"]([^'"]+)['"]}, 1]
line.replace(line.rstrip + options_to_string(gem_name, template) + "\n")
end
end
@_erbout = original_erbout + output.join
end
end
def with_gem_list(*gems)
template = {}
template = gems.pop if gems.last.instance_of?(Hash)
gems.flatten.each do |gem|
@_current_gem = gem
if block_given?
yield
else
@_erbout += gem(template) + "\n"
end
end
end
alias :gems :with_gem_list
def gem(template = {})
"gem '#{@_current_gem}'" + options_to_string(@_current_gem, template)
end
def options_to_string(gem_name, template = {})
template.collect do |key, value|
", #{key.inspect} => %{#{value % gem_name}}"
end.join
end
def no_deployment(&block)
instance_eval(&block) if !@is_deployment
end
def gemfile_header
(has_gemfile? and File.readlines(gemfile_path).first) or ""
end