yeah it's all consolidated now
This commit is contained in:
parent
033ba8a54c
commit
1a5f0142df
47
README.md
47
README.md
@ -3,7 +3,7 @@
|
|||||||
I like to do these things in all my projects:
|
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.
|
* 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.
|
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
|
* 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.
|
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:
|
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
|
* `install-git-hooks` which will do just what it says
|
||||||
* `hooks`, several git hooks that the prior script symlinks into .git/hooks for you
|
* `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
|
* `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
|
``` ruby
|
||||||
<% env :local do %>
|
source :rubygems
|
||||||
gem 'guard', :path => '../guard'
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<% env :remote do %>
|
gem 'rails', '3.2.3'
|
||||||
gem 'guard', :git => 'git://github.com/johnbintz/guard.git'
|
gems 'rake', 'nokogiri', 'rack-rewrite'
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<% no_deployment do %>
|
no_deployment do
|
||||||
gem 'os-specific-things'
|
group :development, :test do
|
||||||
<% end %>
|
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.
|
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
|
and deploying on another, or if you don't want to deal with the dependencies for your testing
|
||||||
frameworks:
|
frameworks:
|
||||||
|
|
||||||
``` erb
|
``` ruby
|
||||||
<% no_deployment do %>
|
no_deployment do
|
||||||
require 'rbconfig'
|
require 'rbconfig'
|
||||||
case RbConfig::CONFIG['host_os']
|
case RbConfig::CONFIG['host_os']
|
||||||
when /darwin/
|
when /darwin/
|
||||||
@ -64,7 +73,7 @@ frameworks:
|
|||||||
group :test do
|
group :test do
|
||||||
# ... all your testing libraries you won't need on the deployed end ...
|
# ... all your testing libraries you won't need on the deployed end ...
|
||||||
end
|
end
|
||||||
<% end %>
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Run `penchant gemfile ENV --deployment` to get this behavior. This is run by default when the
|
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:
|
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.
|
* 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.erb` set up as above and everything works cleanly.
|
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 `script/gemfile remote` to set your project to using remote repositories.
|
||||||
* Runs `rake bootstrap` for the project if it exists.
|
* Runs `rake bootstrap` for the project if it exists.
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ class PenchantCLI < Thor
|
|||||||
method_options :dir => 'script'
|
method_options :dir => 'script'
|
||||||
def convert
|
def convert
|
||||||
install
|
install
|
||||||
FileUtils.mv 'Gemfile', 'Gemfile.erb'
|
FileUtils.mv 'Gemfile', 'Gemfile.penchant'
|
||||||
gemfile(:remote)
|
gemfile(:remote)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ class PenchantCLI < Thor
|
|||||||
|
|
||||||
gemfile = Penchant::Gemfile.new
|
gemfile = Penchant::Gemfile.new
|
||||||
if !gemfile.has_gemfile?
|
if !gemfile.has_gemfile?
|
||||||
puts "No Gemfile or Gemfile.erb, exiting."
|
puts "No Gemfile or Gemfile.penchant, exiting."
|
||||||
exit 1
|
exit 1
|
||||||
end
|
end
|
||||||
system %{bundle}
|
system %{bundle}
|
||||||
|
@ -49,7 +49,7 @@ Feature: Gemfiles
|
|||||||
Scenario: Use a gem list for an operation
|
Scenario: Use a gem list for an operation
|
||||||
Given I have the file "Gemfile.erb" with the content:
|
Given I have the file "Gemfile.erb" with the content:
|
||||||
"""
|
"""
|
||||||
<% with_gem_list 'test' do %>
|
<% gems 'test' do %>
|
||||||
<% env :local, :path => '../%s' do %>
|
<% env :local, :path => '../%s' do %>
|
||||||
<%= gem %>
|
<%= gem %>
|
||||||
<% end %>
|
<% end %>
|
||||||
@ -65,7 +65,7 @@ Feature: Gemfiles
|
|||||||
Scenario: Let gem get additional info
|
Scenario: Let gem get additional info
|
||||||
Given I have the file "Gemfile.erb" with the content:
|
Given I have the file "Gemfile.erb" with the content:
|
||||||
"""
|
"""
|
||||||
<% with_gem_list 'test' do %>
|
<% gems 'test' do %>
|
||||||
<%= gem :path => '../%s' %>
|
<%= gem :path => '../%s' %>
|
||||||
<% end %>
|
<% end %>
|
||||||
"""
|
"""
|
||||||
@ -74,38 +74,24 @@ Feature: Gemfiles
|
|||||||
"""
|
"""
|
||||||
# generated by penchant, environment: local
|
# generated by penchant, environment: local
|
||||||
|
|
||||||
|
gem 'test', {:path=>"../test"}
|
||||||
gem 'test', :path => %{../test}
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Scenario: Use a gem list without a block
|
Scenario: Use a gem list without a block
|
||||||
Given I have the file "Gemfile.erb" with the content:
|
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
|
When I rebuild the Gemfile for "local" mode
|
||||||
Then the file "Gemfile" should have the following content:
|
Then the file "Gemfile" should have the following content:
|
||||||
"""
|
"""
|
||||||
# generated by penchant, environment: local
|
# generated by penchant, environment: local
|
||||||
gem 'test', :path => %{../test}
|
gem 'test', {:path=>"../test"}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Scenario: Use a gem list with an array
|
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:
|
Given I have the file "Gemfile.erb" with the content:
|
||||||
"""
|
"""
|
||||||
<% gems [ 'test' ], :path => '../%s' %>
|
<% gems [ 'test' ], :path => '../%s' %>
|
||||||
@ -114,7 +100,7 @@ Feature: Gemfiles
|
|||||||
Then the file "Gemfile" should have the following content:
|
Then the file "Gemfile" should have the following content:
|
||||||
"""
|
"""
|
||||||
# generated by penchant, environment: local
|
# generated by penchant, environment: local
|
||||||
gem 'test', :path => %{../test}
|
gem 'test', {:path=>"../test"}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -49,7 +49,6 @@ Feature: Gemfiles
|
|||||||
gem "three", {:path=>"../three"}
|
gem "three", {:path=>"../three"}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@wip
|
|
||||||
Scenario: Use an env block
|
Scenario: Use an env block
|
||||||
Given I have the file "Gemfile.penchant" with the content:
|
Given I have the file "Gemfile.penchant" with the content:
|
||||||
"""
|
"""
|
||||||
|
@ -74,31 +74,128 @@ module Penchant
|
|||||||
gemfile_header['deployment mode'] != nil
|
gemfile_header['deployment mode'] != nil
|
||||||
end
|
end
|
||||||
|
|
||||||
class ERBFile
|
class FileProcessor
|
||||||
end
|
attr_reader :environment, :is_deployment
|
||||||
|
|
||||||
class PenchantFile
|
|
||||||
def self.result(data, *args)
|
def self.result(data, *args)
|
||||||
new(data).result(*args)
|
new(data).result(*args)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.handle_result(&block)
|
||||||
|
if block
|
||||||
|
@handle_result = block
|
||||||
|
else
|
||||||
|
@handle_result
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def initialize(data)
|
def initialize(data)
|
||||||
@data = data
|
@data = data
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :environment, :is_deployment
|
|
||||||
|
|
||||||
def result(_env, _is_deployment)
|
def result(_env, _is_deployment)
|
||||||
@environment = _env.to_s.to_sym
|
@environment = _env.to_s.to_sym
|
||||||
@is_deployment = _is_deployment
|
@is_deployment = _is_deployment
|
||||||
|
|
||||||
@output = []
|
@output = []
|
||||||
|
|
||||||
instance_eval(@data)
|
handle_result(@data)
|
||||||
|
|
||||||
@output.join("\n")
|
@output.join("\n")
|
||||||
end
|
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)
|
def gem(*args)
|
||||||
gem_name, template = split_args(args)
|
gem_name, template = split_args(args)
|
||||||
|
|
||||||
@ -135,47 +232,6 @@ module Penchant
|
|||||||
def source(*args)
|
def source(*args)
|
||||||
@output << %{source #{args_to_string(args)}}
|
@output << %{source #{args_to_string(args)}}
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
def switch_to!(gemfile_env = nil, deployment = false)
|
def switch_to!(gemfile_env = nil, deployment = false)
|
||||||
@ -214,64 +270,20 @@ module Penchant
|
|||||||
end
|
end
|
||||||
|
|
||||||
def process(template)
|
def process(template)
|
||||||
case File.extname(processable_gemfile_path)
|
builder = case File.extname(processable_gemfile_path)
|
||||||
when '.penchant'
|
when '.penchant'
|
||||||
PenchantFile.result(template, @env, @is_deployment)
|
PenchantFile
|
||||||
when '.erb'
|
when '.erb'
|
||||||
ERB.new(template, nil, nil, '@_erbout').result(binding).lines.to_a
|
ERBFile
|
||||||
end
|
end
|
||||||
|
|
||||||
|
builder.result(template, @env, @is_deployment)
|
||||||
end
|
end
|
||||||
|
|
||||||
def template
|
def template
|
||||||
File.read(processable_gemfile_path)
|
File.read(processable_gemfile_path)
|
||||||
end
|
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
|
def gemfile_header
|
||||||
(has_gemfile? and File.readlines(gemfile_path).first) or ""
|
(has_gemfile? and File.readlines(gemfile_path).first) or ""
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user