ridgepole 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b7a10d9b0607e25c59ff80c62aad7a6994d3b84d
4
+ data.tar.gz: 56933fbf7941579d0e83d56a10a8703a555baff6
5
+ SHA512:
6
+ metadata.gz: f353e4f59e6188b7851eb14a90ee7ece7484f994f6a80258c1453e1ef0aeb74edf11d5257a71d4330aa8cebc98c5cf946f5238f3b803010deedefcdf44f76ffd
7
+ data.tar.gz: 70a90fa4e5a3acb0b23746871f6bec0a4adcffbe4b7d50891264f9aaf9657c0eccc23dc0868753e506a44805559037c4f7db560bd3be46ef14abaca336e8039a
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .DS_Store
19
+ test.rb
20
+ Schemafile
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ridgepole.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Genki Sugawara
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # Ridgepole
2
+
3
+ Ridgepole is a tool to DB schema.
4
+
5
+ It defines DB schema using [Rails DSL](http://guides.rubyonrails.org/migrations.html#types-of-schema-dumps), and updates DB schema according to DSL.
6
+ (like Chef/Puppet)
7
+
8
+ [![Gem Version](https://badge.fury.io/rb/ridgepole.png)](http://badge.fury.io/rb/ridgepole)
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ gem 'ridgepole'
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install ridgepole
23
+
24
+ ## Usage
25
+
26
+ ```sh
27
+ ridgepole --export -o Schemafile
28
+ vi Schemafile
29
+ ridgepole --apply --dry-run
30
+ ridgepole --apply
31
+ ```
32
+
33
+ ## Demo
34
+
35
+ * [asciinema.org/a/9349](https://asciinema.org/a/9349)
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/ridgepole ADDED
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env ruby
2
+ $: << File.expand_path('../../lib', __FILE__)
3
+ require 'rubygems'
4
+ require 'yaml'
5
+ require 'optparse'
6
+ require 'ridgepole'
7
+
8
+ Version = Ridgepole::VERSION
9
+ DEFAULT_FILENAME = 'Schemafile'
10
+
11
+ config = nil
12
+ mode = nil
13
+ file = DEFAULT_FILENAME
14
+ output_file = '-'
15
+
16
+ options = {
17
+ :dry_run => false,
18
+ :debug => false,
19
+ }
20
+
21
+ ARGV.options do |opt|
22
+ begin
23
+ opt.on('-c', '--config CONF_OR_FILE') {|v| config = v }
24
+ opt.on('-a', '--apply') { mode = :apply }
25
+ opt.on('-f', '--file FILE') {|v| file = v }
26
+ opt.on('', '--dry-run') { options[:dry_run] = true }
27
+ opt.on('-e', '--export') { mode = :export }
28
+ opt.on('-o', '--output FILE') {|v| output_file = v }
29
+ opt.on('' , '--debug') { options[:debug] = true }
30
+ opt.parse!
31
+
32
+ unless config and mode
33
+ puts opt.help
34
+ exit 1
35
+ end
36
+ rescue => e
37
+ $stderr.puts("[ERROR] #{e.message}")
38
+ exit 1
39
+ end
40
+ end
41
+
42
+ begin
43
+ logger = Ridgepole::Logger.instance
44
+ logger.set_debug(options[:debug])
45
+
46
+ config = open(config) {|f| f.read } if File.exist?(config)
47
+ config = YAML.load(config)
48
+ client = Ridgepole::Client.new(config, options)
49
+
50
+ case mode
51
+ when :export
52
+ if output_file == '-'
53
+ logger.info('# Export Schema')
54
+ puts client.dump
55
+ else
56
+ logger.info("Export Schema to `#{output_file}`")
57
+ open(output_file, 'wb') {|f| f.puts client.dump }
58
+ end
59
+ when :apply
60
+ unless File.exist?(file)
61
+ raise "No Schemafile found (looking for: #{file})"
62
+ end
63
+
64
+ msg = "Apply `#{file}`"
65
+ msg << ' (dry-run)' if options[:dry_run]
66
+ logger.info(msg)
67
+
68
+ dsl = open(file) {|f| f.read }
69
+ delta = client.diff(dsl)
70
+
71
+ if options[:dry_run]
72
+ puts delta.script if delta.differ?
73
+ else
74
+ delta.migrate
75
+ end
76
+
77
+ unless delta.differ?
78
+ logger.info('No change')
79
+ end
80
+ end
81
+ rescue => e
82
+ if options[:debug]
83
+ raise e
84
+ else
85
+ $stderr.puts("[ERROR] #{e.message}")
86
+ exit 1
87
+ end
88
+ end
data/lib/ridgepole.rb ADDED
@@ -0,0 +1,15 @@
1
+ require 'logger'
2
+ require 'singleton'
3
+ require 'stringio'
4
+
5
+ require 'active_record'
6
+
7
+ module Ridgepole; end
8
+ require 'ridgepole/client'
9
+ require 'ridgepole/delta'
10
+ require 'ridgepole/diff'
11
+ require 'ridgepole/dsl_parser'
12
+ require 'ridgepole/dumper'
13
+ require 'ridgepole/logger'
14
+ require 'ridgepole/string_ext'
15
+ require 'ridgepole/version'
@@ -0,0 +1,20 @@
1
+ class Ridgepole::Client
2
+ def initialize(conn_spec, options = {})
3
+ @options = options
4
+ ActiveRecord::Base.establish_connection(conn_spec)
5
+
6
+ @dumper = Ridgepole::Dumper.new(@options)
7
+ @parser = Ridgepole::DSLParser.new(@options)
8
+ @diff = Ridgepole::Diff.new(@options)
9
+ end
10
+
11
+ def dump
12
+ @dumper.dump
13
+ end
14
+
15
+ def diff(dsl)
16
+ expected_definition = @parser.parse(dsl)
17
+ current_definition = @parser.parse(@dumper.dump)
18
+ @diff.diff(current_definition, expected_definition)
19
+ end
20
+ end
@@ -0,0 +1,166 @@
1
+ class Ridgepole::Delta
2
+ def initialize(delta, options = {})
3
+ @delta = delta
4
+ @options = options
5
+ end
6
+
7
+ def migrate
8
+ ActiveRecord::Schema.new.instance_eval(script)
9
+ end
10
+
11
+ def script
12
+ buf = StringIO.new
13
+
14
+ (@delta[:add] || {}).each do |table_name, attrs|
15
+ append_create_table(table_name, attrs, buf)
16
+ end
17
+
18
+ (@delta[:rename] || {}).each do |table_name, attrs|
19
+ append_rename_table(table_name, attrs, buf)
20
+ end
21
+
22
+ (@delta[:change] || {}).each do |table_name, attrs|
23
+ append_change(table_name, attrs, buf)
24
+ end
25
+
26
+ (@delta[:delete] || {}).each do |table_name, attrs|
27
+ append_drop_table(table_name, attrs, buf)
28
+ end
29
+
30
+ buf.string.strip
31
+ end
32
+
33
+ def differ?
34
+ not script.empty?
35
+ end
36
+
37
+ private
38
+
39
+ def append_create_table(table_name, attrs, buf)
40
+ options = attrs[:options] || {}
41
+ definition = attrs[:definition] || {}
42
+ indices = attrs[:indices] || {}
43
+
44
+ buf.puts(<<-EOS)
45
+ create_table(#{table_name.inspect}, #{options.inspect}) do |t|
46
+ EOS
47
+
48
+ definition.each do |column_name, column_attrs|
49
+ column_type = column_attrs.fetch(:type)
50
+ column_options = column_attrs[:options] || {}
51
+
52
+ buf.puts(<<-EOS)
53
+ t.#{column_type}(#{column_name.inspect}, #{column_options.inspect})
54
+ EOS
55
+ end
56
+
57
+ buf.puts(<<-EOS)
58
+ end
59
+ EOS
60
+
61
+ indices.each do |index_name, index_attrs|
62
+ append_add_index(table_name, index_name, index_attrs, buf)
63
+ end
64
+
65
+ buf.puts
66
+ end
67
+
68
+ def append_rename_table(to_table_name, from_table_name, buf)
69
+ buf.puts(<<-EOS)
70
+ rename_table(#{from_table_name.inspect}, #{to_table_name.inspect})
71
+ EOS
72
+
73
+ buf.puts
74
+ end
75
+
76
+ def append_drop_table(table_name, attrs, buf)
77
+ buf.puts(<<-EOS)
78
+ drop_table(#{table_name.inspect})
79
+ EOS
80
+
81
+ buf.puts
82
+ end
83
+
84
+ def append_change(table_name, attrs, buf)
85
+ append_change_definition(table_name, attrs[:definition] || {}, buf)
86
+ append_change_indices(table_name, attrs[:indices] || {}, buf)
87
+ buf.puts
88
+ end
89
+
90
+ def append_change_definition(table_name, delta, buf)
91
+ (delta[:add] || {}).each do |column_name, attrs|
92
+ append_add_column(table_name, column_name, attrs, buf)
93
+ end
94
+
95
+ (delta[:rename] || {}).each do |column_name, attrs|
96
+ append_rename_column(table_name, column_name, attrs, buf)
97
+ end
98
+
99
+ (delta[:change] || {}).each do |column_name, attrs|
100
+ append_change_column(table_name, column_name, attrs, buf)
101
+ end
102
+
103
+ (delta[:delete] || {}).each do |column_name, attrs|
104
+ append_remove_column(table_name, column_name, attrs, buf)
105
+ end
106
+ end
107
+
108
+ def append_add_column(table_name, column_name, attrs, buf)
109
+ type = attrs.fetch(:type)
110
+ options = attrs[:options] || {}
111
+
112
+ buf.puts(<<-EOS)
113
+ add_column(#{table_name.inspect}, #{column_name.inspect}, #{type.inspect}, #{options.inspect})
114
+ EOS
115
+ end
116
+
117
+ def append_rename_column(table_name, to_column_name, from_column_name, buf)
118
+ buf.puts(<<-EOS)
119
+ rename_column(#{table_name.inspect}, #{from_column_name.inspect}, #{to_column_name.inspect})
120
+ EOS
121
+ end
122
+
123
+ def append_change_column(table_name, column_name, attrs, buf)
124
+ type = attrs.fetch(:type)
125
+ options = attrs[:options] || {}
126
+
127
+ buf.puts(<<-EOS)
128
+ change_column(#{table_name.inspect}, #{column_name.inspect}, #{type.inspect}, #{options.inspect})
129
+ EOS
130
+ end
131
+
132
+ def append_remove_column(table_name, column_name, attrs, buf)
133
+ buf.puts(<<-EOS)
134
+ remove_column(#{table_name.inspect}, #{column_name.inspect})
135
+ EOS
136
+ end
137
+
138
+ def append_change_indices(table_name, delta, buf)
139
+ (delta[:add] || {}).each do |index_name, attrs|
140
+ append_add_index(table_name, index_name, attrs, buf)
141
+ end
142
+
143
+ (delta[:delete] || {}).each do |index_name, attrs|
144
+ append_remove_index(table_name, index_name, attrs, buf)
145
+ end
146
+ end
147
+
148
+ def append_add_index(table_name, index_name, attrs, buf)
149
+ column_name = attrs.fetch(:column_name)
150
+ options = attrs[:options] || {}
151
+
152
+ buf.puts(<<-EOS)
153
+ add_index(#{table_name.inspect}, #{column_name.inspect}, #{options.inspect})
154
+ EOS
155
+ end
156
+
157
+ def append_remove_index(table_name, index_name, attrs, buf)
158
+ column_name = attrs.fetch(:column_name)
159
+ options = attrs[:options] || {}
160
+ target = options[:name] ? {:name => options[:name]} : column_name
161
+
162
+ buf.puts(<<-EOS)
163
+ remove_index(#{table_name.inspect}, #{target.inspect})
164
+ EOS
165
+ end
166
+ end
@@ -0,0 +1,136 @@
1
+ class Ridgepole::Diff
2
+ def initialize(options = {})
3
+ @options = options
4
+ end
5
+
6
+ def diff(from, to)
7
+ from = (from || {}).dup
8
+ to = (to || {}).dup
9
+ delta = {}
10
+
11
+ to.dup.each do |table_name, to_attrs|
12
+ if (from_table_name = (to_attrs[:options] || {}).delete(:from))
13
+ next unless from.has_key?(from_table_name)
14
+ delta[:rename] ||= {}
15
+ delta[:rename][table_name] = from_table_name
16
+ from.delete(from_table_name)
17
+ to.delete(table_name)
18
+ end
19
+ end
20
+
21
+ to.each do |table_name, to_attrs|
22
+ if (from_attrs = from.delete(table_name))
23
+ scan_change(table_name, from_attrs, to_attrs, delta)
24
+ else
25
+ delta[:add] ||= {}
26
+ delta[:add][table_name] = to_attrs
27
+ end
28
+ end
29
+
30
+ from.each do |table_name, from_attrs|
31
+ delta[:delete] ||= {}
32
+ delta[:delete][table_name] = from_attrs
33
+ end
34
+
35
+ Ridgepole::Delta.new(delta, @options)
36
+ end
37
+
38
+ private
39
+
40
+ def scan_change(table_name, from, to, delta)
41
+ from = (from || {}).dup
42
+ to = (to || {}).dup
43
+ table_delta = {}
44
+
45
+ scan_options_change(from[:options], to[:options], table_delta)
46
+ scan_definition_change(from[:definition], to[:definition], table_delta)
47
+ scan_indices_change(from[:indices], to[:indices], table_delta)
48
+
49
+ unless table_delta.empty?
50
+ delta[:change] ||= {}
51
+ delta[:change][table_name] = table_delta
52
+ end
53
+ end
54
+
55
+ def scan_options_change(from, to, table_delta)
56
+ # XXX: Warn differences of options
57
+ end
58
+
59
+ def scan_definition_change(from, to, table_delta)
60
+ from = (from || {}).dup
61
+ to = (to || {}).dup
62
+ definition_delta = {}
63
+
64
+ to.dup.each do |column_name, to_attrs|
65
+ if (from_column_name = (to_attrs[:options] || {}).delete(:from))
66
+ next unless from.has_key?(from_column_name)
67
+ definition_delta[:rename] ||= {}
68
+ definition_delta[:rename][column_name] = from_column_name
69
+ from.delete(from_column_name)
70
+ to.delete(column_name)
71
+ end
72
+ end
73
+
74
+ priv_column_name = nil
75
+
76
+ to.each do |column_name, to_attrs|
77
+ if (from_attrs = from.delete(column_name))
78
+ if from_attrs != to_attrs
79
+ definition_delta[:change] ||= {}
80
+ definition_delta[:change][column_name] = to_attrs
81
+ end
82
+ else
83
+ definition_delta[:add] ||= {}
84
+ to_attrs[:options] ||= {}
85
+
86
+ if priv_column_name
87
+ to_attrs[:options][:after] = priv_column_name
88
+ else
89
+ to_attrs[:options][:first] = true
90
+ end
91
+
92
+ definition_delta[:add][column_name] = to_attrs
93
+ end
94
+
95
+ priv_column_name = column_name
96
+ end
97
+
98
+ from.each do |column_name, from_attrs|
99
+ definition_delta[:delete] ||= {}
100
+ definition_delta[:delete][column_name] = from_attrs
101
+ end
102
+
103
+ unless definition_delta.empty?
104
+ table_delta[:definition] = definition_delta
105
+ end
106
+ end
107
+
108
+ def scan_indices_change(from, to, table_delta)
109
+ from = (from || {}).dup
110
+ to = (to || {}).dup
111
+ indices_delta = {}
112
+
113
+ to.each do |index_name, to_attrs|
114
+ if (from_attrs = from.delete(index_name))
115
+ if from_attrs != to_attrs
116
+ indices_delta[:add] ||= {}
117
+ indices_delta[:delete] ||= {}
118
+ indices_delta[:add][index_name] = to_attrs
119
+ indices_delta[:delete][index_name] = from_attrs
120
+ end
121
+ else
122
+ indices_delta[:add] ||= {}
123
+ indices_delta[:add][index_name] = to_attrs
124
+ end
125
+ end
126
+
127
+ from.each do |index_name, from_attrs|
128
+ indices_delta[:delete] ||= {}
129
+ indices_delta[:delete][index_name] = from_attrs
130
+ end
131
+
132
+ unless indices_delta.empty?
133
+ table_delta[:indices] = indices_delta
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,81 @@
1
+ class Ridgepole::DSLParser
2
+ class Context
3
+ class TableDefinition
4
+ attr_reader :__definition
5
+
6
+ def initialize
7
+ @__definition = {}
8
+ end
9
+
10
+ def column(name, type, options = {})
11
+ @__definition[name] = {
12
+ :type => type,
13
+ :options => options,
14
+ }
15
+ end
16
+
17
+ TYPES = [
18
+ :string,
19
+ :text,
20
+ :integer,
21
+ :float,
22
+ :decimal,
23
+ :datetime,
24
+ :timestamp,
25
+ :time,
26
+ :date,
27
+ :binary,
28
+ :boolean
29
+ ]
30
+
31
+ TYPES.each do |column_type|
32
+ define_method column_type do |*args|
33
+ options = args.extract_options!
34
+ column_names = args
35
+ column_names.each {|name| column(name, column_type, options) }
36
+ end
37
+ end
38
+ end
39
+
40
+ attr_reader :__definition
41
+
42
+ def initialize
43
+ @__definition = {}
44
+ end
45
+
46
+ def self.eval(dsl)
47
+ ctx = self.new
48
+ ctx.instance_eval(dsl)
49
+ ctx.__definition
50
+ end
51
+
52
+ def create_table(table_name, options = {})
53
+ # XXX: Add exist check
54
+ table_definition = TableDefinition.new
55
+ yield(table_definition)
56
+ @__definition[table_name] ||= {}
57
+ @__definition[table_name][:definition] = table_definition.__definition
58
+ options.delete(:force)
59
+ @__definition[table_name][:options] = options
60
+ end
61
+
62
+ def add_index(table_name, column_name, options = {})
63
+ # XXX: Add exist check
64
+ @__definition[table_name] ||= {}
65
+ @__definition[table_name][:indices] ||= {}
66
+ idx = options[:name] || column_name
67
+ @__definition[table_name][:indices][idx] = {
68
+ :column_name => column_name,
69
+ :options => options,
70
+ }
71
+ end
72
+ end
73
+
74
+ def initialize(options = {})
75
+ @options = options
76
+ end
77
+
78
+ def parse(dsl)
79
+ Context.eval(dsl)
80
+ end
81
+ end
@@ -0,0 +1,16 @@
1
+ class Ridgepole::Dumper
2
+ def initialize(options = {})
3
+ @options = options
4
+ end
5
+
6
+ def dump
7
+ stream = StringIO.new
8
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
9
+
10
+ stream.string.lines.select {|line|
11
+ line !~ /\A#/ &&
12
+ line !~ /\AActiveRecord::Schema\.define/ &&
13
+ line !~ /\Aend/
14
+ }.join.undent.strip
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ class Ridgepole::Logger < ::Logger
2
+ include Singleton
3
+
4
+ def initialize
5
+ super($stdout)
6
+
7
+ self.formatter = proc do |severity, datetime, progname, msg|
8
+ "#{msg}\n"
9
+ end
10
+
11
+ self.level = Logger::INFO
12
+ end
13
+
14
+ def set_debug(value)
15
+ self.level = value ? Logger::DEBUG : Logger::INFO
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ class String
2
+ def undent
3
+ min_space_num = self.split("\n").delete_if {|s| s =~ /^\s*$/ }.map {|s| (s[/^\s+/] || '').length }.min
4
+
5
+ if min_space_num and min_space_num > 0
6
+ gsub(/^[ \t]{,#{min_space_num}}/, '')
7
+ else
8
+ self
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module Ridgepole
2
+ VERSION = '0.0.1'
3
+ end
data/ridgepole.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ridgepole/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'ridgepole'
8
+ spec.version = Ridgepole::VERSION
9
+ spec.authors = ['Genki Sugawara']
10
+ spec.email = ['sugawara@cookpad.com']
11
+ spec.summary = %q{Ridgepole is a tool to DB schema.}
12
+ spec.description = %q{Ridgepole is a tool to DB schema. It defines DB schema using Rails DSL, and updates DB schema according to DSL.}
13
+ spec.homepage = 'https://bitbucket.org/winebarrel/ridgepole'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_dependency 'activerecord'
22
+ spec.add_development_dependency 'bundler'
23
+ spec.add_development_dependency 'rake'
24
+ spec.add_development_dependency 'rspec', '>= 2.14.1'
25
+ spec.add_development_dependency 'mysql2'
26
+ end
metadata ADDED
@@ -0,0 +1,132 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ridgepole
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Genki Sugawara
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-05-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 2.14.1
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: 2.14.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: mysql2
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Ridgepole is a tool to DB schema. It defines DB schema using Rails DSL,
84
+ and updates DB schema according to DSL.
85
+ email:
86
+ - sugawara@cookpad.com
87
+ executables:
88
+ - ridgepole
89
+ extensions: []
90
+ extra_rdoc_files: []
91
+ files:
92
+ - .gitignore
93
+ - Gemfile
94
+ - LICENSE.txt
95
+ - README.md
96
+ - Rakefile
97
+ - bin/ridgepole
98
+ - lib/ridgepole.rb
99
+ - lib/ridgepole/client.rb
100
+ - lib/ridgepole/delta.rb
101
+ - lib/ridgepole/diff.rb
102
+ - lib/ridgepole/dsl_parser.rb
103
+ - lib/ridgepole/dumper.rb
104
+ - lib/ridgepole/logger.rb
105
+ - lib/ridgepole/string_ext.rb
106
+ - lib/ridgepole/version.rb
107
+ - ridgepole.gemspec
108
+ homepage: https://bitbucket.org/winebarrel/ridgepole
109
+ licenses:
110
+ - MIT
111
+ metadata: {}
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - '>='
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubyforge_project:
128
+ rubygems_version: 2.0.14
129
+ signing_key:
130
+ specification_version: 4
131
+ summary: Ridgepole is a tool to DB schema.
132
+ test_files: []