Compare commits
No commits in common. "master" and "develop" have entirely different histories.
|
@ -2,4 +2,3 @@
|
||||||
.bundle
|
.bundle
|
||||||
Gemfile.lock
|
Gemfile.lock
|
||||||
pkg/*
|
pkg/*
|
||||||
.DS_Store
|
|
||||||
|
|
8
Gemfile
8
Gemfile
|
@ -5,8 +5,6 @@ gemspec
|
||||||
|
|
||||||
gem 'guard'
|
gem 'guard'
|
||||||
gem 'guard-rspec'
|
gem 'guard-rspec'
|
||||||
gem 'guard-cucumber'
|
gem 'mocha'
|
||||||
|
gem 'fakefs'
|
||||||
# see, *this* is why you need penchant
|
gem 'rspec', '~> 2.6.0'
|
||||||
#gem 'cuke-pack', :path => '../cuke-pack'
|
|
||||||
gem 'cuke-pack', :git => 'git://github.com/johnbintz/cuke-pack.git'
|
|
||||||
|
|
20
Guardfile
20
Guardfile
|
@ -1,21 +1,9 @@
|
||||||
# A sample Guardfile
|
# A sample Guardfile
|
||||||
# More info at https://github.com/guard/guard#readme
|
# More info at https://github.com/guard/guard#readme
|
||||||
|
|
||||||
group :rspec do
|
guard 'rspec', :cli => '-c', :version => 2 do
|
||||||
guard 'rspec', :cli => '-c', :version => 2 do
|
watch(%r{^spec/.+_spec\.rb$})
|
||||||
watch(%r{^spec/.+_spec\.rb$})
|
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
||||||
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
watch('spec/spec_helper.rb') { "spec" }
|
||||||
watch('spec/spec_helper.rb') { "spec" }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# added by cuke-pack
|
|
||||||
|
|
||||||
group :wip do
|
|
||||||
guard 'cucumber', :env => :cucumber, :cli => '-p wip' do
|
|
||||||
watch(%r{^features/.+.feature$})
|
|
||||||
watch(%r{^(app|lib).*}) { 'features' }
|
|
||||||
watch(%r{^features/support/.+$}) { 'features' }
|
|
||||||
watch(%r{^features/step_definitions/(.+).rb$}) { 'features' }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
241
README.md
241
README.md
|
@ -2,11 +2,9 @@
|
||||||
|
|
||||||
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, and setting up internal
|
* Have all my tests run before committing. I don't like buying ice cream for the team on test failures.
|
||||||
CI for smaller projects is a pain.
|
* 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.
|
||||||
* I can also factor out and simplify a lot of my Gemfile settings.
|
|
||||||
* 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.
|
||||||
|
|
||||||
|
@ -16,238 +14,39 @@ 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.penchant` environments
|
* `gemfile` which switches between `Gemfile.erb` 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/pre-commit`, one of the hooks the prior script installs
|
||||||
* `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.penchant?!
|
|
||||||
|
|
||||||
Yeah, it's a `Gemfile` with some extras:
|
|
||||||
|
|
||||||
``` ruby
|
|
||||||
# Gemfile.penchant
|
|
||||||
source :rubygems
|
|
||||||
|
|
||||||
# ensure git hooks are installed when a gemfile is processed, see below
|
|
||||||
ensure_git_hooks!
|
|
||||||
|
|
||||||
# need the bundler UTF-8 fix? ask for it by name!
|
|
||||||
bundler_encoding_fix!
|
|
||||||
|
|
||||||
# deploying to heroku and want 1.9.3 goodness?
|
|
||||||
ruby '1.9.3'
|
|
||||||
|
|
||||||
gem 'rails', '3.2.3'
|
|
||||||
# expands to:
|
|
||||||
#
|
|
||||||
# gem 'rake'
|
|
||||||
# gem 'nokogiri'
|
|
||||||
# gem 'rack-rewrite'
|
|
||||||
gems 'rake', 'nokogiri', 'rack-rewrite'
|
|
||||||
|
|
||||||
# define custom gem properties that get expanded to ones bundler understands
|
|
||||||
property :github, :git => 'git://github.com/$1/%s.git'
|
|
||||||
# values to the key are [ value ].flatten-ed and the $s are replaced on the fly,
|
|
||||||
# with $1 being the first parameter given
|
|
||||||
|
|
||||||
# set up defaults for all gems in a particular environment
|
|
||||||
defaults_for env(:local), :path => '../%s' # the %s is the name of the gem
|
|
||||||
|
|
||||||
no_deployment do
|
|
||||||
group :development, :test do
|
|
||||||
gem 'rspec', '~> 2.6.0'
|
|
||||||
|
|
||||||
dev_gems = %w{flowerbox guard-flowerbox}
|
|
||||||
|
|
||||||
# set up defaults for certain gems that are probably being used in envs
|
|
||||||
defaults_for dev_gems, :require => nil
|
|
||||||
|
|
||||||
env :local do
|
|
||||||
# expands to:
|
|
||||||
#
|
|
||||||
# gem 'flowerbox', :path => '../flowerbox', :require => nil
|
|
||||||
# gem 'guard-flowerbox', :path => '../guard-flowerbox', :require => nil
|
|
||||||
gems dev_gems
|
|
||||||
end
|
|
||||||
|
|
||||||
env :remote do
|
|
||||||
# expands to:
|
|
||||||
#
|
|
||||||
# gem 'flowerbox', :git => 'git://github.com/johnbintz/flowerbox.git', :require => nil
|
|
||||||
# gem 'guard-flowerbox', :git => 'git://github.com/johnbintz/guard-flowerbox.git', :require => nil
|
|
||||||
gems dev_gems, :github => 'johnbintz'
|
|
||||||
end
|
|
||||||
|
|
||||||
# an even shorter way to specify environments!
|
|
||||||
# in remote env, expands to:
|
|
||||||
# gem 'bullseye', :git => 'git://github.com/johnbintz/bullseye.git'
|
|
||||||
# in local env, expands to:
|
|
||||||
# gem 'bullseye', :path => '../bullseye'
|
|
||||||
env :remote, :opposite => :local do
|
|
||||||
gem 'bullseye', :github => 'johnbintz'
|
|
||||||
end
|
|
||||||
|
|
||||||
# only expanded on Mac OS X
|
|
||||||
os :darwin do
|
|
||||||
gem 'rb-fsevent'
|
|
||||||
end
|
|
||||||
|
|
||||||
# only expanded on Linux
|
|
||||||
os :linux do
|
|
||||||
gems 'rb-inotify', 'ffi'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
Use `script/gemfile local` to get at the local ones, and `script/gemfile remote` to get at the remote ones.
|
|
||||||
It then runs `bundle install`.
|
|
||||||
|
|
||||||
You can also run `penchant gemfile ENV`. Just straight `penchant gemfile` will rebuild the `Gemfile` from
|
|
||||||
`Gemfile.penchant` for whatever environment the `Gemfile` is currently using.
|
|
||||||
|
|
||||||
If you have an existing project, `penchant convert` will convert the `Gemfile` into a `Gemfile.penchant`
|
|
||||||
and add some bonuses, like defining that anything in `env :local` blocks automatically reference `..`,
|
|
||||||
ensuring that hooks are always installed when `penchant gemfile` is executed, and adding the `:github` gem property
|
|
||||||
that lets you pass in the username of the repo to reference that repo:
|
|
||||||
`gem 'penchant', :github => 'johnbintz'`.
|
|
||||||
|
|
||||||
### Stupid-simple local/remote setup
|
|
||||||
|
|
||||||
Use `opposites :local, :remote` and environment settings for local/remote gems will be set accordingly depending
|
|
||||||
on environment:
|
|
||||||
|
|
||||||
``` ruby
|
|
||||||
defaults_for env(:local), :path => '../%s'
|
|
||||||
opposites :local, :remote
|
|
||||||
|
|
||||||
env :remote do
|
|
||||||
gem 'my-gem', :git => 'git://github.com/johnbintz/my-gem.git'
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
In `remote`, the Git repo version is used. In `local`, the path is used. Only one gem definition needed!
|
|
||||||
|
|
||||||
### Deployment mode
|
|
||||||
|
|
||||||
Use `no_deployment` blocks to indicate gems that shouldn't even appear in `Gemfiles` destined for
|
|
||||||
remote servers. *Very* helpful when you have OS-specific gems and are developing on one platform
|
|
||||||
and deploying on another, or if you don't want to deal with the dependencies for your testing
|
|
||||||
frameworks:
|
|
||||||
|
|
||||||
``` ruby
|
|
||||||
gem 'rails'
|
|
||||||
|
|
||||||
no_deployment do
|
|
||||||
os :darwin do
|
|
||||||
gems 'growl_notify', 'growl', 'rb-fsevent'
|
|
||||||
end
|
|
||||||
|
|
||||||
os :linux do
|
|
||||||
gem 'libnotify', :require => nil
|
|
||||||
end
|
|
||||||
|
|
||||||
group :test do
|
|
||||||
# ... all your testing libraries you won't need on the deployed end ...
|
|
||||||
end
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
Run `penchant gemfile ENV --deployment` to get this behavior. This is run by default when the
|
|
||||||
pre-commit git hook runs, but only after the default Rake task passes.
|
|
||||||
|
|
||||||
If you just want any locally installed gems, add the `--local` switch. Great if rubygems.org is down!
|
|
||||||
|
|
||||||
#### Won't this change the project dependencies?!
|
|
||||||
|
|
||||||
Probably not. You probably have the "main" gems in your project locked to a version of Rails or
|
|
||||||
Sinatra or something else, and all of the other gems for authentication, queue processing, etc. are
|
|
||||||
dependent on that framework. Ripping out your testing framework and deployment helpers really
|
|
||||||
shouldn't be changing the main versions of your application gems. It WORKSFORME and YMMV.
|
|
||||||
|
|
||||||
### Getting local gems all set up
|
|
||||||
|
|
||||||
`penchant bootstrap` will go through and find all git repo references in your `Gemfile.penchant` and
|
|
||||||
will download them to the specified directory (by default, `..`). This means blocks like this
|
|
||||||
will work as expected when you `penchant bootstrap` and then `penchant gemfile local`:
|
|
||||||
|
|
||||||
``` ruby
|
|
||||||
env :local do
|
|
||||||
gem 'my-gem', :path => '../%s'
|
|
||||||
end
|
|
||||||
|
|
||||||
env :remote do
|
|
||||||
gem 'my-gem', :git => 'git://github.com/johnbintz/%s.git'
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that this just does a quick `git clone`, so if your project is already in there in a different state,
|
|
||||||
nothing "happens" except that git fails.
|
|
||||||
|
|
||||||
## initialize-environment
|
## initialize-environment
|
||||||
|
|
||||||
Get new developers up to speed fast! `script/initialize-environment` does the following when run:
|
It will also try to run `rake bootstrap`, so add a `:bootstrap` task for things that should happen when you start going
|
||||||
|
(make databases, other stuff, etc, whatever).
|
||||||
|
|
||||||
* Check out any remote repos found in `Gemfile.penchant` to the same directory where your current project lives.
|
## Gemfile.erb?!
|
||||||
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.
|
|
||||||
|
|
||||||
### After-`gemfile` hooks?
|
Yeah, it's a `Gemfile` with ERB in it:
|
||||||
|
|
||||||
Drop a file called `.penchant` in your project directory. It'll get executed every time you switch environments using
|
``` erb
|
||||||
Penchant. I use it to tell my Hydra clients to sync and update their Gemfiles, too:
|
<% if env == "local" %>
|
||||||
|
gem 'guard', :path => '../guard'
|
||||||
``` ruby
|
<% else %>
|
||||||
# rake knows if you need "bundle exec" or not.
|
gem 'guard', :git => 'git://github.com/johnbintz/guard.git'
|
||||||
|
<% end %>
|
||||||
rake "hydra:sync hydra:remote:bundle"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### What environment are you currently using in that Gemfile?
|
Use `script/gemfile local` to get at the local ones, and `script/gemfile remote` (or anything, really) to get at the remote ones.
|
||||||
|
It then runs `bundle install`.
|
||||||
`head -n 1` that puppy, or `penchant gemfile-env`.
|
|
||||||
|
|
||||||
## git hook?!
|
## git hook?!
|
||||||
|
|
||||||
It runs `penchant gemfile remote` then runs `bundle exec rake`. Make sure your default Rake task for the project runs your
|
It runs `script/gemfile remote` then runs `bundle exec rake`. Make sure your default Rake task for the project runs your
|
||||||
tests and performs any other magic necessary before each commit. Your re-environmented Gemfile and Gemfile.lock will be added
|
tests and performs any other magic necessary before each commit.
|
||||||
to your commit if they've changed.
|
|
||||||
|
|
||||||
### Ensuring git hooks get installed
|
|
||||||
|
|
||||||
I find that when I pull down new projects I never remember to install the git hooks, which involves an awkward running
|
|
||||||
of `bundle exec rake` *after* I've already committed code. Since we have computers now, and they can be told to do things,
|
|
||||||
you can add `ensure_git_hooks!` anywhere in your `Gemfile.penchant` to make sure the git hooks are symlinked to the ones
|
|
||||||
in the `script/hooks` directory with every processing of `Gemfile.penchant`.
|
|
||||||
|
|
||||||
### Performing pre-`bundle exec rake` tasks.
|
|
||||||
|
|
||||||
Example: I use a style of Cucumber testing where I co-opt the `@wip` tag and then tell Guard to only run scenarios with `@wip` tags.
|
|
||||||
I don't want `@wip` tasks to be committed to the repo, since committing a half-completed scenario seems silly.
|
|
||||||
So I use `bundle exec rake preflight_check` to check all feature files for `@wip` tasks, and to fail if I hit one. Yes, Cucumber
|
|
||||||
already does this, but in order to get to `bundle exec rake`, I need to go through two `Gemfile` creations, one for `remote --deployment`
|
|
||||||
and one for `remote` to make sure my tests work on remote gems only.
|
|
||||||
|
|
||||||
If `bundle exec rake -T preflight_check` returns a task, that task will be run before all the `Gemfile` switcheroo. *Don't use it
|
|
||||||
as a place to run your tests!*
|
|
||||||
|
|
||||||
### Skipping all that Rake falderal?
|
|
||||||
|
|
||||||
Do it Travis CI style: stick `[ci skip]` in your commit message. That's why the meat of the git hooks resides in
|
|
||||||
`commit-msg` and not `pre-commit`: you need the commit message before you can determine if the tests should be run
|
|
||||||
based on the commit message. Weird, I know.
|
|
||||||
|
|
||||||
## How?!
|
## How?!
|
||||||
|
|
||||||
* No RVM? `gem install penchant`
|
* `gem install penchant`
|
||||||
* RVM? `rvm gemset use global && gem install penchant && rvm gemset use default`
|
|
||||||
* `cd` to your project directory
|
* `cd` to your project directory
|
||||||
|
* `penchant install` (can do `--dir=WHEREVER`, too)
|
||||||
And then one of the following:
|
|
||||||
|
|
||||||
* `penchant install` for a new project (`--dir=WHEREVER` will install the scripts to a directory other than `$PWD/scripts`)
|
|
||||||
* `penchant update` to update the installation (`--dir=WHEVEVER` works here, too)
|
|
||||||
* `penchant convert` for an existing project (`--dir=WHEVEVER` works here, too)
|
|
||||||
|
|
||||||
|
|
14
Rakefile
14
Rakefile
|
@ -1,16 +1,2 @@
|
||||||
require 'bundler'
|
require 'bundler'
|
||||||
Bundler::GemHelper.install_tasks
|
Bundler::GemHelper.install_tasks
|
||||||
|
|
||||||
begin
|
|
||||||
require 'cucumber'
|
|
||||||
require 'cucumber/rake/task'
|
|
||||||
|
|
||||||
Cucumber::Rake::Task.new(:cucumber) do |t|
|
|
||||||
t.cucumber_opts = "features --format pretty"
|
|
||||||
end
|
|
||||||
rescue LoadError
|
|
||||||
"#$! - no cucumber"
|
|
||||||
end
|
|
||||||
|
|
||||||
task :default => [ :cucumber ]
|
|
||||||
|
|
||||||
|
|
141
bin/penchant
141
bin/penchant
|
@ -3,157 +3,28 @@
|
||||||
require 'rubygems'
|
require 'rubygems'
|
||||||
require 'thor'
|
require 'thor'
|
||||||
require 'penchant'
|
require 'penchant'
|
||||||
require 'fileutils'
|
|
||||||
|
|
||||||
class PenchantCLI < Thor
|
class PenchantCLI < Thor
|
||||||
include Thor::Actions
|
include Thor::Actions
|
||||||
source_root File.expand_path('../..', __FILE__)
|
source_root File.expand_path('../..', __FILE__)
|
||||||
|
|
||||||
SCRIPT_DIR = 'script'
|
|
||||||
CLONE_DIR = '..'
|
|
||||||
|
|
||||||
desc "install", "Copy the common scripts to the project"
|
desc "install", "Copy the common scripts to the project"
|
||||||
method_options :dir => SCRIPT_DIR
|
method_options :dir => 'script'
|
||||||
def install
|
def install
|
||||||
directory 'template/script', options[:dir]
|
directory 'template/script', options[:dir]
|
||||||
Dir[File.join(options[:dir], '**/*')].each { |file| File.chmod(0755, file) }
|
Dir[File.join(options[:dir], '**/*')].each { |file| File.chmod(0755, file) }
|
||||||
|
|
||||||
if File.directory?('.git')
|
|
||||||
Penchant::Hooks.install!
|
|
||||||
else
|
|
||||||
puts "No git repository detected here. Skipping git hook installation..."
|
|
||||||
end
|
|
||||||
|
|
||||||
if !File.file?('Gemfile') && !File.file?('Gemfile.penchant')
|
|
||||||
FileUtils.touch('Gemfile.penchant')
|
|
||||||
|
|
||||||
prepend_to_file 'Gemfile.penchant', <<-RB
|
|
||||||
source :rubygems
|
|
||||||
RB
|
|
||||||
|
|
||||||
install_gemfile_penchant
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "update", "Update the installed scripts"
|
desc "gemfile ENV", "Switch the gemfile environment"
|
||||||
method_options :dir => SCRIPT_DIR
|
def gemfile(env)
|
||||||
def update
|
Penchant::Gemfile.do_full_env_switch!(env)
|
||||||
install
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "convert", "Make an existing project Penchant-isized"
|
|
||||||
method_options :dir => SCRIPT_DIR
|
|
||||||
def convert
|
|
||||||
install
|
|
||||||
FileUtils.mv 'Gemfile', 'Gemfile.penchant'
|
|
||||||
install_gemfile_penchant
|
|
||||||
end
|
|
||||||
|
|
||||||
method_options :deployment => false
|
|
||||||
method_options :switch_back => false
|
|
||||||
method_options :no_auto_update => false
|
|
||||||
method_options :local => false
|
|
||||||
desc "gemfile ENV", "Switch the gemfile environment, or rebuild the current environment if not given"
|
|
||||||
def gemfile(env = get_current_env)
|
|
||||||
check_git_hooks!
|
|
||||||
|
|
||||||
if env
|
|
||||||
if options[:switch_back]
|
|
||||||
puts "[penchant] Switching back, fallback: #{env}..."
|
|
||||||
|
|
||||||
Penchant::Gemfile.switch_back!(env)
|
|
||||||
else
|
|
||||||
puts "[penchant] Rebunding for #{env} environment#{options[:deployment] ? ", deployment mode" : ''}..."
|
|
||||||
|
|
||||||
Penchant::Gemfile.do_full_env_switch!(env, options[:deployment])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
gemfile = Penchant::Gemfile.new
|
|
||||||
if !gemfile.has_gemfile?
|
|
||||||
puts "No Gemfile or Gemfile.penchant, exiting."
|
|
||||||
exit 1
|
|
||||||
end
|
|
||||||
|
|
||||||
command = %{bundle}
|
|
||||||
command << " --local" if options[:local]
|
|
||||||
|
|
||||||
system command
|
|
||||||
|
|
||||||
# it's asking for bundle update, we know what we're doing
|
|
||||||
if $?.exitstatus == 6 and !options[:no_auto_update]
|
|
||||||
command = %{bundle update}
|
|
||||||
command << " --local" if options[:local]
|
|
||||||
|
|
||||||
system command
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "gemfile-env", "Get the gemfile environment"
|
desc "gemfile-env", "Get the gemfile environment"
|
||||||
def gemfile_env
|
def gemfile_env
|
||||||
puts get_current_env
|
gemfile = Penchant::Gemfile.new
|
||||||
|
puts gemfile.environment
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "bootstrap [DIR = #{CLONE_DIR}]", "Download all referred-to git repos to the specified directory"
|
|
||||||
def bootstrap(dir = CLONE_DIR)
|
|
||||||
Penchant::Gemfile.defined_git_repos.each do |repo|
|
|
||||||
puts "Cloning #{repo} to #{dir}"
|
|
||||||
repo.clone_to(dir)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def method_missing(method, *args)
|
|
||||||
if Penchant::Gemfile.available_environments.include?(method)
|
|
||||||
gemfile(method, *args)
|
|
||||||
else
|
|
||||||
super(method, *args)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
no_tasks do
|
|
||||||
def get_current_env
|
|
||||||
gemfile = Penchant::Gemfile.new
|
|
||||||
out = [ gemfile.environment ]
|
|
||||||
out << "deployment" if gemfile.deployment?
|
|
||||||
out.join(' ')
|
|
||||||
end
|
|
||||||
|
|
||||||
def check_git_hooks!
|
|
||||||
if !Penchant::Hooks.installed?
|
|
||||||
puts "[penchant] git hooks not installed. Run script/install-git-hooks."
|
|
||||||
puts
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def install_gemfile_penchant
|
|
||||||
prepend_to_file 'Gemfile.penchant', <<-RB
|
|
||||||
# ensure git hooks are always installed
|
|
||||||
ensure_git_hooks!
|
|
||||||
|
|
||||||
# everything in the :local env is assumed to be a sibling directory of this one
|
|
||||||
defaults_for env(:local), :path => '../%s'
|
|
||||||
|
|
||||||
# reference a github repository with gem 'my-gem', :github => 'username'
|
|
||||||
# also supports modern bundler user/repo syntax
|
|
||||||
property(:github) { |name|
|
|
||||||
parts = name.split('/')
|
|
||||||
|
|
||||||
url = case parts.length
|
|
||||||
when 1
|
|
||||||
"git://github.com/\#{name}/%s.git"
|
|
||||||
when 2
|
|
||||||
"git://github.com/\#{parts.first}/\#{parts.last}.git"
|
|
||||||
end
|
|
||||||
|
|
||||||
{ :git => url }
|
|
||||||
}
|
|
||||||
RB
|
|
||||||
gemfile(:remote)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
default_task :gemfile
|
|
||||||
end
|
end
|
||||||
|
|
||||||
PenchantCLI.start
|
PenchantCLI.start
|
||||||
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
<%
|
|
||||||
std_opts = "-r features --format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} -f Cucumber::StepWriter --out features/step_definitions --strict"
|
|
||||||
%>
|
|
||||||
default: <%= std_opts %> features
|
|
||||||
wip: <%= std_opts %> --tags @wip features
|
|
||||||
precommit: FAILFAST=true <%= std_opts %> --tags ~@wip:0 features
|
|
||||||
cleanup: <%= std_opts %> -f Cucumber::CleanupFormatter --out unused.txt features
|
|
||||||
|
|
|
@ -1,77 +0,0 @@
|
||||||
Feature: CLI
|
|
||||||
Scenario: Switch back to the original pre-deployment environment
|
|
||||||
Given I have the file "tmp/Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
gem 'rake'
|
|
||||||
"""
|
|
||||||
And I have the file "tmp/Gemfile" with the content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: production, deployment mode (was local)
|
|
||||||
"""
|
|
||||||
When I run "bin/penchant gemfile other --switch-back" in the "tmp" directory
|
|
||||||
Then the file "tmp/Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: local
|
|
||||||
gem "rake"
|
|
||||||
"""
|
|
||||||
And the output should include "fallback: other"
|
|
||||||
|
|
||||||
Scenario: Try to convert a project, ignoring git hooks
|
|
||||||
Given I have the file "tmp/Gemfile" with the content:
|
|
||||||
"""
|
|
||||||
source :rubygems
|
|
||||||
"""
|
|
||||||
When I run "bin/penchant convert" in the "tmp" directory
|
|
||||||
Then the file "tmp/Gemfile.penchant" should include the following content:
|
|
||||||
"""
|
|
||||||
source :rubygems
|
|
||||||
"""
|
|
||||||
And the output should include "No git"
|
|
||||||
|
|
||||||
Scenario: Run in a project where the git hooks are not set up
|
|
||||||
Given I have the file "tmp/Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
gem 'rake'
|
|
||||||
"""
|
|
||||||
Given I have the file "tmp/script/hooks/pre-commit" with the content:
|
|
||||||
"""
|
|
||||||
a penchant hook
|
|
||||||
"""
|
|
||||||
When I run "bin/penchant gemfile remote" in the "tmp" directory
|
|
||||||
Then the output should include "git hooks not installed"
|
|
||||||
|
|
||||||
Scenario: Run in a project where there are no git hooks, but there is a git repo
|
|
||||||
Given I have the file "tmp/Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
gem 'rake'
|
|
||||||
"""
|
|
||||||
Given I have the directory "tmp/.git"
|
|
||||||
When I run "bin/penchant gemfile remote" in the "tmp" directory
|
|
||||||
Then the output should not include "git hooks not installed"
|
|
||||||
|
|
||||||
Scenario: Run in a project where git hooks are set up
|
|
||||||
Given I have the file "tmp/Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
gem 'rake'
|
|
||||||
"""
|
|
||||||
Given I have the file "tmp/script/hooks/pre-commit" with the content:
|
|
||||||
"""
|
|
||||||
a penchant hook
|
|
||||||
"""
|
|
||||||
Given I have the symlink "tmp/.git/hooks/pre-commit" which points to "tmp/script/hooks/pre-commit"
|
|
||||||
When I run "bin/penchant gemfile remote" in the "tmp" directory
|
|
||||||
Then the output should not include "git hooks not installed"
|
|
||||||
|
|
||||||
Scenario: Install Penchant into a directory with no Gemfile
|
|
||||||
Given I have the directory "tmp"
|
|
||||||
When I run "bin/penchant install" in the "tmp" directory
|
|
||||||
Then the file "tmp/Gemfile.penchant" should include the following content:
|
|
||||||
"""
|
|
||||||
source :rubygems
|
|
||||||
"""
|
|
||||||
Then the file "tmp/Gemfile" should include the following content:
|
|
||||||
"""
|
|
||||||
source :rubygems
|
|
||||||
"""
|
|
||||||
And the output should include "No git"
|
|
||||||
|
|
|
@ -1,441 +0,0 @@
|
||||||
@fakefs
|
|
||||||
Feature: Gemfiles
|
|
||||||
Scenario: Process a pure Ruby gemfile
|
|
||||||
Given I have the file "Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
source :rubygems
|
|
||||||
|
|
||||||
gemspec
|
|
||||||
|
|
||||||
group :cats, :dogs do
|
|
||||||
case environment
|
|
||||||
when :local
|
|
||||||
gem 'test', :path => '../test'
|
|
||||||
when :remote
|
|
||||||
gem 'test', :git => 'git://github.com/johnbintz/test.git'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
"""
|
|
||||||
When I rebuild the Gemfile for "local" mode
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: local
|
|
||||||
source :rubygems
|
|
||||||
gemspec
|
|
||||||
|
|
||||||
group :cats, :dogs do
|
|
||||||
gem "test", {:path=>"../test"}
|
|
||||||
end
|
|
||||||
"""
|
|
||||||
When I rebuild the Gemfile for "remote" mode
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: remote
|
|
||||||
source :rubygems
|
|
||||||
gemspec
|
|
||||||
|
|
||||||
group :cats, :dogs do
|
|
||||||
gem "test", {:git=>"git://github.com/johnbintz/test.git"}
|
|
||||||
end
|
|
||||||
"""
|
|
||||||
|
|
||||||
Scenario: Use a gemlist
|
|
||||||
Given I have the file "Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
gems 'one', 'two', 'three', :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 "one", {:path=>"../one"}
|
|
||||||
gem "two", {:path=>"../two"}
|
|
||||||
gem "three", {:path=>"../three"}
|
|
||||||
"""
|
|
||||||
|
|
||||||
Scenario: Use an env block
|
|
||||||
Given I have the file "Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
env :local do
|
|
||||||
gems 'one', 'two', 'three', :path => '../%s'
|
|
||||||
end
|
|
||||||
"""
|
|
||||||
When I rebuild the Gemfile for "local" mode
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: local
|
|
||||||
gem "one", {:path=>"../one"}
|
|
||||||
gem "two", {:path=>"../two"}
|
|
||||||
gem "three", {:path=>"../three"}
|
|
||||||
"""
|
|
||||||
|
|
||||||
When I rebuild the Gemfile for "remote" mode
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: remote
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
Scenario: Skip deployment blocks
|
|
||||||
Given I have the file "Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
no_deployment do
|
|
||||||
gem 'one'
|
|
||||||
end
|
|
||||||
"""
|
|
||||||
When I rebuild the Gemfile for "local" mode
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: local
|
|
||||||
gem "one"
|
|
||||||
"""
|
|
||||||
|
|
||||||
When I rebuild the Gemfile for "local" mode with deployment
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: local, deployment mode (was local)
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
Scenario: Peel multiple hashes off a gemlist
|
|
||||||
Given I have the file "Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
gems 'one', { :path => '../%s' }, { :require => nil }
|
|
||||||
"""
|
|
||||||
When I rebuild the Gemfile for "local" mode
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: local
|
|
||||||
gem "one", {:path=>"../one", :require=>nil}
|
|
||||||
"""
|
|
||||||
|
|
||||||
Scenario: Don't add an empty hash
|
|
||||||
Given I have the file "Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
gems 'one'
|
|
||||||
"""
|
|
||||||
When I rebuild the Gemfile for "local" mode
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: local
|
|
||||||
gem "one"
|
|
||||||
"""
|
|
||||||
|
|
||||||
Scenario: Single gem gets processed like a gems list
|
|
||||||
Given I have the file "Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
gem 'one', '1.2.3', :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 "one", "1.2.3", {:path=>"../one"}
|
|
||||||
"""
|
|
||||||
|
|
||||||
@mocha
|
|
||||||
Scenario: OS-specific blocks
|
|
||||||
Given I have the file "Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
os :darwin do
|
|
||||||
gem 'one', :path => '../%s'
|
|
||||||
end
|
|
||||||
"""
|
|
||||||
And I am on the "darwin" platform
|
|
||||||
When I rebuild the Gemfile for "local" mode
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: local
|
|
||||||
gem "one", {:path=>"../one"}
|
|
||||||
"""
|
|
||||||
Given I am on the "linux" platform
|
|
||||||
When I rebuild the Gemfile for "local" mode
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: local
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
Scenario: Get the list of environments defined
|
|
||||||
Given I have the file "Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
env :cat do
|
|
||||||
gem 'one', :path => '../%s'
|
|
||||||
end
|
|
||||||
|
|
||||||
env :dog do
|
|
||||||
gem 'two', :path => '../%s'
|
|
||||||
end
|
|
||||||
"""
|
|
||||||
When I request the list of environments available
|
|
||||||
Then I should get the following environments:
|
|
||||||
| cat |
|
|
||||||
| dog |
|
|
||||||
|
|
||||||
Scenario: Get the list of git repos defined
|
|
||||||
Given I have the file "Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
gem 'one', :path => '../%s'
|
|
||||||
gem 'two', :git => 'git://github.cats/%s.git'
|
|
||||||
"""
|
|
||||||
When I request the list of git repositories
|
|
||||||
Then I should get the following repositories:
|
|
||||||
| git://github.cats/two.git |
|
|
||||||
|
|
||||||
Scenario: Get the list of git repos defined, regardless of environment
|
|
||||||
Given I have the file "Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
gem 'one', :path => '../%s'
|
|
||||||
env :remote do
|
|
||||||
gem 'two', :git => 'git://github.cats/%s.git'
|
|
||||||
end
|
|
||||||
"""
|
|
||||||
When I request the list of git repositories
|
|
||||||
Then I should get the following repositories:
|
|
||||||
| git://github.cats/two.git |
|
|
||||||
|
|
||||||
Scenario: Propose defaults for a gem
|
|
||||||
Given I have the file "Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
defaults_for 'one', :path => '../%s'
|
|
||||||
gem 'one', '1.2.3'
|
|
||||||
"""
|
|
||||||
When I rebuild the Gemfile for "local" mode
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: local
|
|
||||||
gem "one", "1.2.3", {:path=>"../one"}
|
|
||||||
"""
|
|
||||||
|
|
||||||
Scenario: Propose defaults for an array of gems
|
|
||||||
Given I have the file "Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
defaults_for ['one'], :path => '../%s'
|
|
||||||
gem 'one', '1.2.3'
|
|
||||||
"""
|
|
||||||
When I rebuild the Gemfile for "local" mode
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: local
|
|
||||||
gem "one", "1.2.3", {:path=>"../one"}
|
|
||||||
"""
|
|
||||||
|
|
||||||
Scenario: Propose defaults for an environment
|
|
||||||
Given I have the file "Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
defaults_for env(:local), :path => '../%s'
|
|
||||||
env :local do
|
|
||||||
gem 'one', '1.2.3'
|
|
||||||
end
|
|
||||||
"""
|
|
||||||
When I rebuild the Gemfile for "local" mode
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: local
|
|
||||||
gem "one", "1.2.3", {:path=>"../one"}
|
|
||||||
"""
|
|
||||||
|
|
||||||
Scenario: Create opposite environment gem assumptions to cut down on repetition
|
|
||||||
Given I have the file "Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
defaults_for env(:local), :path => '../%s'
|
|
||||||
property(:github) { |name| { :git => "git://github.com/#{name}/%s.git" } }
|
|
||||||
|
|
||||||
env :remote, :opposite => :local do
|
|
||||||
gem 'one', :github => 'johnbintz', :require => nil
|
|
||||||
end
|
|
||||||
env :local, :opposite => :remote do
|
|
||||||
gem 'two', :path => '../%s', :require => nil
|
|
||||||
end
|
|
||||||
"""
|
|
||||||
When I rebuild the Gemfile for "local" mode
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: local
|
|
||||||
gem "one", {:path=>"../one", :require=>nil}
|
|
||||||
gem "two", {:path=>"../two", :require=>nil}
|
|
||||||
"""
|
|
||||||
When I rebuild the Gemfile for "remote" mode
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: remote
|
|
||||||
gem "one", {:git=>"git://github.com/johnbintz/one.git", :require=>nil}
|
|
||||||
gem "two", {:require=>nil}
|
|
||||||
"""
|
|
||||||
|
|
||||||
Scenario: Set the opposite environment in the environment defaults
|
|
||||||
Given I have the file "Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
defaults_for env(:local), :path => '../%s', :opposite => :remote
|
|
||||||
defaults_for env(:remote), :opposite => :local
|
|
||||||
property(:github) { |name| { :git => "git://github.com/#{name}/%s.git" } }
|
|
||||||
|
|
||||||
env :remote do
|
|
||||||
gem 'one', :github => 'johnbintz', :require => nil
|
|
||||||
end
|
|
||||||
env :local do
|
|
||||||
gem 'two', :path => '../%s', :require => nil
|
|
||||||
end
|
|
||||||
"""
|
|
||||||
When I rebuild the Gemfile for "local" mode
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: local
|
|
||||||
gem "one", {:path=>"../one", :require=>nil}
|
|
||||||
gem "two", {:path=>"../two", :require=>nil}
|
|
||||||
"""
|
|
||||||
When I rebuild the Gemfile for "remote" mode
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: remote
|
|
||||||
gem "one", {:git=>"git://github.com/johnbintz/one.git", :require=>nil}
|
|
||||||
gem "two", {:require=>nil}
|
|
||||||
"""
|
|
||||||
|
|
||||||
Scenario: Define a pair of opposites
|
|
||||||
Given I have the file "Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
defaults_for env(:local), :path => '../%s'
|
|
||||||
opposites :local, :remote
|
|
||||||
|
|
||||||
property(:github) { |name| { :git => "git://github.com/#{name}/%s.git" } }
|
|
||||||
|
|
||||||
env :remote do
|
|
||||||
gem 'one', :github => 'johnbintz', :require => nil
|
|
||||||
end
|
|
||||||
env :local do
|
|
||||||
gem 'two', :path => '../%s', :require => nil
|
|
||||||
end
|
|
||||||
"""
|
|
||||||
When I rebuild the Gemfile for "local" mode
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: local
|
|
||||||
gem "one", {:path=>"../one", :require=>nil}
|
|
||||||
gem "two", {:path=>"../two", :require=>nil}
|
|
||||||
"""
|
|
||||||
When I rebuild the Gemfile for "remote" mode
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: remote
|
|
||||||
gem "one", {:git=>"git://github.com/johnbintz/one.git", :require=>nil}
|
|
||||||
gem "two", {:require=>nil}
|
|
||||||
"""
|
|
||||||
|
|
||||||
Scenario: Define a pair of opposites in the other order
|
|
||||||
Given I have the file "Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
opposites :local, :remote
|
|
||||||
defaults_for env(:local), :path => '../%s'
|
|
||||||
|
|
||||||
property(:github) { |name| { :git => "git://github.com/#{name}/%s.git" } }
|
|
||||||
|
|
||||||
env :remote do
|
|
||||||
gem 'one', :github => 'johnbintz', :require => nil
|
|
||||||
end
|
|
||||||
env :local do
|
|
||||||
gem 'two', :path => '../%s', :require => nil
|
|
||||||
end
|
|
||||||
"""
|
|
||||||
When I rebuild the Gemfile for "local" mode
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: local
|
|
||||||
gem "one", {:path=>"../one", :require=>nil}
|
|
||||||
gem "two", {:path=>"../two", :require=>nil}
|
|
||||||
"""
|
|
||||||
When I rebuild the Gemfile for "remote" mode
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: remote
|
|
||||||
gem "one", {:git=>"git://github.com/johnbintz/one.git", :require=>nil}
|
|
||||||
gem "two", {:require=>nil}
|
|
||||||
"""
|
|
||||||
|
|
||||||
Scenario: Override defaults for an environment
|
|
||||||
Given I have the file "Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
defaults_for env(:local), :path => '../%s'
|
|
||||||
env :local do
|
|
||||||
gem 'one', '1.2.3', :path => '../cats'
|
|
||||||
end
|
|
||||||
"""
|
|
||||||
When I rebuild the Gemfile for "local" mode
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: local
|
|
||||||
gem "one", "1.2.3", {:path=>"../cats"}
|
|
||||||
"""
|
|
||||||
|
|
||||||
Scenario: Define special expansions for properties
|
|
||||||
Given I have the file "Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
defaults_for env(:local), :path => '../%s'
|
|
||||||
property(:github) { |name| { :git => "git://github.com/#{name}/%s.git" } }
|
|
||||||
gem 'one', :github => 'john'
|
|
||||||
"""
|
|
||||||
When I rebuild the Gemfile for "local" mode
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: local
|
|
||||||
gem "one", {:git=>"git://github.com/john/one.git"}
|
|
||||||
"""
|
|
||||||
|
|
||||||
Scenario: Define special expansions for properties as a hash
|
|
||||||
Given I have the file "Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
defaults_for env(:local), :path => '../%s'
|
|
||||||
property :github, :git => "git://github.com/$1/%s.git"
|
|
||||||
gem 'one', :github => 'john'
|
|
||||||
"""
|
|
||||||
When I rebuild the Gemfile for "local" mode
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: local
|
|
||||||
gem "one", {:git=>"git://github.com/john/one.git"}
|
|
||||||
"""
|
|
||||||
|
|
||||||
@mocha
|
|
||||||
Scenario: Force installing of git hooks if the gemfile asks for it
|
|
||||||
Given I expect git hooks to be installed
|
|
||||||
Given I have the file "Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
ensure_git_hooks!
|
|
||||||
|
|
||||||
gem 'one'
|
|
||||||
"""
|
|
||||||
When I rebuild the Gemfile for "local" mode
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: local
|
|
||||||
gem "one"
|
|
||||||
"""
|
|
||||||
|
|
||||||
Scenario: Pass through the Ruby version
|
|
||||||
Given I have the file "Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
ruby '1.9.3'
|
|
||||||
"""
|
|
||||||
When I rebuild the Gemfile for "local" mode
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: local
|
|
||||||
ruby "1.9.3"
|
|
||||||
"""
|
|
||||||
|
|
||||||
Scenario: Ask for the Gemfile encoding fix
|
|
||||||
Given I have the file "Gemfile.penchant" with the content:
|
|
||||||
"""
|
|
||||||
bundler_encoding_fix!
|
|
||||||
"""
|
|
||||||
When I rebuild the Gemfile for "local" mode
|
|
||||||
Then the file "Gemfile" should have the following content:
|
|
||||||
"""
|
|
||||||
# generated by penchant, environment: local
|
|
||||||
if RUBY_VERSION =~ /1.9/
|
|
||||||
Encoding.default_external = Encoding::UTF_8
|
|
||||||
Encoding.default_internal = Encoding::UTF_8
|
|
||||||
end
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
Given /^I am on the "([^"]*)" platform$/ do |os|
|
|
||||||
Penchant::FileProcessor.any_instance.stubs(:current_os).returns(os.to_sym)
|
|
||||||
end
|
|
|
@ -1,3 +0,0 @@
|
||||||
Given /^I expect git hooks to be installed$/ do
|
|
||||||
Penchant::Hooks.expects(:install!)
|
|
||||||
end
|
|
|
@ -1,3 +0,0 @@
|
||||||
Given /^I have the directory "(.*?)"$/ do |dir|
|
|
||||||
FileUtils.mkdir_p dir
|
|
||||||
end
|
|
|
@ -1,5 +0,0 @@
|
||||||
Given /^I have the file "([^"]*)" with the content:$/ do |file, string|
|
|
||||||
FileUtils.mkdir_p File.dirname(file)
|
|
||||||
|
|
||||||
File.open(file, 'wb') { |fh| fh.print string }
|
|
||||||
end
|
|
|
@ -1,4 +0,0 @@
|
||||||
Given /^I have the symlink "(.*?)" which points to "(.*?)"$/ do |source, target|
|
|
||||||
FileUtils.mkdir_p(File.dirname(source))
|
|
||||||
File.symlink(target, source)
|
|
||||||
end
|
|
|
@ -1,3 +0,0 @@
|
||||||
Then /^I should get the following environments:$/ do |table|
|
|
||||||
@environments.collect(&:to_s).sort.should == table.raw.flatten.sort
|
|
||||||
end
|
|
|
@ -1,4 +0,0 @@
|
||||||
Then /^I should get the following repositories:$/ do |table|
|
|
||||||
@repos.collect(&:to_s).sort.should == table.raw.flatten.sort
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
Then /^the file "(.*?)" should have the following stripped content:$/ do |file, string|
|
|
||||||
test_lines = string.lines.to_a
|
|
||||||
|
|
||||||
File.read(file).lines.collect(&:strip).reject(&:empty?).to_a.each do |line|
|
|
||||||
raise StandardError.new if test_lines.empty?
|
|
||||||
|
|
||||||
line.strip.should == test_lines.shift.strip
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,3 +0,0 @@
|
||||||
Then /^the file "([^"]*)" should have the following content:$/ do |file, string|
|
|
||||||
File.read(file).should == string
|
|
||||||
end
|
|
|
@ -1,3 +0,0 @@
|
||||||
Then /^the file "(.*?)" should include the following content:$/ do |file, string|
|
|
||||||
File.read(file).should include(string)
|
|
||||||
end
|
|
|
@ -1,3 +0,0 @@
|
||||||
Then /^the output should include "([^"]*)"$/ do |text|
|
|
||||||
@output.should include(text)
|
|
||||||
end
|
|
|
@ -1,3 +0,0 @@
|
||||||
Then /^the output should not include "(.*?)"$/ do |text|
|
|
||||||
@output.should_not include(text)
|
|
||||||
end
|
|
|
@ -1,4 +0,0 @@
|
||||||
When /^I rebuild the Gemfile for "(.*?)" mode$/ do |env|
|
|
||||||
Penchant::Gemfile.do_full_env_switch!(env)
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
When /^I rebuild the Gemfile asking to switch back to the previous state$/ do
|
|
||||||
Penchant::Gemfile.switch_back!("remote")
|
|
||||||
end
|
|
|
@ -1,3 +0,0 @@
|
||||||
When /^I rebuild the Gemfile for "([^"]*)" mode with deployment$/ do |env|
|
|
||||||
Penchant::Gemfile.do_full_env_switch!(env, true)
|
|
||||||
end
|
|
|
@ -1,3 +0,0 @@
|
||||||
When /^I request the list of environments available$/ do
|
|
||||||
@environments = Penchant::Gemfile.available_environments
|
|
||||||
end
|
|
|
@ -1,3 +0,0 @@
|
||||||
When /^I request the list of git repositories$/ do
|
|
||||||
@repos = Penchant::Gemfile.defined_git_repos
|
|
||||||
end
|
|
|
@ -1,3 +0,0 @@
|
||||||
When /^I run "([^"]*)" in the "([^"]*)" directory$/ do |command, dir|
|
|
||||||
@output = %x{bash -c 'opwd=$PWD; cd #{dir} && $opwd/#{command}'}
|
|
||||||
end
|
|
|
@ -1,20 +0,0 @@
|
||||||
require 'cuke-pack/support/pause'
|
|
||||||
require 'cuke-pack/support/pending'
|
|
||||||
|
|
||||||
Before do
|
|
||||||
# if you want pending steps to pause before marking the step as pending,
|
|
||||||
# set @pause_ok to true
|
|
||||||
|
|
||||||
@pause_ok = false
|
|
||||||
end
|
|
||||||
|
|
||||||
require 'cuke-pack/support/step_writer'
|
|
||||||
require 'cuke-pack/support/wait_for'
|
|
||||||
require 'cuke-pack/support/failfast'
|
|
||||||
|
|
||||||
# set the level of flaying on the step definitions
|
|
||||||
# set it to false to skip flaying
|
|
||||||
flay_level = 32
|
|
||||||
|
|
||||||
require 'cuke-pack/support/flay'
|
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
require 'fakefs/safe'
|
|
||||||
require 'penchant'
|
|
||||||
require 'mocha'
|
|
||||||
|
|
||||||
World(Mocha::API)
|
|
||||||
|
|
||||||
Before('@fakefs') do
|
|
||||||
FakeFS.activate!
|
|
||||||
end
|
|
||||||
|
|
||||||
Before('@mocha') do
|
|
||||||
mocha_setup
|
|
||||||
end
|
|
||||||
|
|
||||||
After do
|
|
||||||
FakeFS::FileSystem.clear
|
|
||||||
FakeFS.deactivate!
|
|
||||||
|
|
||||||
begin
|
|
||||||
mocha_verify
|
|
||||||
ensure
|
|
||||||
mocha_teardown
|
|
||||||
end
|
|
||||||
|
|
||||||
FileUtils.rm_rf 'tmp'
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,13 +1,3 @@
|
||||||
module Penchant
|
module Penchant
|
||||||
autoload :Gemfile, 'penchant/gemfile'
|
autoload :Gemfile, 'penchant/gemfile'
|
||||||
autoload :Repo, 'penchant/repo'
|
|
||||||
autoload :DotPenchant, 'penchant/dot_penchant'
|
|
||||||
autoload :Hooks, 'penchant/hooks'
|
|
||||||
autoload :Env, 'penchant/env'
|
|
||||||
autoload :FileProcessor, 'penchant/file_processor'
|
|
||||||
autoload :Defaults, 'penchant/defaults'
|
|
||||||
autoload :CustomProperty, 'penchant/custom_property'
|
|
||||||
autoload :PropertyStack, 'penchant/property_stack'
|
|
||||||
autoload :PropertyStackBuilder, 'penchant/property_stack_builder'
|
|
||||||
autoload :PropertyStackProcessor, 'penchant/property_stack_processor'
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
module Penchant
|
|
||||||
class CustomProperty
|
|
||||||
def initialize(value)
|
|
||||||
@value = value
|
|
||||||
end
|
|
||||||
|
|
||||||
def process(values)
|
|
||||||
if @value.respond_to?(:call)
|
|
||||||
@value.call(*values).to_a
|
|
||||||
else
|
|
||||||
@value.collect do |k, v|
|
|
||||||
v = v.dup.gsub(%r{\$(\d+)}) { |m| values[m.to_i - 1 ] }
|
|
||||||
|
|
||||||
[ k, v ]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
module Penchant
|
|
||||||
class Defaults
|
|
||||||
def initialize
|
|
||||||
@defaults = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
def [](key)
|
|
||||||
@defaults[key.to_s] ||= {}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,27 +0,0 @@
|
||||||
module Penchant
|
|
||||||
class DotPenchant
|
|
||||||
class << self
|
|
||||||
def run(env = nil, deployment = false)
|
|
||||||
dot_penchant = new
|
|
||||||
dot_penchant.run(env)
|
|
||||||
dot_penchant
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def run(env = nil, deployment = false)
|
|
||||||
instance_eval(File.read('.penchant'))
|
|
||||||
end
|
|
||||||
|
|
||||||
def rake(*tasks)
|
|
||||||
command = [ "rake", *tasks ]
|
|
||||||
command.unshift("bundle exec") if gemfile?
|
|
||||||
Kernel.system command.join(' ')
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
def gemfile?
|
|
||||||
File.file?('Gemfile')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
module Penchant
|
|
||||||
class Env
|
|
||||||
attr_accessor :name
|
|
||||||
|
|
||||||
def initialize(name)
|
|
||||||
@name = name.to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
def ==(other)
|
|
||||||
@name == other.name
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_s
|
|
||||||
"@#{name}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,210 +0,0 @@
|
||||||
module Penchant
|
|
||||||
class FileProcessor
|
|
||||||
attr_reader :environment, :is_deployment, :available_environments, :defined_git_repos
|
|
||||||
|
|
||||||
ANY_ENVIRONMENT = :any_environment
|
|
||||||
|
|
||||||
def self.result(data, *args)
|
|
||||||
new(data).result(*args)
|
|
||||||
end
|
|
||||||
|
|
||||||
def initialize(data)
|
|
||||||
@data = data
|
|
||||||
@available_environments = []
|
|
||||||
@defined_git_repos = []
|
|
||||||
@defaults = Defaults.new
|
|
||||||
@properties = PropertyStackBuilder.new(@defaults)
|
|
||||||
|
|
||||||
@_current_env_defaults = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
def result(_env, _is_deployment)
|
|
||||||
@environment = _env.to_s.to_sym
|
|
||||||
@is_deployment = _is_deployment
|
|
||||||
|
|
||||||
@output = []
|
|
||||||
|
|
||||||
instance_eval(@data)
|
|
||||||
|
|
||||||
@output.join("\n")
|
|
||||||
end
|
|
||||||
|
|
||||||
def <<(string)
|
|
||||||
@output << string
|
|
||||||
end
|
|
||||||
|
|
||||||
def env(*args)
|
|
||||||
options = {}
|
|
||||||
options = args.pop if args.last.kind_of?(::Hash)
|
|
||||||
|
|
||||||
@available_environments += args
|
|
||||||
|
|
||||||
requested_env_defaults = _defaults_for(Env.new(environment))
|
|
||||||
|
|
||||||
if block_given?
|
|
||||||
if for_environment?(args)
|
|
||||||
@_current_env_defaults = requested_env_defaults
|
|
||||||
yield
|
|
||||||
@_current_env_defaults = {}
|
|
||||||
else
|
|
||||||
if opposite_environment = (options[:opposite] or requested_env_defaults[:opposite])
|
|
||||||
if for_environment?([ environment, args, opposite_environment ].flatten.uniq)
|
|
||||||
@_current_env_defaults = requested_env_defaults
|
|
||||||
@_strip_pathing_options = true
|
|
||||||
yield
|
|
||||||
@_strip_pathing_options = false
|
|
||||||
@_current_env_defaults = {}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
Env.new(args.shift)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def property(name, hash = nil, &block)
|
|
||||||
@properties[name] = hash || block
|
|
||||||
end
|
|
||||||
|
|
||||||
def opposites(left, right)
|
|
||||||
@defaults[Env.new(left)][:opposite] = right
|
|
||||||
@defaults[Env.new(right)][:opposite] = left
|
|
||||||
end
|
|
||||||
|
|
||||||
def for_environment?(envs)
|
|
||||||
envs.include?(environment) || environment == ANY_ENVIRONMENT
|
|
||||||
end
|
|
||||||
|
|
||||||
def no_deployment
|
|
||||||
yield if !is_deployment
|
|
||||||
end
|
|
||||||
|
|
||||||
def ensure_git_hooks!
|
|
||||||
Penchant::Hooks.install!
|
|
||||||
end
|
|
||||||
|
|
||||||
def os(*args)
|
|
||||||
yield if args.include?(current_os)
|
|
||||||
end
|
|
||||||
|
|
||||||
def defaults_for(*args)
|
|
||||||
defaults = args.pop
|
|
||||||
|
|
||||||
args.flatten.each do |gem|
|
|
||||||
@defaults[gem].merge!(defaults)
|
|
||||||
end
|
|
||||||
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 = nil, &given_block)
|
|
||||||
index = @output.length
|
|
||||||
(block || given_block).call
|
|
||||||
index.upto(@output.length - 1) do |i|
|
|
||||||
@output[i] = " " + @output[i]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def _defaults_for(gem_name)
|
|
||||||
result = @_current_env_defaults
|
|
||||||
result.merge(@defaults[gem_name] || {})
|
|
||||||
end
|
|
||||||
|
|
||||||
def current_os
|
|
||||||
require 'rbconfig'
|
|
||||||
case host_os = RbConfig::CONFIG['host_os']
|
|
||||||
when /darwin/
|
|
||||||
:darwin
|
|
||||||
when /linux/
|
|
||||||
:linux
|
|
||||||
else
|
|
||||||
host_os[%r{^[a-z]+}, 1].to_sym
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def gem(*args)
|
|
||||||
gem_name = [ args.shift ]
|
|
||||||
template = {}
|
|
||||||
|
|
||||||
if args.last.kind_of?(::Hash)
|
|
||||||
template = args.pop
|
|
||||||
end
|
|
||||||
|
|
||||||
version = args.first
|
|
||||||
|
|
||||||
options = @properties.create_stack_for(template, @_strip_pathing_options).process_for_gem(gem_name.first, @_current_env_defaults)
|
|
||||||
|
|
||||||
args = [ gem_name.first ]
|
|
||||||
args << version if version
|
|
||||||
|
|
||||||
if options[:git]
|
|
||||||
@defined_git_repos << Penchant::Repo.new(options[:git])
|
|
||||||
end
|
|
||||||
|
|
||||||
args << options if !options.empty?
|
|
||||||
|
|
||||||
self << %{gem #{args_to_string(args)}}
|
|
||||||
end
|
|
||||||
|
|
||||||
def gems(*args)
|
|
||||||
gems, template = split_args(args)
|
|
||||||
|
|
||||||
gems.flatten.each do |gem_name|
|
|
||||||
options = @properties.create_stack_for(template, @_strip_pathing_options).process_for_gem(gem_name)
|
|
||||||
|
|
||||||
args = [ gem_name ]
|
|
||||||
args << options if !options.empty?
|
|
||||||
|
|
||||||
gem *args
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def group(*args, &block)
|
|
||||||
self << ""
|
|
||||||
self << %{group #{args_to_string(args)} do}
|
|
||||||
|
|
||||||
call_and_indent_output(block)
|
|
||||||
|
|
||||||
self << %{end}
|
|
||||||
end
|
|
||||||
|
|
||||||
def ruby(*args)
|
|
||||||
passthrough :ruby, *args
|
|
||||||
end
|
|
||||||
|
|
||||||
def bundler_encoding_fix!
|
|
||||||
self << (<<-RB)
|
|
||||||
if RUBY_VERSION =~ /1.9/
|
|
||||||
Encoding.default_external = Encoding::UTF_8
|
|
||||||
Encoding.default_internal = Encoding::UTF_8
|
|
||||||
end
|
|
||||||
RB
|
|
||||||
end
|
|
||||||
|
|
||||||
def gemspec
|
|
||||||
passthrough :gemspec
|
|
||||||
end
|
|
||||||
|
|
||||||
def source(*args)
|
|
||||||
passthrough :source, *args
|
|
||||||
end
|
|
||||||
|
|
||||||
def passthrough(method, *args)
|
|
||||||
self << %{#{method} #{args_to_string(args)}}.strip
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,40 +1,24 @@
|
||||||
|
require 'erb'
|
||||||
|
|
||||||
module Penchant
|
module Penchant
|
||||||
class Gemfile
|
class Gemfile
|
||||||
attr_reader :path, :is_deployment
|
attr_reader :path
|
||||||
|
|
||||||
def self.do_full_env_switch!(env, deployment = false)
|
class << self
|
||||||
return false if !(gemfile = pre_switch(env, deployment))
|
def do_full_env_switch!(env)
|
||||||
|
gemfile = Penchant::Gemfile.new
|
||||||
|
if !gemfile.has_gemfile_erb?
|
||||||
|
puts "Not using Gemfile.erb, exiting."
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
gemfile.switch_to!(env, deployment)
|
gemfile.switch_to!(env)
|
||||||
|
system %{bundle}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.switch_back!(fallback_env)
|
|
||||||
return false if !(gemfile = pre_switch(fallback_env))
|
|
||||||
|
|
||||||
gemfile.switch_back!(fallback_env)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.pre_switch(env, deployment = false)
|
|
||||||
gemfile = new
|
|
||||||
return false if !gemfile.has_processable_gemfile?
|
|
||||||
gemfile.run_dot_penchant!(env, deployment)
|
|
||||||
|
|
||||||
gemfile
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.available_environments
|
|
||||||
new.available_environments
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.defined_git_repos
|
|
||||||
new.defined_git_repos
|
|
||||||
end
|
|
||||||
|
|
||||||
def current_env ; @env ; end
|
|
||||||
|
|
||||||
def initialize(path = Dir.pwd)
|
def initialize(path = Dir.pwd)
|
||||||
@path = path
|
@path = path
|
||||||
@env = environment
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def gemfile_path
|
def gemfile_path
|
||||||
|
@ -42,75 +26,30 @@ module Penchant
|
||||||
end
|
end
|
||||||
|
|
||||||
def has_gemfile?
|
def has_gemfile?
|
||||||
File.file?(gemfile_path)
|
File.file?('Gemfile')
|
||||||
end
|
end
|
||||||
|
|
||||||
def has_dot_penchant?
|
def gemfile_erb_path
|
||||||
File.file?('.penchant')
|
file_in_path('Gemfile.erb')
|
||||||
end
|
end
|
||||||
|
|
||||||
def gemfile_penchant_path
|
def has_gemfile_erb?
|
||||||
file_in_path('Gemfile.penchant')
|
File.file?(gemfile_erb_path)
|
||||||
end
|
|
||||||
|
|
||||||
def has_gemfile_penchant?
|
|
||||||
File.file?(gemfile_penchant_path)
|
|
||||||
end
|
|
||||||
|
|
||||||
def has_processable_gemfile?
|
|
||||||
has_gemfile_penchant?
|
|
||||||
end
|
|
||||||
|
|
||||||
def processable_gemfile_path
|
|
||||||
gemfile_penchant_path
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def environment
|
def environment
|
||||||
gemfile_header.strip[%r{environment: ([^, ]*)}, 1]
|
File.readlines(gemfile_path).first.strip[%r{environment: (.*)}, 1]
|
||||||
end
|
end
|
||||||
|
|
||||||
def deployment?
|
def switch_to!(gemfile_env = nil)
|
||||||
gemfile_header['deployment mode'] != nil
|
@env = gemfile_env
|
||||||
end
|
template = File.read(gemfile_erb_path)
|
||||||
|
|
||||||
def available_environments
|
File.open(gemfile_path, 'wb') do |fh|
|
||||||
process
|
fh.puts "# generated by penchant, environment: #{@env}"
|
||||||
builder.available_environments
|
|
||||||
end
|
|
||||||
|
|
||||||
def defined_git_repos
|
fh.print ERB.new(template).result(binding)
|
||||||
process(FileProcessor::ANY_ENVIRONMENT)
|
|
||||||
builder.defined_git_repos
|
|
||||||
end
|
|
||||||
|
|
||||||
def switch_to!(gemfile_env = nil, deployment = false)
|
|
||||||
@env, @is_deployment = gemfile_env, deployment
|
|
||||||
|
|
||||||
output = [ header, process ]
|
|
||||||
|
|
||||||
File.open(gemfile_path, 'wb') { |fh| fh.print output.join("\n") }
|
|
||||||
end
|
|
||||||
|
|
||||||
def run_dot_penchant!(env, deployment)
|
|
||||||
DotPenchant.run(env || environment, deployment) if has_dot_penchant?
|
|
||||||
end
|
|
||||||
|
|
||||||
def header
|
|
||||||
header = [ "# generated by penchant, environment: #{current_env}" ]
|
|
||||||
|
|
||||||
if is_deployment
|
|
||||||
header << ", deployment mode (was #{environment})"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
header.join
|
|
||||||
end
|
|
||||||
|
|
||||||
def prior_environment
|
|
||||||
gemfile_header[%r{\(was (.+)\)}, 1]
|
|
||||||
end
|
|
||||||
|
|
||||||
def switch_back!(fallback_env)
|
|
||||||
switch_to!(prior_environment || fallback_env)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -118,20 +57,8 @@ module Penchant
|
||||||
File.join(@path, file)
|
File.join(@path, file)
|
||||||
end
|
end
|
||||||
|
|
||||||
def process(env = @env)
|
def env(check, &block)
|
||||||
builder.result(env, @is_deployment)
|
instance_eval(&block) if check.to_s == @env.to_s
|
||||||
end
|
|
||||||
|
|
||||||
def builder
|
|
||||||
@builder ||= FileProcessor.new(template)
|
|
||||||
end
|
|
||||||
|
|
||||||
def template
|
|
||||||
File.read(processable_gemfile_path)
|
|
||||||
end
|
|
||||||
|
|
||||||
def gemfile_header
|
|
||||||
(has_gemfile? and File.readlines(gemfile_path).first) or ""
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
require 'pathname'
|
|
||||||
|
|
||||||
module Penchant
|
|
||||||
class Hooks
|
|
||||||
HOOKS_DIR = 'script/hooks'
|
|
||||||
GIT_HOOKS_DIR = '.git/hooks'
|
|
||||||
|
|
||||||
def self.installed?
|
|
||||||
if File.directory?(HOOKS_DIR)
|
|
||||||
Dir[File.join(HOOKS_DIR, '*')].each do |file|
|
|
||||||
target = File.join(GIT_HOOKS_DIR, File.basename(file))
|
|
||||||
return false if !File.symlink?(target)
|
|
||||||
return false if !File.expand_path(File.readlink(target)) == File.expand_path(file)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.install!
|
|
||||||
if git?
|
|
||||||
puts "[penchant] installing git hooks"
|
|
||||||
|
|
||||||
Dir['script/hooks/*'].each do |hook|
|
|
||||||
FileUtils.ln_sf File.join(Dir.pwd, hook), "#{GIT_HOOKS_DIR}/#{File.split(hook).last}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.git?
|
|
||||||
File.directory?(GIT_HOOKS_DIR)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
module Penchant
|
|
||||||
class PropertyStack
|
|
||||||
PATHING_OPTIONS = [ :git, :branch, :path ].freeze
|
|
||||||
|
|
||||||
def initialize(builder, property_stack, strip_pathing_options)
|
|
||||||
@builder, @property_stack, @strip_pathing_options = builder, property_stack.dup, strip_pathing_options
|
|
||||||
end
|
|
||||||
|
|
||||||
def processor
|
|
||||||
@processor ||= PropertyStackProcessor.new(@builder)
|
|
||||||
end
|
|
||||||
|
|
||||||
def process_for_gem(gem_name, additional_env = {})
|
|
||||||
properties = processor.process(gem_name, @property_stack)
|
|
||||||
|
|
||||||
if @strip_pathing_options
|
|
||||||
PATHING_OPTIONS.each { |key| properties.delete(key) }
|
|
||||||
end
|
|
||||||
|
|
||||||
properties = processor.process(gem_name, @builder.defaults[gem_name].merge(additional_env)).merge(properties)
|
|
||||||
|
|
||||||
properties.delete(:opposite)
|
|
||||||
|
|
||||||
Hash[properties.sort]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
module Penchant
|
|
||||||
class PropertyStackBuilder
|
|
||||||
attr_reader :defaults
|
|
||||||
|
|
||||||
def initialize(defaults)
|
|
||||||
@defaults = defaults
|
|
||||||
|
|
||||||
@custom_properties = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
def []=(key, value)
|
|
||||||
@custom_properties[key] = CustomProperty.new(value)
|
|
||||||
end
|
|
||||||
|
|
||||||
def [](key)
|
|
||||||
@custom_properties[key]
|
|
||||||
end
|
|
||||||
|
|
||||||
def create_stack_for(stack, strip_pathing_options = false)
|
|
||||||
PropertyStack.new(self, stack, strip_pathing_options)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
module Penchant
|
|
||||||
class PropertyStackProcessor
|
|
||||||
def initialize(builder)
|
|
||||||
@builder = builder
|
|
||||||
end
|
|
||||||
|
|
||||||
def process(gem_name, stack)
|
|
||||||
properties = {}
|
|
||||||
property_stack = stack.dup.to_a
|
|
||||||
|
|
||||||
while !property_stack.empty?
|
|
||||||
key, value = property_stack.shift
|
|
||||||
|
|
||||||
if property = @builder[key]
|
|
||||||
property_stack += property.process([ value ].flatten)
|
|
||||||
else
|
|
||||||
value = value % gem_name if value.respond_to?(:%)
|
|
||||||
|
|
||||||
properties[key] = value
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
properties
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,16 +0,0 @@
|
||||||
module Penchant
|
|
||||||
class Repo
|
|
||||||
def initialize(url)
|
|
||||||
@url = url
|
|
||||||
end
|
|
||||||
|
|
||||||
def clone_to(dir)
|
|
||||||
Dir.chdir(dir) do
|
|
||||||
system %{git clone #{@url}}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_s ; @url ; end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
module Penchant
|
module Penchant
|
||||||
VERSION = "0.2.29"
|
VERSION = "0.0.1"
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,13 +18,4 @@ Gem::Specification.new do |s|
|
||||||
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
||||||
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
||||||
s.require_paths = ["lib"]
|
s.require_paths = ["lib"]
|
||||||
|
|
||||||
s.add_dependency 'bundler'
|
|
||||||
s.add_dependency 'thor'
|
|
||||||
|
|
||||||
s.add_development_dependency 'cucumber'
|
|
||||||
s.add_development_dependency 'mocha'
|
|
||||||
s.add_development_dependency 'fakefs'
|
|
||||||
s.add_development_dependency 'rspec', '~> 2.6.0'
|
|
||||||
s.add_development_dependency 'rake'
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
#!/usr/bin/env ruby
|
|
||||||
|
|
||||||
require 'rubygems'
|
|
||||||
require 'penchant'
|
|
||||||
|
|
||||||
if Penchant::Gemfile.do_full_env_switch!(ARGV[0])
|
|
||||||
puts "Gemfile switched to #{ARGV[0]}"
|
|
||||||
else
|
|
||||||
exit 0
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
msg=$(cat $1)
|
|
||||||
|
|
||||||
# wtf mac os x lion
|
|
||||||
if [ ! -z "$MY_RUBY_HOME" ]; then
|
|
||||||
PATH="$MY_RUBY_HOME/bin:$PATH"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -z "$GEM_PATH" ]; then
|
|
||||||
oifs="$IFS"
|
|
||||||
while IFS=":" read -ra GEM_PATHS; do
|
|
||||||
FIXED_GEM_PATH=""
|
|
||||||
for i in "${GEM_PATHS[@]}"; do
|
|
||||||
FIXED_GEM_PATH="$FIXED_GEM_PATH:${i}/bin"
|
|
||||||
done
|
|
||||||
done <<< "$GEM_PATH"
|
|
||||||
IFS="$oifs"
|
|
||||||
PATH="$FIXED_GEM_PATH:$PATH"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "${msg}" != *"[ci skip]"* ]]; then
|
|
||||||
bundle exec rake --trace
|
|
||||||
R=$?
|
|
||||||
if [ $R -ne 0 ]; then exit $R; fi
|
|
||||||
fi
|
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
#!/usr/bin/env ruby
|
|
||||||
|
|
||||||
puts "Bundling..."
|
|
||||||
system %{bundle}
|
|
||||||
|
|
||||||
puts "Installing git hooks"
|
|
||||||
system %{script/install-git-hooks}
|
|
||||||
|
|
||||||
bundle = File.file?('Gemfile') ? 'bundle exec' : ''
|
|
||||||
|
|
||||||
command = [ bundle, 'rake', '-s', '-T', 'bootstrap' ]
|
|
||||||
|
|
||||||
if !(%x{#{command.join(' ')}}).empty?
|
|
||||||
puts "Trying to run rake bootstrap..."
|
|
||||||
system %{#{bundle} rake bootstrap}
|
|
||||||
end
|
|
||||||
|
|
||||||
puts "Done!"
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
for hook in script/hooks/* ; do
|
|
||||||
ln -sf $PWD/$hook .git/hooks/${hook##*/}
|
|
||||||
done
|
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe Penchant::Gemfile do
|
||||||
|
include FakeFS::SpecHelpers
|
||||||
|
|
||||||
|
let(:dir) { File.expand_path(Dir.pwd) }
|
||||||
|
let(:gemfile) { described_class.new(dir) }
|
||||||
|
|
||||||
|
let(:gemfile_path) { File.join(dir, 'Gemfile') }
|
||||||
|
let(:gemfile_erb_path) { File.join(dir, 'Gemfile.erb') }
|
||||||
|
|
||||||
|
def write_file(path, content = nil)
|
||||||
|
File.open(path, 'wb') do |fh|
|
||||||
|
content = yield if block_given?
|
||||||
|
fh.print content
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
subject { gemfile }
|
||||||
|
|
||||||
|
context 'with no gemfile' do
|
||||||
|
it { should_not have_gemfile }
|
||||||
|
it { should_not have_gemfile_erb }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with gemfile' do
|
||||||
|
let(:data) { "whatever" }
|
||||||
|
|
||||||
|
before do
|
||||||
|
write_file(gemfile_path) { data }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'existence' do
|
||||||
|
it { should have_gemfile }
|
||||||
|
it { should_not have_gemfile_erb }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#environment' do
|
||||||
|
context 'not defined' do
|
||||||
|
its(:environment) { should be_nil }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'defined' do
|
||||||
|
let(:environment) { 'test' }
|
||||||
|
let(:data) { <<-GEMFILE }
|
||||||
|
# generated by penchant, environment: #{environment}
|
||||||
|
GEMFILE
|
||||||
|
|
||||||
|
its(:environment) { should == environment }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#switch_to!' do
|
||||||
|
it 'should raise an exception' do
|
||||||
|
expect { subject.switch_to!(:whatever) }.to raise_error(Errno::ENOENT)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with gemfile.erb' do
|
||||||
|
let(:erb_data) { 'whatever' }
|
||||||
|
|
||||||
|
before do
|
||||||
|
write_file(gemfile_erb_path) { erb_data }
|
||||||
|
end
|
||||||
|
|
||||||
|
it { should_not have_gemfile }
|
||||||
|
it { should have_gemfile_erb }
|
||||||
|
|
||||||
|
describe '#switch_to!' do
|
||||||
|
let(:erb_data) { <<-ERB }
|
||||||
|
<% env :test do %>
|
||||||
|
test
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<% env :not do %>
|
||||||
|
not
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
all
|
||||||
|
ERB
|
||||||
|
|
||||||
|
it 'should render test data' do
|
||||||
|
subject.switch_to!(:test)
|
||||||
|
|
||||||
|
File.read('Gemfile').should include('test')
|
||||||
|
File.read('Gemfile').should_not include('not')
|
||||||
|
File.read('Gemfile').should include('all')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should not render test data' do
|
||||||
|
subject.switch_to!(:not)
|
||||||
|
|
||||||
|
File.read('Gemfile').should_not include('test')
|
||||||
|
File.read('Gemfile').should include('not')
|
||||||
|
File.read('Gemfile').should include('all')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should not render either' do
|
||||||
|
subject.switch_to!
|
||||||
|
|
||||||
|
File.read('Gemfile').should_not include('test')
|
||||||
|
File.read('Gemfile').should_not include('not')
|
||||||
|
File.read('Gemfile').should include('all')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
require 'fakefs/spec_helpers'
|
||||||
|
require 'penchant'
|
||||||
|
|
||||||
|
RSpec.configure do |c|
|
||||||
|
c.mock_with :mocha
|
||||||
|
end
|
|
@ -1,40 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
msg=$(cat $1)
|
|
||||||
|
|
||||||
OLD_GIT_DIR=$GIT_DIR
|
|
||||||
|
|
||||||
# lion appears to insert git paths before everything else. ensure rvm can
|
|
||||||
# bust through, at the very least.
|
|
||||||
if [ ! -z "$MY_RUBY_HOME" ]; then
|
|
||||||
PATH="$MY_RUBY_HOME/bin:$PATH"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -z "$GEM_PATH" ]; then
|
|
||||||
oifs="$IFS"
|
|
||||||
while IFS=":" read -ra GEM_PATHS; do
|
|
||||||
FIXED_GEM_PATH=""
|
|
||||||
for i in "${GEM_PATHS[@]}"; do
|
|
||||||
FIXED_GEM_PATH="$FIXED_GEM_PATH:${i}/bin"
|
|
||||||
done
|
|
||||||
done <<< "$GEM_PATH"
|
|
||||||
IFS="$oifs"
|
|
||||||
PATH="$FIXED_GEM_PATH:$PATH"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "${msg}" != *"[ci skip]"* ]]; then
|
|
||||||
if [ "$(penchant gemfile-env)" != "remote" ]; then
|
|
||||||
unset GIT_DIR
|
|
||||||
penchant gemfile remote
|
|
||||||
GIT_DIR=$OLD_GIT_DIR
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ $(bundle exec rake -P | grep default | wc -l) -ne 0 ]; then
|
|
||||||
bundle exec rake
|
|
||||||
R=$?
|
|
||||||
if [ $R -ne 0 ]; then exit $R; fi
|
|
||||||
else
|
|
||||||
echo "[penchant] No default Rake task found! Add one if you want to run tests before committing."
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
unset GIT_DIR
|
|
||||||
echo "Run penchant gemfile remote to get back to work!"
|
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
if [ $(bundle exec rake -P | grep preflight_check | wc -l) -ne 0 ]; then
|
OLD_GIT_DIR=$GIT_DIR
|
||||||
bundle exec rake preflight_check
|
|
||||||
R=$?
|
|
||||||
if [ $R -ne 0 ]; then exit $R; fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
unset GIT_DIR
|
unset GIT_DIR
|
||||||
penchant gemfile remote --deployment
|
penchant gemfile remote
|
||||||
GIT_DIR=$OLD_GIT_DIR
|
GIT_DIR=$OLD_GIT_DIR
|
||||||
git add Gemfile*
|
|
||||||
|
|
||||||
exit 0
|
bundle exec rake
|
||||||
|
R=$?
|
||||||
|
if [ $R -ne 0 ]; then exit $R; fi
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,23 @@
|
||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
puts "Bundling..."
|
if File.file?('Gemfile.erb')
|
||||||
system %{bundle}
|
pwd = Dir.pwd
|
||||||
|
|
||||||
|
Dir.chdir '..' do
|
||||||
|
File.readlines(File.join(pwd, 'Gemfile.erb')).find_all { |line| line[':git'] }.each do |line|
|
||||||
|
repo = line[%r{:git => (['"])(.*)\1}, 2]
|
||||||
|
|
||||||
|
puts "Installing #{repo}"
|
||||||
|
system %{git clone #{repo}}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
puts "Bundling for local environment"
|
||||||
|
system %{script/gemfile local}
|
||||||
|
else
|
||||||
|
puts "Bundling..."
|
||||||
|
system %{bundle}
|
||||||
|
end
|
||||||
|
|
||||||
puts "Installing git hooks"
|
puts "Installing git hooks"
|
||||||
system %{script/install-git-hooks}
|
system %{script/install-git-hooks}
|
||||||
|
|
Loading…
Reference in New Issue