pg_migrate 0.1.11 → 0.1.12
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 +4 -4
- data/.gitignore +34 -34
- data/.gitmodules +3 -3
- data/Gemfile +9 -9
- data/Gemfile.lock +39 -39
- data/LICENSE +21 -21
- data/README.md +33 -33
- data/Rakefile +2 -2
- data/bin/pg_migrate +6 -6
- data/lib/pg_migrate/builder.rb +214 -214
- data/lib/pg_migrate/command_line.rb +242 -242
- data/lib/pg_migrate/config_parser.rb +48 -48
- data/lib/pg_migrate/manifest_reader.rb +102 -102
- data/lib/pg_migrate/migration.rb +11 -11
- data/lib/pg_migrate/migrator.rb +94 -94
- data/lib/pg_migrate/package.rb +152 -152
- data/lib/pg_migrate/package_templates/Gemfile.erb +3 -3
- data/lib/pg_migrate/package_templates/bin/migrate.rb +9 -9
- data/lib/pg_migrate/package_templates/gemspec.erb +21 -21
- data/lib/pg_migrate/package_templates/lib/gem/version.rb +3 -3
- data/lib/pg_migrate/package_templates/lib/gem.rb +12 -12
- data/lib/pg_migrate/props.rb +19 -19
- data/lib/pg_migrate/sql_reader.rb +51 -51
- data/lib/pg_migrate/templates/bootstrap.erb +175 -175
- data/lib/pg_migrate/templates/up.erb +30 -30
- data/lib/pg_migrate/util.rb +73 -73
- data/lib/pg_migrate/version.rb +3 -3
- data/lib/pg_migrate.rb +40 -40
- data/pg_migrate.gemspec +29 -29
- data/spec/database.yml +8 -8
- data/spec/pg_migrate/builder_spec.rb +113 -113
- data/spec/pg_migrate/command_line_spec.rb +53 -53
- data/spec/pg_migrate/config_parser_spec.rb +18 -18
- data/spec/pg_migrate/db_utility.rb +73 -73
- data/spec/pg_migrate/input_manifests/single_manifest/manifest +3 -3
- data/spec/pg_migrate/input_manifests/single_manifest/up/single1.sql +29 -29
- data/spec/pg_migrate/manifest_reader_spec.rb +19 -19
- data/spec/pg_migrate/migrator_spec.rb +68 -68
- data/spec/pg_migrate/package_spec.rb +38 -38
- data/spec/pg_migrate/sql_reader_spec.rb +21 -21
- data/spec/spec_helper.rb +15 -15
- metadata +5 -5
data/lib/pg_migrate/builder.rb
CHANGED
@@ -1,214 +1,214 @@
|
|
1
|
-
require 'pathname'
|
2
|
-
require 'fileutils'
|
3
|
-
require 'find'
|
4
|
-
require 'erb'
|
5
|
-
|
6
|
-
|
7
|
-
module PgMigrate
|
8
|
-
# takes a unprocessed manifest directory, and adds before/after headers to each file
|
9
|
-
class Builder
|
10
|
-
|
11
|
-
attr_accessor :manifest_reader, :sql_reader, :loaded_manifest
|
12
|
-
|
13
|
-
def initialize(manifest_reader, sql_reader)
|
14
|
-
@log = Logging.logger[self]
|
15
|
-
@manifest_reader = manifest_reader
|
16
|
-
@sql_reader = sql_reader
|
17
|
-
@template_dir = File.join(File.dirname(__FILE__), 'templates')
|
18
|
-
end
|
19
|
-
|
20
|
-
|
21
|
-
# input_dir is root path, contains file 'manifest' and 'migrations'
|
22
|
-
# output_dir will have a manifest and migrations folder, but processed
|
23
|
-
# force will create the output dir if needed, and *delete an existing directory* if it's in the way
|
24
|
-
# test will run tests
|
25
|
-
def build(input_dir, output_dir, options={:force=>true, :test=>false})
|
26
|
-
input_dir = File.expand_path(input_dir)
|
27
|
-
output_dir = File.expand_path(output_dir)
|
28
|
-
|
29
|
-
if input_dir == output_dir
|
30
|
-
raise 'input_dir can not be same as output_dir: #{input_dir}'
|
31
|
-
end
|
32
|
-
|
33
|
-
@log.debug "building migration directory #{input_dir} and placing result at: #{output_dir}"
|
34
|
-
|
35
|
-
output = Pathname.new(output_dir)
|
36
|
-
if !output.exist?
|
37
|
-
if !options[:force]
|
38
|
-
raise "Output directory '#{output_dir}' does not exist. Create it or specify force=true"
|
39
|
-
else
|
40
|
-
output.mkpath
|
41
|
-
end
|
42
|
-
else
|
43
|
-
# verify that it's is a directory
|
44
|
-
if !output.directory?
|
45
|
-
raise "output_dir #{output_dir} is a file; not a directory."
|
46
|
-
else
|
47
|
-
@log.debug("deleting & recreating existing output_dir #{output_dir}")
|
48
|
-
output.rmtree
|
49
|
-
output.mkpath
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
# manifest always goes over mostly as-is,
|
54
|
-
# just with a comment added at top indicating our version
|
55
|
-
|
56
|
-
input_manifest = File.join(input_dir, MANIFEST_FILENAME)
|
57
|
-
output_manifest = File.join(output_dir, MANIFEST_FILENAME)
|
58
|
-
|
59
|
-
File.open(output_manifest, 'w') do |fout|
|
60
|
-
fout.puts "#{BUILDER_VERSION_HEADER}pg_migrate_ruby-#{PgMigrate::VERSION}"
|
61
|
-
IO.readlines(input_manifest).each do |input|
|
62
|
-
fout.puts input
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
# if .pg_migrate file exists, copy it
|
67
|
-
input_pg_config = File.join(input_dir, PG_CONFIG)
|
68
|
-
if FileTest::exist? input_pg_config
|
69
|
-
output_pg_config = File.join(output_dir, PG_CONFIG)
|
70
|
-
|
71
|
-
File.open(output_pg_config, 'w') do |fout|
|
72
|
-
IO.readlines(input_pg_config).each do |input|
|
73
|
-
fout.puts input
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
# in order array of manifest declarations
|
79
|
-
@loaded_manifest = @manifest_reader.load_input_manifest(input_dir)
|
80
|
-
# hashed on migration name hash of manifest
|
81
|
-
|
82
|
-
loaded_manifest_hash = @manifest_reader.hash_loaded_manifest(loaded_manifest)
|
83
|
-
@manifest_reader.validate_migration_paths(input_dir, loaded_manifest)
|
84
|
-
|
85
|
-
build_up(input_dir, output_dir, loaded_manifest_hash, loaded_manifest)
|
86
|
-
|
87
|
-
# ok we are done. time to test!
|
88
|
-
if options[:test]
|
89
|
-
test(output_dir, options)
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
def build_up(input_dir, output_dir, loaded_manifest_hash, loaded_manifest)
|
94
|
-
migrations_input = File.join(input_dir, UP_DIRNAME)
|
95
|
-
migrations_output = File.join(output_dir, UP_DIRNAME)
|
96
|
-
|
97
|
-
if(!FileTest::exist? migrations_input)
|
98
|
-
raise "'up' directory must exist at #{migrations_input}"
|
99
|
-
end
|
100
|
-
|
101
|
-
# iterate through files in input migrations path, wrapping files with transactions and other required bits
|
102
|
-
|
103
|
-
Find.find(migrations_input) do |path|
|
104
|
-
if path == ".."
|
105
|
-
Find.prune
|
106
|
-
else
|
107
|
-
@log.debug "building #{path}"
|
108
|
-
|
109
|
-
# create relative bit
|
110
|
-
relative_path = path[migrations_input.length..-1]
|
111
|
-
|
112
|
-
# create the filename correct for the input directory, for this file
|
113
|
-
migration_in_path = path
|
114
|
-
|
115
|
-
# create the filename correct for the output directory, for this file
|
116
|
-
migration_out_path = File.join(migrations_output, relative_path)
|
117
|
-
|
118
|
-
process_and_copy_up(migration_in_path, migration_out_path, relative_path, loaded_manifest_hash, loaded_manifest)
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
create_bootstrap_script(migrations_output)
|
123
|
-
end
|
124
|
-
|
125
|
-
# creates the 'pg_migrations table'
|
126
|
-
def create_bootstrap_script(migration_out_path)
|
127
|
-
@log.debug "creating bootstrap script #{migration_out_path}"
|
128
|
-
run_template("bootstrap.erb", binding, File.join(migration_out_path, BOOTSTRAP_FILENAME))
|
129
|
-
end
|
130
|
-
|
131
|
-
def create_wrapped_up_migration(migration_in_filepath, migration_out_filepath, migration_def, loaded_manifest)
|
132
|
-
@log.debug "securing migration #{migration_def.name}"
|
133
|
-
|
134
|
-
builder_version="pg_migrate_ruby-#{PgMigrate::VERSION}"
|
135
|
-
manifest_version=loaded_manifest[-1].ordinal
|
136
|
-
migration_content = nil
|
137
|
-
File.open(migration_in_filepath, 'r') { |reader| migration_content = reader.read }
|
138
|
-
run_template("up.erb", binding, File.join(migration_out_filepath))
|
139
|
-
end
|
140
|
-
|
141
|
-
# given an input template and binding, writes to an output file
|
142
|
-
def run_template(template, binding, output_filepath)
|
143
|
-
bootstrap_template = nil
|
144
|
-
File.open(File.join(@template_dir, template), 'r') do |reader|
|
145
|
-
bootstrap_template = reader.read
|
146
|
-
end
|
147
|
-
|
148
|
-
|
149
|
-
template = ERB.new(bootstrap_template, 0, "%<>")
|
150
|
-
content = template.result(binding)
|
151
|
-
File.open(output_filepath, 'w') do |writer|
|
152
|
-
writer.syswrite(content)
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
def process_and_copy_up(migration_in_path, migration_out_path, relative_path, loaded_manifest_hash, loaded_manifest)
|
157
|
-
|
158
|
-
if FileTest.directory?(migration_in_path)
|
159
|
-
# copy over directories
|
160
|
-
# find relative-to-migrations dir this path
|
161
|
-
FileUtils.mkdir(migration_out_path)
|
162
|
-
else
|
163
|
-
if migration_in_path.end_with?('.sql')
|
164
|
-
# if a .sql file, then copy & process
|
165
|
-
|
166
|
-
# create the the 'key' version of this name, which is basically the filepath
|
167
|
-
# of the .sql file relative without the leading '/' directory
|
168
|
-
manifest_name = relative_path[1..-1]
|
169
|
-
|
170
|
-
@log.debug("retrieving manifest definition for #{manifest_name}")
|
171
|
-
|
172
|
-
migration_def = loaded_manifest_hash[manifest_name]
|
173
|
-
|
174
|
-
unless migration_def.nil?
|
175
|
-
create_wrapped_up_migration(migration_in_path, migration_out_path, migration_def, loaded_manifest)
|
176
|
-
end
|
177
|
-
else
|
178
|
-
@log.debug "copying non-sql file #{migration_in_path}"
|
179
|
-
# if not a .sql file, just copy it over
|
180
|
-
FileUtils.cp(migration_in_path, migration_out_path)
|
181
|
-
end
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
def recreate_test_database(conn, test_db_name)
|
186
|
-
@log.debug "recreate test database #{test_db_name}"
|
187
|
-
|
188
|
-
conn.exec("drop database if exists #{test_db_name}")
|
189
|
-
conn.exec("create database #{test_db_name}")
|
190
|
-
end
|
191
|
-
|
192
|
-
def test(output_dir, test_options)
|
193
|
-
|
194
|
-
@log.info "testing..."
|
195
|
-
|
196
|
-
oobconn = Util::get_oob_conn(test_options)
|
197
|
-
target_dbname = Util::get_db_name(test_options)
|
198
|
-
|
199
|
-
run_manifests = []
|
200
|
-
|
201
|
-
|
202
|
-
recreate_test_database(oobconn, target_dbname)
|
203
|
-
|
204
|
-
conn = Util::get_conn(test_options)
|
205
|
-
|
206
|
-
migrator = Migrator.new(manifest_reader, sql_reader, :pgconn => conn)
|
207
|
-
migrator.migrate(output_dir)
|
208
|
-
conn.close
|
209
|
-
|
210
|
-
@log.info "test success"
|
211
|
-
|
212
|
-
end
|
213
|
-
end
|
214
|
-
end
|
1
|
+
require 'pathname'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'find'
|
4
|
+
require 'erb'
|
5
|
+
|
6
|
+
|
7
|
+
module PgMigrate
|
8
|
+
# takes a unprocessed manifest directory, and adds before/after headers to each file
|
9
|
+
class Builder
|
10
|
+
|
11
|
+
attr_accessor :manifest_reader, :sql_reader, :loaded_manifest
|
12
|
+
|
13
|
+
def initialize(manifest_reader, sql_reader)
|
14
|
+
@log = Logging.logger[self]
|
15
|
+
@manifest_reader = manifest_reader
|
16
|
+
@sql_reader = sql_reader
|
17
|
+
@template_dir = File.join(File.dirname(__FILE__), 'templates')
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
# input_dir is root path, contains file 'manifest' and 'migrations'
|
22
|
+
# output_dir will have a manifest and migrations folder, but processed
|
23
|
+
# force will create the output dir if needed, and *delete an existing directory* if it's in the way
|
24
|
+
# test will run tests
|
25
|
+
def build(input_dir, output_dir, options={:force=>true, :test=>false})
|
26
|
+
input_dir = File.expand_path(input_dir)
|
27
|
+
output_dir = File.expand_path(output_dir)
|
28
|
+
|
29
|
+
if input_dir == output_dir
|
30
|
+
raise 'input_dir can not be same as output_dir: #{input_dir}'
|
31
|
+
end
|
32
|
+
|
33
|
+
@log.debug "building migration directory #{input_dir} and placing result at: #{output_dir}"
|
34
|
+
|
35
|
+
output = Pathname.new(output_dir)
|
36
|
+
if !output.exist?
|
37
|
+
if !options[:force]
|
38
|
+
raise "Output directory '#{output_dir}' does not exist. Create it or specify force=true"
|
39
|
+
else
|
40
|
+
output.mkpath
|
41
|
+
end
|
42
|
+
else
|
43
|
+
# verify that it's is a directory
|
44
|
+
if !output.directory?
|
45
|
+
raise "output_dir #{output_dir} is a file; not a directory."
|
46
|
+
else
|
47
|
+
@log.debug("deleting & recreating existing output_dir #{output_dir}")
|
48
|
+
output.rmtree
|
49
|
+
output.mkpath
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# manifest always goes over mostly as-is,
|
54
|
+
# just with a comment added at top indicating our version
|
55
|
+
|
56
|
+
input_manifest = File.join(input_dir, MANIFEST_FILENAME)
|
57
|
+
output_manifest = File.join(output_dir, MANIFEST_FILENAME)
|
58
|
+
|
59
|
+
File.open(output_manifest, 'w') do |fout|
|
60
|
+
fout.puts "#{BUILDER_VERSION_HEADER}pg_migrate_ruby-#{PgMigrate::VERSION}"
|
61
|
+
IO.readlines(input_manifest).each do |input|
|
62
|
+
fout.puts input
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# if .pg_migrate file exists, copy it
|
67
|
+
input_pg_config = File.join(input_dir, PG_CONFIG)
|
68
|
+
if FileTest::exist? input_pg_config
|
69
|
+
output_pg_config = File.join(output_dir, PG_CONFIG)
|
70
|
+
|
71
|
+
File.open(output_pg_config, 'w') do |fout|
|
72
|
+
IO.readlines(input_pg_config).each do |input|
|
73
|
+
fout.puts input
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# in order array of manifest declarations
|
79
|
+
@loaded_manifest = @manifest_reader.load_input_manifest(input_dir)
|
80
|
+
# hashed on migration name hash of manifest
|
81
|
+
|
82
|
+
loaded_manifest_hash = @manifest_reader.hash_loaded_manifest(loaded_manifest)
|
83
|
+
@manifest_reader.validate_migration_paths(input_dir, loaded_manifest)
|
84
|
+
|
85
|
+
build_up(input_dir, output_dir, loaded_manifest_hash, loaded_manifest)
|
86
|
+
|
87
|
+
# ok we are done. time to test!
|
88
|
+
if options[:test]
|
89
|
+
test(output_dir, options)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def build_up(input_dir, output_dir, loaded_manifest_hash, loaded_manifest)
|
94
|
+
migrations_input = File.join(input_dir, UP_DIRNAME)
|
95
|
+
migrations_output = File.join(output_dir, UP_DIRNAME)
|
96
|
+
|
97
|
+
if(!FileTest::exist? migrations_input)
|
98
|
+
raise "'up' directory must exist at #{migrations_input}"
|
99
|
+
end
|
100
|
+
|
101
|
+
# iterate through files in input migrations path, wrapping files with transactions and other required bits
|
102
|
+
|
103
|
+
Find.find(migrations_input) do |path|
|
104
|
+
if path == ".."
|
105
|
+
Find.prune
|
106
|
+
else
|
107
|
+
@log.debug "building #{path}"
|
108
|
+
|
109
|
+
# create relative bit
|
110
|
+
relative_path = path[migrations_input.length..-1]
|
111
|
+
|
112
|
+
# create the filename correct for the input directory, for this file
|
113
|
+
migration_in_path = path
|
114
|
+
|
115
|
+
# create the filename correct for the output directory, for this file
|
116
|
+
migration_out_path = File.join(migrations_output, relative_path)
|
117
|
+
|
118
|
+
process_and_copy_up(migration_in_path, migration_out_path, relative_path, loaded_manifest_hash, loaded_manifest)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
create_bootstrap_script(migrations_output)
|
123
|
+
end
|
124
|
+
|
125
|
+
# creates the 'pg_migrations table'
|
126
|
+
def create_bootstrap_script(migration_out_path)
|
127
|
+
@log.debug "creating bootstrap script #{migration_out_path}"
|
128
|
+
run_template("bootstrap.erb", binding, File.join(migration_out_path, BOOTSTRAP_FILENAME))
|
129
|
+
end
|
130
|
+
|
131
|
+
def create_wrapped_up_migration(migration_in_filepath, migration_out_filepath, migration_def, loaded_manifest)
|
132
|
+
@log.debug "securing migration #{migration_def.name}"
|
133
|
+
|
134
|
+
builder_version="pg_migrate_ruby-#{PgMigrate::VERSION}"
|
135
|
+
manifest_version=loaded_manifest[-1].ordinal
|
136
|
+
migration_content = nil
|
137
|
+
File.open(migration_in_filepath, 'r') { |reader| migration_content = reader.read }
|
138
|
+
run_template("up.erb", binding, File.join(migration_out_filepath))
|
139
|
+
end
|
140
|
+
|
141
|
+
# given an input template and binding, writes to an output file
|
142
|
+
def run_template(template, binding, output_filepath)
|
143
|
+
bootstrap_template = nil
|
144
|
+
File.open(File.join(@template_dir, template), 'r') do |reader|
|
145
|
+
bootstrap_template = reader.read
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
template = ERB.new(bootstrap_template, 0, "%<>")
|
150
|
+
content = template.result(binding)
|
151
|
+
File.open(output_filepath, 'w') do |writer|
|
152
|
+
writer.syswrite(content)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def process_and_copy_up(migration_in_path, migration_out_path, relative_path, loaded_manifest_hash, loaded_manifest)
|
157
|
+
|
158
|
+
if FileTest.directory?(migration_in_path)
|
159
|
+
# copy over directories
|
160
|
+
# find relative-to-migrations dir this path
|
161
|
+
FileUtils.mkdir(migration_out_path)
|
162
|
+
else
|
163
|
+
if migration_in_path.end_with?('.sql')
|
164
|
+
# if a .sql file, then copy & process
|
165
|
+
|
166
|
+
# create the the 'key' version of this name, which is basically the filepath
|
167
|
+
# of the .sql file relative without the leading '/' directory
|
168
|
+
manifest_name = relative_path[1..-1]
|
169
|
+
|
170
|
+
@log.debug("retrieving manifest definition for #{manifest_name}")
|
171
|
+
|
172
|
+
migration_def = loaded_manifest_hash[manifest_name]
|
173
|
+
|
174
|
+
unless migration_def.nil?
|
175
|
+
create_wrapped_up_migration(migration_in_path, migration_out_path, migration_def, loaded_manifest)
|
176
|
+
end
|
177
|
+
else
|
178
|
+
@log.debug "copying non-sql file #{migration_in_path}"
|
179
|
+
# if not a .sql file, just copy it over
|
180
|
+
FileUtils.cp(migration_in_path, migration_out_path)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def recreate_test_database(conn, test_db_name)
|
186
|
+
@log.debug "recreate test database #{test_db_name}"
|
187
|
+
|
188
|
+
conn.exec("drop database if exists #{test_db_name}")
|
189
|
+
conn.exec("create database #{test_db_name}")
|
190
|
+
end
|
191
|
+
|
192
|
+
def test(output_dir, test_options)
|
193
|
+
|
194
|
+
@log.info "testing..."
|
195
|
+
|
196
|
+
oobconn = Util::get_oob_conn(test_options)
|
197
|
+
target_dbname = Util::get_db_name(test_options)
|
198
|
+
|
199
|
+
run_manifests = []
|
200
|
+
|
201
|
+
|
202
|
+
recreate_test_database(oobconn, target_dbname)
|
203
|
+
|
204
|
+
conn = Util::get_conn(test_options)
|
205
|
+
|
206
|
+
migrator = Migrator.new(manifest_reader, sql_reader, :pgconn => conn)
|
207
|
+
migrator.migrate(output_dir)
|
208
|
+
conn.close
|
209
|
+
|
210
|
+
@log.info "test success"
|
211
|
+
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|