flipp 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +17 -0
- data/Rakefile +2 -0
- data/flipp.gemspec +24 -0
- data/lib/flipp.rb +2 -0
- data/lib/flipp/flipp.rb +56 -0
- data/lib/flipp/railties/reestablish_connection.rb +11 -0
- data/lib/helpers/git_helper.rb +33 -0
- data/spec/lib/flipp/flipp_spec.rb +66 -0
- data/spec/lib/helpers/git_helper_spec.rb +41 -0
- data/spec/spec_helper.rb +3 -0
- data/tasks/flipp.rb +15 -0
- metadata +82 -0
data/README.md
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# flipp
|
2
|
+
|
3
|
+
To alleviate issues around highly divergent development databases on feature/refactor branches, flipp helps switch databases upon new branch checkouts.
|
4
|
+
|
5
|
+
# Database Support
|
6
|
+
|
7
|
+
Current support is for MySQL only.
|
8
|
+
|
9
|
+
# Installation & Usage
|
10
|
+
|
11
|
+
1. Add `gem 'flipp'` to your Gemfile or do `gem install flipp`.
|
12
|
+
2. Run `rake flipp:install` from your project's root directory to install the git hook
|
13
|
+
3. Normal git workflow, ie. switch branches normally
|
14
|
+
|
15
|
+
# License
|
16
|
+
|
17
|
+
flipp is released under the MIT license
|
data/Rakefile
ADDED
data/flipp.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
lib = File.expand_path('../lib/', __FILE__)
|
2
|
+
$:.unshift lib unless $:.include?(lib)
|
3
|
+
|
4
|
+
require 'bundler'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "flipp"
|
8
|
+
s.version = '0.0.1'
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.authors = ["Mike Pack"]
|
11
|
+
s.email = ["mikepackdev@gmail.com"]
|
12
|
+
s.homepage = "http://www.mikepackdev.com"
|
13
|
+
s.summary = %q{Switch development databases upon branch checkouts.}
|
14
|
+
s.description = %q{To alleviate issues around highly divergent development databases on feature/refactor branches, flipp helps switch databases upon new branch checkouts.}
|
15
|
+
|
16
|
+
s.required_rubygems_version = ">= 1.3.6"
|
17
|
+
|
18
|
+
s.add_runtime_dependency 'active_record'
|
19
|
+
s.add_runtime_dependency 'database_exporter'
|
20
|
+
|
21
|
+
s.files = %w( README.md Rakefile flipp.gemspec tasks/flipp.rb ) + Dir["lib/**/*.rb"]
|
22
|
+
s.test_files = Dir["spec/**/*.rb"]
|
23
|
+
s.require_paths = ["lib"]
|
24
|
+
end
|
data/lib/flipp.rb
ADDED
data/lib/flipp/flipp.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_record'
|
3
|
+
require 'database_exporter'
|
4
|
+
require File.join(File.dirname(__FILE__), '../helpers/git_helper')
|
5
|
+
|
6
|
+
# The Flipp class orchestrates the actual switching of databaseses
|
7
|
+
class Flipp
|
8
|
+
def initialize(branch = GitHelper.current_branch)
|
9
|
+
@branch = branch
|
10
|
+
end
|
11
|
+
|
12
|
+
def switch_databases
|
13
|
+
current_config = ActiveRecord::Base.connection_pool.spec.config
|
14
|
+
new_config = current_config.merge!({:database => new_database_name(current_config)})
|
15
|
+
|
16
|
+
puts "Switching databases (#{new_config[:database]})..."
|
17
|
+
|
18
|
+
# Try connecting to the new database
|
19
|
+
begin
|
20
|
+
ActiveRecord::Base.establish_connection new_config
|
21
|
+
rescue
|
22
|
+
create_new_db_or_fallback current_config, new_config
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_new_db_or_fallback(current_config, new_config)
|
27
|
+
# Try creating then connecting to the new database
|
28
|
+
begin
|
29
|
+
create_and_copy_data! current_config, new_config
|
30
|
+
rescue => exception
|
31
|
+
# Fallback and use the original config
|
32
|
+
puts "Could not use the new database, falling back to your normal development database..."
|
33
|
+
ActiveRecord::Base.establish_connection current_config
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def new_database_name(config)
|
38
|
+
# The new name for the database
|
39
|
+
# eg. if the original dev database is dev_db and the branch was "new_feature",
|
40
|
+
# the new database would be db_db_new_feature
|
41
|
+
config[:database] + '_' + @branch
|
42
|
+
end
|
43
|
+
|
44
|
+
def create_and_copy_data!(current_config, new_config)
|
45
|
+
# Copy the current development database's data to the new database
|
46
|
+
puts "Copying data to the new database (this could take a minute but will only run once)..."
|
47
|
+
copy_data current_config, new_config
|
48
|
+
|
49
|
+
# Try out the new database
|
50
|
+
ActiveRecord::Base.establish_connection new_config
|
51
|
+
end
|
52
|
+
|
53
|
+
def copy_data(current_config, new_config)
|
54
|
+
DatabaseExporter.new(current_config).copy(new_config)
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'flipp'
|
2
|
+
|
3
|
+
class ReestablishConnection < Rails::Railtie
|
4
|
+
initializer "restablish_connection.configure_rails_initialization" do
|
5
|
+
if Rails.env.development? and GitHelper.hook_installed?
|
6
|
+
# Use the connection determined by flipp
|
7
|
+
flipp = Flipp.new
|
8
|
+
flipp.switch_databases
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module GitHelper
|
4
|
+
def self.hook_installed?
|
5
|
+
File.exists? '.git/hooks/post-checkout'
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.install_hook
|
9
|
+
# Check for the .git directory
|
10
|
+
if File.directory? '.git'
|
11
|
+
unless File.directory? '.git/hooks'
|
12
|
+
# Create hooks directory
|
13
|
+
end
|
14
|
+
|
15
|
+
# Copy the file to the git hooks
|
16
|
+
puts 'Moving git hook into place...'
|
17
|
+
FileUtils.cp 'lib/git_hooks/post-checkout', File.expand_path('.git/hooks/post-checkout')
|
18
|
+
# And give it execute permissions
|
19
|
+
FileUtils.chmod 0755, '.git/hooks/post-checkout'
|
20
|
+
else
|
21
|
+
puts "Can't find your .git directory. Are you at the root of your project?"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.uninstall_hook
|
26
|
+
puts 'Removing git hook...'
|
27
|
+
FileUtils.rm File.expand_path('.git/hooks/post-checkout')
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.current_branch
|
31
|
+
`git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* /\1/'`.chomp[1..-1] # Remove control character
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Flipp do
|
4
|
+
let(:flipp) { Flipp.new('new_feature_branch') }
|
5
|
+
let(:old_db) { {:adapter => 'mysql2', :host => 'localhost', :username => 'root', :database => 'old_db'} }
|
6
|
+
let(:new_db) { {:adapter => 'mysql2', :host => 'localhost', :username => 'root', :database => 'new_db'} }
|
7
|
+
|
8
|
+
describe '#switch_databases' do
|
9
|
+
before do
|
10
|
+
# Stub the current connection
|
11
|
+
ActiveRecord::Base.stub_chain(:connection_pool, :spec, :config).and_return({:adapter => 'mysql2', :host => 'localhost', :username => 'root', :database => 'old_db'})
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'tries to connect to the new database' do
|
15
|
+
ActiveRecord::Base.should_receive(:establish_connection).with(an_instance_of(Hash))
|
16
|
+
flipp.switch_databases
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'tries to create and copy data to new database, then connect' do
|
20
|
+
ActiveRecord::Base.stub(:establish_connection) { raise }
|
21
|
+
flipp.should_receive(:create_new_db_or_fallback).with(an_instance_of(Hash), an_instance_of(Hash))
|
22
|
+
flipp.switch_databases
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#create_new_db_or_fallback' do
|
27
|
+
it 'falls back on the original connection if the new database can not be formed' do
|
28
|
+
flipp.stub(:create_and_copy_data!) { raise }
|
29
|
+
flipp.should_receive(:create_and_copy_data!).with(old_db, new_db)
|
30
|
+
ActiveRecord::Base.should_receive(:establish_connection).with(old_db)
|
31
|
+
flipp.create_new_db_or_fallback(old_db, new_db)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#new_database_name' do
|
36
|
+
it 'constructs a database name consisting of the current dev db and the branch name' do
|
37
|
+
flipp.new_database_name({:database => 'dev_db'}).should == 'dev_db_new_feature_branch'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#create_and_copy_data!' do
|
42
|
+
it 'copies the database' do
|
43
|
+
flipp.should_receive(:copy_data).with(old_db, new_db)
|
44
|
+
flipp.create_and_copy_data!(old_db, new_db)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'tries to connect to the new database' do
|
48
|
+
ActiveRecord::Base.should_receive(:establish_connection).with(new_db)
|
49
|
+
flipp.create_and_copy_data!(old_db, new_db)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '#copy_data' do
|
54
|
+
it 'invokes the database adapter and makes a copy' do
|
55
|
+
# Mock DatabaseExporter so we can access the #copy method
|
56
|
+
mock = double(DatabaseExporter)
|
57
|
+
DatabaseExporter.stub(:new).and_return(mock)
|
58
|
+
|
59
|
+
# Expect it to instantiate and call the #copy method
|
60
|
+
DatabaseExporter.should_receive(:new).with(old_db)
|
61
|
+
mock.should_receive(:copy).with(new_db)
|
62
|
+
|
63
|
+
flipp.copy_data(old_db, new_db)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GitHelper do
|
4
|
+
describe '#hook_installed?' do
|
5
|
+
it 'returns true when the hook exists' do
|
6
|
+
FileUtils.touch '.git/hooks/post-checkout'
|
7
|
+
GitHelper.hook_installed?.should be_true
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'returns false when the hook does not exists' do
|
11
|
+
FileUtils.rm '.git/hooks/post-checkout'
|
12
|
+
GitHelper.hook_installed?.should be_false
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#install_hook' do
|
17
|
+
it 'moves the git hook into place' do
|
18
|
+
GitHelper.install_hook
|
19
|
+
FileUtils.compare_file('.git/hooks/post-checkout', File.expand_path('../../../../lib/git_hooks/post-checkout', __FILE__))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#uninstall_hook' do
|
24
|
+
before { GitHelper.install_hook }
|
25
|
+
|
26
|
+
it 'remove the git hook' do
|
27
|
+
GitHelper.uninstall_hook
|
28
|
+
GitHelper.hook_installed?.should be_false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#current_branch' do
|
33
|
+
it 'returns the name of the current git branch' do
|
34
|
+
`git checkout -b new_and_fun_branch`
|
35
|
+
GitHelper.current_branch.should == 'new_and_fun_branch'
|
36
|
+
|
37
|
+
# Cleanup
|
38
|
+
`git checkout master && git branch -d new_and_fun_branch`
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/spec/spec_helper.rb
ADDED
data/tasks/flipp.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../lib/helpers/git_helper')
|
2
|
+
|
3
|
+
namespace :flipp do
|
4
|
+
desc 'Install flipp'
|
5
|
+
task :install do
|
6
|
+
# Move git hook into place
|
7
|
+
GitHelper.install_hook
|
8
|
+
end
|
9
|
+
|
10
|
+
desc 'Uninstall flipp'
|
11
|
+
task :uninstall do
|
12
|
+
# Remove git hook
|
13
|
+
GitHelper.uninstall_hook
|
14
|
+
end
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: flipp
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Mike Pack
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-02-19 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: active_record
|
16
|
+
requirement: &70345674000980 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70345674000980
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: database_exporter
|
27
|
+
requirement: &70345673999500 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70345673999500
|
36
|
+
description: To alleviate issues around highly divergent development databases on
|
37
|
+
feature/refactor branches, flipp helps switch databases upon new branch checkouts.
|
38
|
+
email:
|
39
|
+
- mikepackdev@gmail.com
|
40
|
+
executables: []
|
41
|
+
extensions: []
|
42
|
+
extra_rdoc_files: []
|
43
|
+
files:
|
44
|
+
- README.md
|
45
|
+
- Rakefile
|
46
|
+
- flipp.gemspec
|
47
|
+
- tasks/flipp.rb
|
48
|
+
- lib/flipp/flipp.rb
|
49
|
+
- lib/flipp/railties/reestablish_connection.rb
|
50
|
+
- lib/flipp.rb
|
51
|
+
- lib/helpers/git_helper.rb
|
52
|
+
- spec/lib/flipp/flipp_spec.rb
|
53
|
+
- spec/lib/helpers/git_helper_spec.rb
|
54
|
+
- spec/spec_helper.rb
|
55
|
+
homepage: http://www.mikepackdev.com
|
56
|
+
licenses: []
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options: []
|
59
|
+
require_paths:
|
60
|
+
- lib
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ! '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 1.3.6
|
73
|
+
requirements: []
|
74
|
+
rubyforge_project:
|
75
|
+
rubygems_version: 1.8.10
|
76
|
+
signing_key:
|
77
|
+
specification_version: 3
|
78
|
+
summary: Switch development databases upon branch checkouts.
|
79
|
+
test_files:
|
80
|
+
- spec/lib/flipp/flipp_spec.rb
|
81
|
+
- spec/lib/helpers/git_helper_spec.rb
|
82
|
+
- spec/spec_helper.rb
|