mysqlnoio 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +16 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +78 -0
- data/Guardfile +8 -0
- data/LICENSE +622 -0
- data/README.md +45 -0
- data/Rakefile +43 -0
- data/Vagrantfile +18 -0
- data/bin/mysql-noio +49 -0
- data/lib/mysqlnoio/about.rb +12 -0
- data/lib/mysqlnoio/errors.rb +11 -0
- data/lib/mysqlnoio/wrap.rb +34 -0
- data/lib/mysqlnoio/wrap_stack.rb +65 -0
- data/lib/mysqlnoio/wraps/blocks.rb +24 -0
- data/lib/mysqlnoio/wraps/deactivated_slave.rb +18 -0
- data/lib/mysqlnoio/wraps/global_lock.rb +21 -0
- data/lib/mysqlnoio.rb +19 -0
- data/mysqlnoio.gemspec +39 -0
- data/spec/integration/mysql-noio_spec.rb +17 -0
- data/spec/mysqlnoio/wrap_stack_spec.rb +66 -0
- data/spec/mysqlnoio/wraps/blocks_spec.rb +44 -0
- data/spec/mysqlnoio/wraps/deactivated_slave_spec.rb +25 -0
- data/spec/mysqlnoio/wraps/global_lock_spec.rb +25 -0
- data/spec/spec_helper.rb +6 -0
- data/vagrant/provision.sh +13 -0
- metadata +235 -0
data/Rakefile
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
require 'mysqlnoio'
|
4
|
+
|
5
|
+
desc "Builds the gem"
|
6
|
+
task :build do
|
7
|
+
sh "gem build mysqlnoio.gemspec"
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "Publishes the gem to fury.io"
|
11
|
+
task :publish => [:build] do |t|
|
12
|
+
sh "git tag -f #{MySQLNoIo::VERSION}"
|
13
|
+
sh "git push origin #{MySQLNoIo::VERSION} -f"
|
14
|
+
sh "curl -F p1=@mysqlnoio-#{MySQLNoIo::VERSION}.gem https://push.fury.io/BEz67VknqnyqmV6p7Huq/"
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Cleans the project directory up"
|
18
|
+
task :clean do
|
19
|
+
sh "rm -rf doc/ tmp/"
|
20
|
+
sh "rm -f mysqlnoio-*.gem"
|
21
|
+
end
|
22
|
+
|
23
|
+
# Various RSpec Bitties
|
24
|
+
base_opts = '--color --order random'
|
25
|
+
desc "Run specs"
|
26
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
27
|
+
t.verbose = false
|
28
|
+
t.rspec_opts = "#{base_opts} --tag ~integration"
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "Run integration specs"
|
32
|
+
RSpec::Core::RakeTask.new(:integration) do |t|
|
33
|
+
t.verbose = false
|
34
|
+
t.rspec_opts = "#{base_opts} --tag integration"
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "Run all specs"
|
38
|
+
RSpec::Core::RakeTask.new(:test) do |t|
|
39
|
+
t.verbose = false
|
40
|
+
t.rspec_opts = base_opts
|
41
|
+
end
|
42
|
+
|
43
|
+
task :default => :spec
|
data/Vagrantfile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- mode: ruby -*-
|
2
|
+
# vi: set ft=ruby :
|
3
|
+
|
4
|
+
$boot = <<SCRIPT
|
5
|
+
sudo apt-get install build-essential
|
6
|
+
|
7
|
+
curl -L https://get.rvm.io | bash -s --autolibs=3 --ruby
|
8
|
+
SCRIPT
|
9
|
+
|
10
|
+
Vagrant.configure("2") do |config|
|
11
|
+
config.vm.box = "ubuntu-12.04.2-server-adm54-vmware-fusion"
|
12
|
+
config.vm.box_url = "https://s3.amazonaws.com/gsc-vagrant-boxes/ubuntu-12.04.2-server-amd64.box"
|
13
|
+
|
14
|
+
config.vm.provision :shell do |shell|
|
15
|
+
shell.inline = $script
|
16
|
+
shell.path = 'vagrant/provision.sh'
|
17
|
+
end
|
18
|
+
end
|
data/bin/mysql-noio
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'mysqlnoio'
|
5
|
+
|
6
|
+
credentials = {}
|
7
|
+
wraps = []
|
8
|
+
|
9
|
+
OptionParser.new do |opts|
|
10
|
+
opts.banner = "Usage: mysql-noio [options] <command>"
|
11
|
+
|
12
|
+
# Determine the MySQL connection parameters
|
13
|
+
opts.on("-u", "--user USER", "MySQL Username") do |v|
|
14
|
+
credentials[:username] = v
|
15
|
+
end
|
16
|
+
|
17
|
+
opts.on("-p", "--password PASSWORD", "MySQL Password") do |v|
|
18
|
+
credentials[:password] = v
|
19
|
+
end
|
20
|
+
|
21
|
+
opts.on("-h", "--host HOST", "MySQL Server Host") do |v|
|
22
|
+
credentials[:host] = v
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
opts.on("-t", "--lock-tables", "Lock tables with a read lock") do |v|
|
27
|
+
wraps << :lock
|
28
|
+
end
|
29
|
+
|
30
|
+
opts.on("-s", "--stop-slave", "Stop the slave thread") do |v|
|
31
|
+
wraps << :stop
|
32
|
+
end
|
33
|
+
|
34
|
+
opts.on
|
35
|
+
end.parse!
|
36
|
+
|
37
|
+
client = Mysql2::Client.new(credentials)
|
38
|
+
|
39
|
+
stack = MySQLNoIo::WrapStack.new
|
40
|
+
stack.add_wrap MySQLNoIo::Wraps::DeactivatedSlave.new client if wraps.include? :stop
|
41
|
+
stack.add_wrap MySQLNoIo::Wraps::GlobalLock.new client if wraps.include? :lock
|
42
|
+
|
43
|
+
stack.execute do
|
44
|
+
spawn *ARGV
|
45
|
+
Process.wait
|
46
|
+
end
|
47
|
+
|
48
|
+
exit $?.to_i
|
49
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
|
2
|
+
module MySQLNoIo
|
3
|
+
# Used in Gemspec and Commander
|
4
|
+
NAME = 'mysqlnoio'
|
5
|
+
|
6
|
+
# Used in Gemspec and Commander
|
7
|
+
VERSION = '0.1.0'
|
8
|
+
|
9
|
+
# Used in Gemspec and Commander
|
10
|
+
DESCRIPTION = 'mysqlnoio allows you to execute commands while MySQL is locked.'
|
11
|
+
end
|
12
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
module MySQLNoIo
|
3
|
+
|
4
|
+
# A wrap represents a open/close block which always runs a before and an
|
5
|
+
# after statement.
|
6
|
+
#
|
7
|
+
# Passing a block to #execute will execute the block from between the
|
8
|
+
# statements.
|
9
|
+
#
|
10
|
+
# Example:
|
11
|
+
# class FooWrap
|
12
|
+
# def execute &block
|
13
|
+
# puts "Hi"
|
14
|
+
#
|
15
|
+
# yeild(block)
|
16
|
+
# ensure
|
17
|
+
# puts "Bye"
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# foo = FooWrap.new()
|
22
|
+
# foo.execute do
|
23
|
+
# puts "Ahh! Safety!"
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# Will output:
|
27
|
+
# Hi
|
28
|
+
# Ahh! Safety!
|
29
|
+
# Bye
|
30
|
+
#
|
31
|
+
class Wrap
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1,65 @@
|
|
1
|
+
|
2
|
+
module MySQLNoIo
|
3
|
+
# A WrapStack collects a series of Wraps, and runs their #execute commands
|
4
|
+
# inside one another.
|
5
|
+
#
|
6
|
+
# Example:
|
7
|
+
# stack = MySQLNoIo::WrapStack.new()a
|
8
|
+
#
|
9
|
+
# wrapFoo = Wrap::Foo.new()
|
10
|
+
# wrapBar = Wrap::Bar.new()
|
11
|
+
#
|
12
|
+
# stack.add_stack wrapFoo
|
13
|
+
# stack.add_stack wrapBar
|
14
|
+
# stack.execute do
|
15
|
+
# puts "hi"
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# Is identical to:
|
19
|
+
# wrapFoo.execute do
|
20
|
+
# wrapBar.execute do
|
21
|
+
# puts "hi"
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
class WrapStack
|
26
|
+
def initialize
|
27
|
+
@wraps = []
|
28
|
+
end
|
29
|
+
|
30
|
+
# Add a layer to wrap around the execution of the command
|
31
|
+
#
|
32
|
+
# @param [MySQLNoIo::Wrap] the wrapper to add to the stack
|
33
|
+
# @raise [MySQLNoIo::Errors::ArgumentError] if the wrapper is not sufficient
|
34
|
+
#
|
35
|
+
# @return [TrueClass]
|
36
|
+
def add_wrap wrap
|
37
|
+
unless wrap.respond_to?('execute')
|
38
|
+
raise MySQLNoIo::Errors::ArgumentError.new('Wrap must respond to #execute and accept a block.')
|
39
|
+
end
|
40
|
+
|
41
|
+
@wraps << wrap
|
42
|
+
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
# Execute your bit of code from within the safety and comfort of the
|
47
|
+
# wrappers appended to the stack.
|
48
|
+
def execute &block
|
49
|
+
# Brace yourself.
|
50
|
+
#
|
51
|
+
# This next bit of code creates a nested lamda like the WrapStack
|
52
|
+
# describes.
|
53
|
+
deep_proc = @wraps.reverse.inject(block) do |deep_proc, layer|
|
54
|
+
Proc.new do
|
55
|
+
layer.execute do
|
56
|
+
deep_proc.call
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
deep_proc.call
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module MySQLNoIo
|
2
|
+
module Wraps
|
3
|
+
# Just an example Wrap for testing and examples.
|
4
|
+
class Blocks
|
5
|
+
# The before block will be run prior to the execution.
|
6
|
+
def before &block
|
7
|
+
@prior = block
|
8
|
+
end
|
9
|
+
|
10
|
+
# The after block will be run post execution.
|
11
|
+
def after &block
|
12
|
+
@post = block
|
13
|
+
end
|
14
|
+
|
15
|
+
# Call the prior block, then execute, and then call the post-block.
|
16
|
+
def execute &block
|
17
|
+
@prior.call if @prior.respond_to?(:call)
|
18
|
+
block.call
|
19
|
+
ensure
|
20
|
+
@post.call if @post.respond_to?(:call)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module MySQLNoIo
|
2
|
+
module Wraps
|
3
|
+
# Stops the database slave entirely for your command
|
4
|
+
class DeactivatedSlave
|
5
|
+
def initialize mysql
|
6
|
+
@mysql = mysql
|
7
|
+
end
|
8
|
+
|
9
|
+
def execute &block
|
10
|
+
@mysql.query('STOP SLAVE;')
|
11
|
+
yield
|
12
|
+
ensure
|
13
|
+
@mysql.query('START SLAVE;')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module MySQLNoIo
|
2
|
+
module Wraps
|
3
|
+
# Allows you to run commands against a MySQL database, while MySQL's
|
4
|
+
# tables are locked, and the tables are flushed.
|
5
|
+
class GlobalLock
|
6
|
+
# Prepare to set up the GlobalLock wrapper, with the mysql2 connection
|
7
|
+
def initialize mysql
|
8
|
+
@mysql = mysql
|
9
|
+
end
|
10
|
+
|
11
|
+
# Lock the tables, run our command, and then unlock the tables.
|
12
|
+
def execute &block
|
13
|
+
@mysql.query("FLUSH TABLES WITH READ LOCK;")
|
14
|
+
yield
|
15
|
+
ensure
|
16
|
+
@mysql.query("UNLOCK TABLES;")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
data/lib/mysqlnoio.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
require 'mysql2'
|
3
|
+
|
4
|
+
require 'mysqlnoio/about'
|
5
|
+
|
6
|
+
require 'mysqlnoio/errors'
|
7
|
+
|
8
|
+
require 'mysqlnoio/wrap_stack'
|
9
|
+
require 'mysqlnoio/wrap'
|
10
|
+
require 'mysqlnoio/wraps/blocks'
|
11
|
+
require 'mysqlnoio/wraps/global_lock'
|
12
|
+
require 'mysqlnoio/wraps/deactivated_slave'
|
13
|
+
|
14
|
+
|
15
|
+
# See: README.md
|
16
|
+
module MySQLNoIo
|
17
|
+
|
18
|
+
end
|
19
|
+
|
data/mysqlnoio.gemspec
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
|
5
|
+
require 'mysqlnoio/about'
|
6
|
+
|
7
|
+
Gem::Specification.new do |gem|
|
8
|
+
gem.name = MySQLNoIo::NAME
|
9
|
+
gem.version = MySQLNoIo::VERSION
|
10
|
+
gem.description = MySQLNoIo::DESCRIPTION
|
11
|
+
gem.summary = 'Execute shell commands while MySQL IO is stopped.'
|
12
|
+
gem.homepage = 'https://zippykid.com'
|
13
|
+
gem.authors = ["ZippyKid", "Graham Christensen"]
|
14
|
+
gem.email = ["info@zippykid.com"]
|
15
|
+
gem.licenses = ["MIT"]
|
16
|
+
|
17
|
+
gem.files = `git ls-files`.split($/)
|
18
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
19
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
20
|
+
gem.require_paths = ["lib"]
|
21
|
+
|
22
|
+
gem.add_dependency('mysql2')
|
23
|
+
|
24
|
+
gem.add_development_dependency('rspec')
|
25
|
+
gem.add_development_dependency('debugger')
|
26
|
+
|
27
|
+
# Guard:
|
28
|
+
gem.add_development_dependency('guard')
|
29
|
+
gem.add_development_dependency('guard-rspec')
|
30
|
+
gem.add_development_dependency('guard-shell')
|
31
|
+
gem.add_development_dependency('rb-fsevent', '~> 0.9')
|
32
|
+
gem.add_development_dependency('rb-inotify', '~> 0.9')
|
33
|
+
gem.add_development_dependency('travis-lint')
|
34
|
+
|
35
|
+
# Docs
|
36
|
+
gem.add_development_dependency('yard')
|
37
|
+
gem.add_development_dependency('redcarpet')
|
38
|
+
end
|
39
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper.rb'
|
2
|
+
|
3
|
+
describe "mysql-noio", :integration => true do
|
4
|
+
context "called with no parameters" do
|
5
|
+
let (:output) { `bundle exec #{project_root}/bin/mysql-noio 2>&1` }
|
6
|
+
|
7
|
+
it "exits with a zero error code" do
|
8
|
+
$?.to_i.should eq(0)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "does not contain something that looks like a stack trace" do
|
12
|
+
output.should_not =~ /in `<main>'/
|
13
|
+
output.should_not =~ /syntax error/
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MySQLNoIo::WrapStack do
|
4
|
+
let(:stack) { MySQLNoIo::WrapStack.new }
|
5
|
+
describe "#add_wrap" do
|
6
|
+
|
7
|
+
context "An invalid wrap is provided" do
|
8
|
+
it "expects the method to have an #execute method" do
|
9
|
+
expect {
|
10
|
+
stack.add_wrap(nil)
|
11
|
+
}.to raise_error(MySQLNoIo::Errors::ArgumentError, /\#execute/)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context "A valid wrap is provided" do
|
16
|
+
let (:wrap) { double("MySQLNoIo::Wrap", execute: true) }
|
17
|
+
it "only requires the #execute method to be callable" do
|
18
|
+
stack.add_wrap(wrap).should eq(true)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#execute" do
|
24
|
+
let (:wrap_foo) do
|
25
|
+
wrap = MySQLNoIo::Wraps::Blocks.new
|
26
|
+
wrap.before do
|
27
|
+
@output << "foo-before\n"
|
28
|
+
end
|
29
|
+
wrap.after do
|
30
|
+
@output << "foo-after\n"
|
31
|
+
end
|
32
|
+
|
33
|
+
wrap
|
34
|
+
end
|
35
|
+
|
36
|
+
let (:wrap_bar) do
|
37
|
+
wrap = MySQLNoIo::Wraps::Blocks.new
|
38
|
+
wrap.before do
|
39
|
+
@output << "bar-before\n"
|
40
|
+
end
|
41
|
+
wrap.after do
|
42
|
+
@output << "bar-after\n"
|
43
|
+
end
|
44
|
+
|
45
|
+
wrap
|
46
|
+
end
|
47
|
+
|
48
|
+
it "Calls the wrappers in order, and then my bits." do
|
49
|
+
@output = ""
|
50
|
+
stack.add_wrap wrap_foo
|
51
|
+
stack.add_wrap wrap_bar
|
52
|
+
stack.execute do
|
53
|
+
@output << "Cheesy filling!\n"
|
54
|
+
end
|
55
|
+
|
56
|
+
desired_output = "foo-before\n"
|
57
|
+
desired_output << "bar-before\n"
|
58
|
+
desired_output << "Cheesy filling!\n"
|
59
|
+
desired_output << "bar-after\n"
|
60
|
+
desired_output << "foo-after\n"
|
61
|
+
|
62
|
+
@output.should eq(desired_output)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
|
2
|
+
describe MySQLNoIo::Wraps::Blocks do
|
3
|
+
subject { MySQLNoIo::Wraps::Blocks.new() }
|
4
|
+
context "accepts a before block" do
|
5
|
+
it { should respond_to :before }
|
6
|
+
end
|
7
|
+
|
8
|
+
context "accepts an after block" do
|
9
|
+
it { should respond_to :after }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#execute" do
|
13
|
+
context "executing a block" do
|
14
|
+
let (:wrapper) { MySQLNoIo::Wraps::Blocks.new() }
|
15
|
+
let (:block_before) { Proc.new do @output << "chocolate" end }
|
16
|
+
let (:block_execute) { Proc.new do @output << "icing" end }
|
17
|
+
let (:block_after) { Proc.new do @output << "vanilla" end }
|
18
|
+
|
19
|
+
it "executes the block passed to #execute" do
|
20
|
+
@output = ""
|
21
|
+
wrapper.execute do block_execute.call end
|
22
|
+
|
23
|
+
@output.should eq("icing")
|
24
|
+
end
|
25
|
+
|
26
|
+
it "executes the before block ... before" do
|
27
|
+
@output = ""
|
28
|
+
wrapper.before do block_before.call end
|
29
|
+
wrapper.execute do block_execute.call end
|
30
|
+
|
31
|
+
@output.should eq("chocolateicing")
|
32
|
+
end
|
33
|
+
|
34
|
+
it "executes the after block ... after" do
|
35
|
+
@output = ""
|
36
|
+
wrapper.after do block_after.call end
|
37
|
+
wrapper.execute do block_execute.call end
|
38
|
+
|
39
|
+
@output.should eq("icingvanilla")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
describe MySQLNoIo::Wraps::DeactivatedSlave do
|
2
|
+
describe "#execute" do
|
3
|
+
it "Runs STOP SLAVE and START SLAVE around our command" do
|
4
|
+
@cmds = ""
|
5
|
+
|
6
|
+
mysql = double("MySQL2::Client")
|
7
|
+
mysql.should_receive(:query).exactly(2).times do |arg|
|
8
|
+
@cmds << "#{arg}\n"
|
9
|
+
end
|
10
|
+
|
11
|
+
wrap = MySQLNoIo::Wraps::DeactivatedSlave.new mysql
|
12
|
+
wrap.execute do
|
13
|
+
@cmds << "-- my command\n"
|
14
|
+
end
|
15
|
+
|
16
|
+
@cmds.should eq(<<-FOO
|
17
|
+
STOP SLAVE;
|
18
|
+
-- my command
|
19
|
+
START SLAVE;
|
20
|
+
FOO
|
21
|
+
)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
describe MySQLNoIo::Wraps::GlobalLock do
|
2
|
+
describe "#execute" do
|
3
|
+
it "Runs lock and unlock around our command" do
|
4
|
+
@cmds = ""
|
5
|
+
|
6
|
+
mysql = double("MySQL2::Client")
|
7
|
+
mysql.should_receive(:query).exactly(2).times do |arg|
|
8
|
+
@cmds << "#{arg}\n"
|
9
|
+
end
|
10
|
+
|
11
|
+
wrap = MySQLNoIo::Wraps::GlobalLock.new mysql
|
12
|
+
wrap.execute do
|
13
|
+
@cmds << "-- my command\n"
|
14
|
+
end
|
15
|
+
|
16
|
+
@cmds.should eq(<<-FOO
|
17
|
+
FLUSH TABLES WITH READ LOCK;
|
18
|
+
-- my command
|
19
|
+
UNLOCK TABLES;
|
20
|
+
FOO
|
21
|
+
)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
apt-get update
|
4
|
+
apt-get --yes install libmysqlclient-dev mysql-server-5.5
|
5
|
+
|
6
|
+
curl -L https://get.rvm.io | bash -s stable --autolibs=3 --ruby
|
7
|
+
source /usr/local/rvm/scripts/rvm
|
8
|
+
rvm in /vagrant do bundle install
|
9
|
+
|
10
|
+
cd /vagrant
|
11
|
+
|
12
|
+
rake
|
13
|
+
|