pg_migrate 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +1 -1
- data/lib/pg_migrate/builder.rb +27 -12
- data/lib/pg_migrate/command_line.rb +130 -15
- data/lib/pg_migrate/manifest_reader.rb +6 -6
- data/lib/pg_migrate/migration.rb +1 -1
- data/lib/pg_migrate/migrator.rb +2 -2
- data/lib/pg_migrate/package.rb +142 -0
- data/lib/pg_migrate/package_templates/Gemfile.erb +4 -0
- data/lib/pg_migrate/package_templates/bin/migrate.rb +10 -0
- data/lib/pg_migrate/package_templates/gemspec.erb +21 -0
- data/lib/pg_migrate/package_templates/lib/gem/version.rb +3 -0
- data/lib/pg_migrate/package_templates/lib/gem.rb +12 -0
- data/lib/pg_migrate/props.rb +19 -0
- data/lib/pg_migrate/sql_reader.rb +4 -3
- data/lib/pg_migrate/templates/bootstrap.erb +50 -20
- data/lib/pg_migrate/templates/up.erb +6 -4
- data/lib/pg_migrate/version.rb +1 -1
- data/lib/pg_migrate.rb +5 -1
- data/pg_migrate.gemspec +1 -1
- data/spec/pg_migrate/builder_spec.rb +2 -0
- data/spec/pg_migrate/command_line_spec.rb +53 -0
- data/spec/pg_migrate/migrator_spec.rb +3 -3
- data/spec/pg_migrate/package_spec.rb +38 -0
- metadata +13 -2
data/Gemfile.lock
CHANGED
data/lib/pg_migrate/builder.rb
CHANGED
@@ -8,10 +8,8 @@ module PgMigrate
|
|
8
8
|
# takes a unprocessed manifest directory, and adds before/after headers to each file
|
9
9
|
class Builder
|
10
10
|
|
11
|
-
|
12
11
|
attr_accessor :manifest_reader, :sql_reader
|
13
12
|
|
14
|
-
|
15
13
|
def initialize(manifest_reader, sql_reader)
|
16
14
|
@log = Logging.logger[self]
|
17
15
|
@manifest_reader = manifest_reader
|
@@ -26,7 +24,7 @@ module PgMigrate
|
|
26
24
|
def build(input_dir, output_dir, options={:force=>true})
|
27
25
|
input_dir = File.expand_path(input_dir)
|
28
26
|
output_dir = File.expand_path(output_dir)
|
29
|
-
|
27
|
+
|
30
28
|
if input_dir == output_dir
|
31
29
|
raise 'input_dir can not be same as output_dir: #{input_dir}'
|
32
30
|
end
|
@@ -36,7 +34,7 @@ module PgMigrate
|
|
36
34
|
output = Pathname.new(output_dir)
|
37
35
|
if !output.exist?
|
38
36
|
if !options[:force]
|
39
|
-
raise "Output directory '#{output_dir}' does not exist. Create it or specify
|
37
|
+
raise "Output directory '#{output_dir}' does not exist. Create it or specify force=true"
|
40
38
|
else
|
41
39
|
output.mkpath
|
42
40
|
end
|
@@ -64,6 +62,18 @@ module PgMigrate
|
|
64
62
|
end
|
65
63
|
end
|
66
64
|
|
65
|
+
# if .pg_migrate file exists, copy it
|
66
|
+
input_pg_config = File.join(input_dir, PG_CONFIG)
|
67
|
+
if FileTest::exist? input_pg_config
|
68
|
+
output_pg_config = File.join(output_dir, PG_CONFIG)
|
69
|
+
|
70
|
+
File.open(output_pg_config, 'w') do |fout|
|
71
|
+
IO.readlines(input_pg_config).each do |input|
|
72
|
+
fout.puts input
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
67
77
|
# in order array of manifest declarations
|
68
78
|
loaded_manifest = @manifest_reader.load_input_manifest(input_dir)
|
69
79
|
# hashed on migration name hash of manifest
|
@@ -71,13 +81,17 @@ module PgMigrate
|
|
71
81
|
loaded_manifest_hash = @manifest_reader.hash_loaded_manifest(loaded_manifest)
|
72
82
|
@manifest_reader.validate_migration_paths(input_dir, loaded_manifest)
|
73
83
|
|
74
|
-
build_up(input_dir, output_dir, loaded_manifest_hash)
|
84
|
+
build_up(input_dir, output_dir, loaded_manifest_hash, loaded_manifest)
|
75
85
|
end
|
76
86
|
|
77
|
-
def build_up(input_dir, output_dir, loaded_manifest_hash)
|
87
|
+
def build_up(input_dir, output_dir, loaded_manifest_hash, loaded_manifest)
|
78
88
|
migrations_input = File.join(input_dir, UP_DIRNAME)
|
79
89
|
migrations_output = File.join(output_dir, UP_DIRNAME)
|
80
90
|
|
91
|
+
if(!FileTest::exist? migrations_input)
|
92
|
+
raise "'up' directory must exist at #{migrations_input}"
|
93
|
+
end
|
94
|
+
|
81
95
|
# iterate through files in input migrations path, wrapping files with transactions and other required bits
|
82
96
|
|
83
97
|
Find.find(migrations_input) do |path|
|
@@ -95,7 +109,7 @@ module PgMigrate
|
|
95
109
|
# create the filename correct for the output directory, for this file
|
96
110
|
migration_out_path = File.join(migrations_output, relative_path)
|
97
111
|
|
98
|
-
process_and_copy_up(migration_in_path, migration_out_path, relative_path, loaded_manifest_hash)
|
112
|
+
process_and_copy_up(migration_in_path, migration_out_path, relative_path, loaded_manifest_hash, loaded_manifest)
|
99
113
|
end
|
100
114
|
end
|
101
115
|
|
@@ -107,10 +121,11 @@ module PgMigrate
|
|
107
121
|
run_template("bootstrap.erb", binding, File.join(migration_out_path, BOOTSTRAP_FILENAME))
|
108
122
|
end
|
109
123
|
|
110
|
-
def create_wrapped_up_migration(migration_in_filepath, migration_out_filepath, migration_def)
|
111
|
-
|
124
|
+
def create_wrapped_up_migration(migration_in_filepath, migration_out_filepath, migration_def, loaded_manifest)
|
125
|
+
builder_version="pg_migrate_ruby-#{PgMigrate::VERSION}"
|
126
|
+
manifest_version=loaded_manifest[-1].ordinal
|
112
127
|
migration_content = nil
|
113
|
-
File.open(migration_in_filepath, 'r') {|reader| migration_content = reader.read }
|
128
|
+
File.open(migration_in_filepath, 'r') { |reader| migration_content = reader.read }
|
114
129
|
run_template("up.erb", binding, File.join(migration_out_filepath))
|
115
130
|
end
|
116
131
|
|
@@ -129,7 +144,7 @@ module PgMigrate
|
|
129
144
|
end
|
130
145
|
end
|
131
146
|
|
132
|
-
def process_and_copy_up(migration_in_path, migration_out_path, relative_path, loaded_manifest_hash)
|
147
|
+
def process_and_copy_up(migration_in_path, migration_out_path, relative_path, loaded_manifest_hash, loaded_manifest)
|
133
148
|
|
134
149
|
if FileTest.directory?(migration_in_path)
|
135
150
|
# copy over directories
|
@@ -147,7 +162,7 @@ module PgMigrate
|
|
147
162
|
|
148
163
|
migration_def = loaded_manifest_hash[manifest_name]
|
149
164
|
|
150
|
-
create_wrapped_up_migration(migration_in_path, migration_out_path, migration_def)
|
165
|
+
create_wrapped_up_migration(migration_in_path, migration_out_path, migration_def, loaded_manifest)
|
151
166
|
else
|
152
167
|
# if not a .sql file, just copy it over
|
153
168
|
FileUtils.cp(migration_in_path, migration_out_path)
|
@@ -1,31 +1,56 @@
|
|
1
1
|
module PgMigrate
|
2
2
|
class CommandLine < Thor
|
3
3
|
|
4
|
+
@@packaged_source = '.'
|
5
|
+
|
6
|
+
def initialize(*args)
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.packaged_source
|
11
|
+
@@packaged_source
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.packaged_source=(value)
|
15
|
+
@@packaged_source = value
|
16
|
+
end
|
17
|
+
|
18
|
+
|
4
19
|
desc "up", "migrates the database forwards, applying migrations found in the source directory"
|
5
|
-
method_option :source, :aliases => "-s", :default =>
|
6
|
-
method_option :connopts, :aliases => "-
|
7
|
-
method_option :verbose, :aliases => "-v", :type => :boolean, :
|
20
|
+
method_option :source, :aliases => "-s", :default => nil, :banner => 'input directory', :desc => "a pg_migrate built manifest. Should contain your processed manifest and up|down|test folders"
|
21
|
+
method_option :connopts, :aliases => "-c", :type => :hash, :required => true, :banner => "connection options", :desc => "database connection options used by gem 'pg': dbname|host|hostaddr|port|user|password|connection_timeout|options|sslmode|krbsrvname|gsslib|service"
|
22
|
+
method_option :verbose, :aliases => "-v", :type => :boolean, :banner => "verbose", :desc=> "set to raise verbosity"
|
8
23
|
|
9
24
|
def up
|
10
|
-
|
25
|
+
source = options[:source]
|
26
|
+
|
27
|
+
if source.nil?
|
28
|
+
source = @@packaged_source
|
29
|
+
end
|
30
|
+
|
31
|
+
method_defaults = {"verbose" => false}
|
32
|
+
local_options = set_defaults_from_file(method_defaults, "up", source)
|
33
|
+
local_options = local_options.merge(options)
|
34
|
+
|
35
|
+
bootstrap_logger(local_options["verbose"])
|
11
36
|
|
12
37
|
manifest_reader = ManifestReader.new
|
13
38
|
sql_reader = SqlReader.new
|
14
39
|
|
15
|
-
connopts =
|
16
|
-
if !connopts[
|
40
|
+
connopts = local_options["connopts"]
|
41
|
+
if !connopts["port"].nil?
|
17
42
|
connopts[:port] = connopts[:port].to_i
|
18
43
|
end
|
19
44
|
|
20
45
|
migrator = Migrator.new(manifest_reader, sql_reader, connopts)
|
21
46
|
|
22
47
|
begin
|
23
|
-
migrator.migrate(
|
48
|
+
migrator.migrate(source)
|
24
49
|
rescue Exception => e
|
25
|
-
if !
|
50
|
+
if !local_options["verbose"]
|
26
51
|
# catch common exceptions and make pretty on command-line
|
27
52
|
if !e.message.index("ManifestReader: code=unloadable_manifest").nil?
|
28
|
-
puts "Unable to load manifest in source directory '#{
|
53
|
+
puts "Unable to load manifest in source directory '#{source}' . Check -s|--source option and run again."
|
29
54
|
exit 1
|
30
55
|
else
|
31
56
|
raise e
|
@@ -41,25 +66,81 @@ module PgMigrate
|
|
41
66
|
desc "down", "not implemented"
|
42
67
|
|
43
68
|
def down
|
69
|
+
local_options = options
|
70
|
+
options = set_defaults_from_file(location_options)
|
44
71
|
bootstrap_logger(options[:verbose])
|
45
72
|
|
46
73
|
raise 'Not implemented'
|
47
74
|
end
|
48
75
|
|
49
76
|
desc "build", "processes a pg_migrate source directory and places the result in the specified output directory"
|
50
|
-
method_option :source, :aliases => "-s", :default =>
|
51
|
-
method_option :out, :aliases => "-o", :
|
52
|
-
method_option :force, :aliases => "-f", :
|
53
|
-
method_option :verbose, :aliases => "-v", :type => :boolean, :
|
77
|
+
method_option :source, :aliases => "-s", :default => nil, :banner => 'input directory', :desc => "the input directory containing a manifest file and up|down|test folders"
|
78
|
+
method_option :out, :aliases => "-o", :banner => "output directory", :desc => "where the processed migrations will be placed"
|
79
|
+
method_option :force, :aliases => "-f", :type => :boolean, :banner => "overwrite out", :desc => "if specified, the out directory will be created before processing occurs, replacing any existing directory"
|
80
|
+
method_option :verbose, :aliases => "-v", :type => :boolean, :banner => "verbose", :desc=> "set to raise verbosity"
|
54
81
|
|
55
82
|
def build
|
83
|
+
source = options[:source]
|
56
84
|
|
57
|
-
|
85
|
+
if source.nil?
|
86
|
+
source = @@packaged_source
|
87
|
+
end
|
88
|
+
|
89
|
+
method_defaults = {"force" => false, "verbose" => false}
|
90
|
+
local_options = set_defaults_from_file(method_defaults, "build", source)
|
91
|
+
local_options = local_options.merge(options)
|
92
|
+
|
93
|
+
bootstrap_logger(local_options["verbose"])
|
94
|
+
|
95
|
+
if !local_options["out"]
|
96
|
+
puts "error: --out not specified"
|
97
|
+
exit 1
|
98
|
+
end
|
58
99
|
|
59
100
|
manifest_reader = ManifestReader.new
|
60
101
|
sql_reader = SqlReader.new
|
61
102
|
builder = Builder.new(manifest_reader, sql_reader)
|
62
|
-
builder.build(
|
103
|
+
builder.build(source, local_options["out"], :force => local_options["force"])
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
desc "package", "packages a built pg_migrate project into a custom gem containing schemas and simpler migration interface"
|
108
|
+
method_option :source, :aliases => "-s", :default => nil, :banner => 'input directory', :desc => "the input directory containing a manifest file and up|down|test folders that has been previously built by pg_migrate build"
|
109
|
+
method_option :out, :aliases => "-o", :banner => "output directory", :desc => "where the gem will be placed (as well as the exploded gem's contents)"
|
110
|
+
method_option :name, :aliases => "-n", :banner => "the name of the schema gem", :desc => "the name of the gem"
|
111
|
+
method_option :version, :aliases => "-e", :banner => "the version of the schema gem", :desc => "the version of the gem"
|
112
|
+
method_option :force, :aliases => "-f", :type => :boolean, :banner => "overwrite out", :desc => "if specified, the out directory will be created before processing occurs, replacing any existing directory"
|
113
|
+
method_option :verbose, :aliases => "-v", :type => :boolean, :banner => "verbose", :desc=> "set to raise verbosity"
|
114
|
+
|
115
|
+
def package
|
116
|
+
source = options[:source]
|
117
|
+
|
118
|
+
if source.nil?
|
119
|
+
source = @@packaged_source
|
120
|
+
end
|
121
|
+
|
122
|
+
method_defaults = {"force" => false, "verbose" => false}
|
123
|
+
local_options = set_defaults_from_file(method_defaults, "package", source)
|
124
|
+
local_options = local_options.merge(options)
|
125
|
+
|
126
|
+
if !local_options["out"]
|
127
|
+
puts "error: --out not specified"
|
128
|
+
exit 1
|
129
|
+
end
|
130
|
+
if !local_options["name"]
|
131
|
+
puts "error: --version not specified"
|
132
|
+
exit 1
|
133
|
+
end
|
134
|
+
if !local_options["version"]
|
135
|
+
puts "error: --version not specified"
|
136
|
+
exit 1
|
137
|
+
end
|
138
|
+
|
139
|
+
bootstrap_logger(local_options["verbose"])
|
140
|
+
|
141
|
+
manifest_reader = ManifestReader.new
|
142
|
+
builder = Package.new(manifest_reader)
|
143
|
+
builder.package(source, local_options["out"], local_options["name"], local_options["version"], :force => local_options["force"])
|
63
144
|
end
|
64
145
|
|
65
146
|
no_tasks do
|
@@ -73,6 +154,40 @@ module PgMigrate
|
|
73
154
|
|
74
155
|
Logging.logger.root.appenders = Logging.appenders.stdout
|
75
156
|
end
|
157
|
+
|
158
|
+
|
159
|
+
def set_defaults_from_file(default_options, context, source)
|
160
|
+
@file_defaults = @file_defaults ||= load_file(context, source)
|
161
|
+
merged = default_options.merge(@file_defaults)
|
162
|
+
end
|
163
|
+
|
164
|
+
def load_file(context, source)
|
165
|
+
|
166
|
+
defaults = nil
|
167
|
+
config = File.join(source, PG_CONFIG)
|
168
|
+
if FileTest::exist? (config)
|
169
|
+
puts "found #{PG_CONFIG}"
|
170
|
+
defaults = Properties.new(config)
|
171
|
+
else
|
172
|
+
defaults = Properties.new
|
173
|
+
end
|
174
|
+
|
175
|
+
map = {}
|
176
|
+
defaults.each_pair do |k, v|
|
177
|
+
map[k.upcase] = v
|
178
|
+
|
179
|
+
# make a context-removed version of a key, if it starts with 'context.'
|
180
|
+
prefix = "#{context}."
|
181
|
+
if k.start_with? prefix
|
182
|
+
map[k[prefix.length..-1]] = v
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
return map
|
187
|
+
|
188
|
+
end
|
76
189
|
end
|
190
|
+
|
191
|
+
|
77
192
|
end
|
78
193
|
end
|
@@ -52,18 +52,17 @@ module PgMigrate
|
|
52
52
|
|
53
53
|
manifest_filepath = File.join(manifest_path, MANIFEST_FILENAME)
|
54
54
|
|
55
|
-
@log.debug "loading manifest from #{
|
55
|
+
@log.debug "loading manifest from #{manifest_filepath}"
|
56
56
|
|
57
|
+
# there should be a file called 'manifest' at this location
|
57
58
|
if !FileTest::exist?(manifest_filepath)
|
58
|
-
raise "ManifestReader: code=unloadable_manifest: manifest not found at #{
|
59
|
+
raise "ManifestReader: code=unloadable_manifest: manifest not found at #{manifest_filepath}"
|
59
60
|
end
|
60
61
|
|
61
|
-
# there should be a file called 'manifest' at this location
|
62
62
|
manifest_lines = IO.readlines(manifest_filepath)
|
63
63
|
|
64
64
|
ordinal = 0
|
65
65
|
manifest_lines.each_with_index do |line, index|
|
66
|
-
# ignore comments
|
67
66
|
migration_name = line.strip
|
68
67
|
|
69
68
|
@log.debug "processing line:#{index} #{line}"
|
@@ -76,15 +75,16 @@ module PgMigrate
|
|
76
75
|
version = migration_name[BUILDER_VERSION_HEADER.length..-1]
|
77
76
|
@log.debug "manifest has builder_version #{version}"
|
78
77
|
else
|
79
|
-
raise "manifest invalid: missing/malformed version. expecting '# pg_migrate-VERSION' to begin first line '#{line}' of manifest file: '#{
|
78
|
+
raise "manifest invalid: missing/malformed version. expecting '# pg_migrate-VERSION' to begin first line '#{line}' of manifest file: '#{manifest_filepath}'"
|
80
79
|
end
|
81
80
|
end
|
82
81
|
end
|
83
82
|
|
83
|
+
# ignore comments
|
84
84
|
if migration_name.empty? or migration_name.start_with?('#')
|
85
85
|
# ignored!
|
86
86
|
else
|
87
|
-
@log.debug "adding
|
87
|
+
@log.debug "adding migration #{migration_name} with ordinal #{ordinal}"
|
88
88
|
manifest.push(Migration.new(migration_name, ordinal, build_migration_path(manifest_path, migration_name)))
|
89
89
|
ordinal += 1
|
90
90
|
end
|
data/lib/pg_migrate/migration.rb
CHANGED
data/lib/pg_migrate/migrator.rb
CHANGED
@@ -72,7 +72,7 @@ module PgMigrate
|
|
72
72
|
|
73
73
|
statements = @sql_reader.load_migration(filepath)
|
74
74
|
if statements.length == 0
|
75
|
-
raise 'no statements found in migration #{
|
75
|
+
raise 'no statements found in migration #{filepath}'
|
76
76
|
end
|
77
77
|
run_migration(name, statements)
|
78
78
|
end
|
@@ -86,7 +86,7 @@ module PgMigrate
|
|
86
86
|
end
|
87
87
|
rescue Exception => e
|
88
88
|
# we make a special allowance for one exception; it just means this migration
|
89
|
-
# has already
|
89
|
+
# has already occurred, and we should just treat it like a continue
|
90
90
|
if e.message.index('pg_migrate: code=migration_exists').nil?
|
91
91
|
conn.exec("ROLLBACK")
|
92
92
|
raise e
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rubygems/builder'
|
5
|
+
#require 'rubygems/package'
|
6
|
+
|
7
|
+
module PgMigrate
|
8
|
+
class Package
|
9
|
+
|
10
|
+
attr_accessor :manifest_reader
|
11
|
+
|
12
|
+
def initialize(manifest_reader)
|
13
|
+
@log = Logging.logger[self]
|
14
|
+
@manifest_reader = manifest_reader
|
15
|
+
@template_dir = File.join(File.dirname(__FILE__), 'package_templates')
|
16
|
+
end
|
17
|
+
|
18
|
+
def package(built_migration_path, output_dir, name, version, options={:force=>true})
|
19
|
+
gemspec = create_gem(built_migration_path, output_dir, name, version, options[:force])
|
20
|
+
build_gem(gemspec, output_dir)
|
21
|
+
end
|
22
|
+
|
23
|
+
def create_gem (built_migration_path, output_dir, name, version, force)
|
24
|
+
# validate that manifest is valid
|
25
|
+
@log.debug "validating output dir is manifest"
|
26
|
+
|
27
|
+
if !FileTest::exist?(built_migration_path)
|
28
|
+
raise "built manifest path does not exist #{built_migration_path}"
|
29
|
+
end
|
30
|
+
|
31
|
+
if built_migration_path == output_dir
|
32
|
+
raise "source and destination can not be the same path"
|
33
|
+
end
|
34
|
+
|
35
|
+
loaded_manifest = @manifest_reader.load_input_manifest(built_migration_path)
|
36
|
+
@manifest_reader.validate_migration_paths(built_migration_path, loaded_manifest)
|
37
|
+
|
38
|
+
@log.debug "preparing to build gem"
|
39
|
+
|
40
|
+
target = File.join(output_dir, name)
|
41
|
+
|
42
|
+
# stolen almost verbatim from bundler: https://github.com/carlhuda/bundler/blob/master/lib/bundler/cli.rb
|
43
|
+
constant_name = name.split('_').map { |p| p[0..0].upcase + p[1..-1] }.join
|
44
|
+
constant_name = constant_name.split('-').map { |q| q[0..0].upcase + q[1..-1] }.join('::') if constant_name =~ /-/
|
45
|
+
constant_array = constant_name.split('::')
|
46
|
+
# end stolen
|
47
|
+
|
48
|
+
author = "pgmigrate"
|
49
|
+
email = "pgmigrate@pgmigrate.io"
|
50
|
+
pg_migrate_version = PgMigrate::VERSION
|
51
|
+
gemfiles = ["Gemfile", "#{name}.gemspec", "lib/#{name}.rb", "lib/#{name}/version.rb", "bin/#{name}"]
|
52
|
+
gemfiles += userfiles(built_migration_path, name)
|
53
|
+
gemspec_path = File.join(output_dir, "#{name}.gemspec")
|
54
|
+
|
55
|
+
@log.debug "building gem"
|
56
|
+
|
57
|
+
output = Pathname.new(output_dir)
|
58
|
+
if !output.exist?
|
59
|
+
if !force
|
60
|
+
raise "Output directory '#{output_dir}' does not exist. Create it or specify force=true"
|
61
|
+
else
|
62
|
+
output.mkpath
|
63
|
+
end
|
64
|
+
else
|
65
|
+
# verify that it's is a directory
|
66
|
+
if !output.directory?
|
67
|
+
raise "output_dir #{output_dir} is a file; not a directory."
|
68
|
+
else
|
69
|
+
@log.debug("deleting & recreating existing output_dir #{output_dir}")
|
70
|
+
output.rmtree
|
71
|
+
output.mkpath
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
FileUtils.mkdir_p(output_dir)
|
76
|
+
FileUtils.mkdir_p(File.join(output_dir, "bin"))
|
77
|
+
FileUtils.mkdir_p(File.join(output_dir, "lib", name))
|
78
|
+
run_template("Gemfile.erb", binding, File.join(output_dir, "Gemfile"))
|
79
|
+
run_template("gemspec.erb", binding, gemspec_path)
|
80
|
+
run_template("lib/gem.rb", binding, File.join(output_dir, "lib", "#{name}.rb"))
|
81
|
+
run_template("lib/gem/version.rb", binding, File.join(output_dir, "lib", name, "version.rb"))
|
82
|
+
run_template("bin/migrate.rb", binding, File.join(output_dir, "bin", "#{name}"))
|
83
|
+
copy_schema(built_migration_path, File.join(output_dir, "lib", name, "schemas"))
|
84
|
+
|
85
|
+
return gemspec_path
|
86
|
+
end
|
87
|
+
|
88
|
+
def copy_schema(built_migration_path, output_dir)
|
89
|
+
FileUtils.cp_r(File.join(built_migration_path, '.'), output_dir)
|
90
|
+
end
|
91
|
+
|
92
|
+
def build_gem(gemspec_path, output_dir)
|
93
|
+
@log.debug "building gem"
|
94
|
+
|
95
|
+
@log.debug "loading gem specification #{gemspec_path}"
|
96
|
+
spec = Gem::Specification.load(gemspec_path)
|
97
|
+
|
98
|
+
if spec.nil?
|
99
|
+
raise 'unable to build gem from specification'
|
100
|
+
end
|
101
|
+
|
102
|
+
@log.debug "packaging gem"
|
103
|
+
Dir.chdir(output_dir) do
|
104
|
+
Gem::Builder.new(spec).build
|
105
|
+
end
|
106
|
+
#Gem::Package.build spec, false
|
107
|
+
end
|
108
|
+
|
109
|
+
def userfiles(built_migration_path, name)
|
110
|
+
|
111
|
+
gempaths = []
|
112
|
+
Find.find(built_migration_path) do |path|
|
113
|
+
if path == ".."
|
114
|
+
Find.prune
|
115
|
+
else
|
116
|
+
# make relative
|
117
|
+
|
118
|
+
relative = path[built_migration_path.length..-1]
|
119
|
+
gempath = File.join("lib", name, "schemas", relative)
|
120
|
+
gempaths.push(gempath)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
return gempaths
|
125
|
+
end
|
126
|
+
|
127
|
+
# given an input template and binding, writes to an output file
|
128
|
+
def run_template(template, opt, output_filepath)
|
129
|
+
bootstrap_template = nil
|
130
|
+
File.open(File.join(@template_dir, template), 'r') do |reader|
|
131
|
+
bootstrap_template = reader.read
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
template = ERB.new(bootstrap_template, 0, "%<>")
|
136
|
+
content = template.result(opt)
|
137
|
+
File.open(output_filepath, 'w') do |writer|
|
138
|
+
writer.syswrite(content)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/<%= name %>/version', __FILE__)
|
3
|
+
lib=File.expand_path('../lib', __FILE__)
|
4
|
+
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.authors = ["<%= author %>"]
|
8
|
+
gem.email = ["<%= email %> "]
|
9
|
+
gem.description = %q{A pg_migrate bundle for <%= name %>}
|
10
|
+
gem.summary = %q{A pg_migrate bundle built by pg_migrate, containing the schemas of <%= name %>)}
|
11
|
+
gem.homepage = "https://github.com/sethcall/pg_migrate"
|
12
|
+
|
13
|
+
gem.files = <%= gemfiles %>
|
14
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
15
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
16
|
+
gem.name = "<%= name %>"
|
17
|
+
gem.require_paths = ["lib"]
|
18
|
+
gem.version = <%= constant_name %>::VERSION
|
19
|
+
|
20
|
+
gem.add_dependency('pg_migrate', '<%= pg_migrate_version %>')
|
21
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require '<%= name %>/version'
|
2
|
+
require 'pg_migrate'
|
3
|
+
|
4
|
+
module <%= constant_name %>
|
5
|
+
|
6
|
+
class Migrator
|
7
|
+
def migrate options={}
|
8
|
+
pgMigrator = PgMigrate::Migrator.new(PgMigrate::ManifestReader.new, PgMigrate::SqlReader.new, options)
|
9
|
+
pgMigrator.migrate(File.expand_path('../<%= name %>/schemas', __FILE__))
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# from comment at http://devender.wordpress.com/2006/05/01/reading-and-writing-java-property-files-with-ruby/
|
2
|
+
|
3
|
+
module PgMigrate
|
4
|
+
class Properties < Hash
|
5
|
+
def initialize(filename = nil)
|
6
|
+
if (filename) then
|
7
|
+
File.open(filename).select { |line| not line=~/^[ \t]*(#.+)*$/ }.# ignore comments and blank lines
|
8
|
+
each { |line|
|
9
|
+
(k, v) = line.chomp.split('=', 2)
|
10
|
+
self[k.strip] = v.strip
|
11
|
+
}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
self.map { |k, v| " #{k}=#{v}" }.join("\n")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -26,12 +26,13 @@ module PgMigrate
|
|
26
26
|
current_statement += " " + line_stripped;
|
27
27
|
|
28
28
|
if line_stripped.end_with?(";")
|
29
|
-
if current_statement =~ /^\s*CREATE\s+(OR\s+REPLACE\s+)?FUNCTION/i
|
29
|
+
if current_statement =~ /^\s*CREATE\s+(OR\s+REPLACE\s+)?FUNCTION/i || current_statement =~ /^\s*DO\s+/i
|
30
30
|
# if we are in a function, a ';' isn't enough to end. We need to see if the last word was one of
|
31
|
-
# pltcl, plperl, plpgsql, plpythonu, sql
|
31
|
+
# pltcl, plperl, plpgsql, plpythonu, sql
|
32
32
|
# you can extend languages in postgresql; detecting these isn't supported yet.
|
33
33
|
|
34
|
-
|
34
|
+
# we also detect anonymous functions (DO) and their ending sequence.
|
35
|
+
if current_statement =~ /(plpgsql|plperl|plpythonu|pltcl|sql)\s*;$/i || current_statement =~ /END\s*\$\$\s+(LANGUAGE\s+(plpgsql|plperl|plpythonu|pltcl|sql))?\s*;$/i
|
35
36
|
statements.push(current_statement[0...-1]) # strip off last ;
|
36
37
|
current_statement = ""
|
37
38
|
end
|
@@ -9,35 +9,48 @@
|
|
9
9
|
|
10
10
|
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
11
11
|
|
12
|
-
|
12
|
+
-- bootstrap in the pgmigrate schema namespace, if it doesn't exist
|
13
|
+
DO $$DECLARE already_exists boolean;
|
14
|
+
BEGIN
|
15
|
+
|
16
|
+
SELECT exists INTO STRICT already_exists (select * from pg_catalog.pg_namespace where nspname = 'pgmigrate');
|
17
|
+
|
18
|
+
IF NOT already_exists THEN
|
19
|
+
create schema pgmigrate;
|
20
|
+
END IF;
|
21
|
+
|
22
|
+
END$$;
|
23
|
+
|
24
|
+
|
25
|
+
CREATE OR REPLACE FUNCTION pgmigrate.bootstrap_pg_migrate() RETURNS void AS $$
|
13
26
|
DECLARE
|
14
27
|
found_pg_migrate information_schema.tables;
|
15
28
|
found_pg_migrations information_schema.tables;
|
16
29
|
|
17
30
|
BEGIN
|
18
31
|
BEGIN
|
19
|
-
SELECT * INTO STRICT found_pg_migrate FROM information_schema.tables WHERE table_name = 'pg_migrate';
|
32
|
+
SELECT * INTO STRICT found_pg_migrate FROM information_schema.tables WHERE table_name = 'pg_migrate' and table_schema = 'pgmigrate';
|
20
33
|
|
21
34
|
EXCEPTION
|
22
35
|
WHEN NO_DATA_FOUND THEN
|
23
|
-
CREATE TABLE pg_migrate (id BIGSERIAL PRIMARY KEY, template_version VARCHAR(255), builder_version VARCHAR(255), migrator_version VARCHAR(255), database_version VARCHAR(1024));
|
24
|
-
CREATE INDEX pg_migrate_unique_index ON pg_migrate (template_version, builder_version, migrator_version, database_version);
|
36
|
+
CREATE TABLE pgmigrate.pg_migrate (id BIGSERIAL PRIMARY KEY, template_version VARCHAR(255), builder_version VARCHAR(255), migrator_version VARCHAR(255), database_version VARCHAR(1024));
|
37
|
+
CREATE INDEX pg_migrate_unique_index ON pgmigrate.pg_migrate (template_version, builder_version, migrator_version, database_version);
|
25
38
|
|
26
39
|
WHEN TOO_MANY_ROWS THEN
|
27
40
|
RAISE EXCEPTION 'Multiple pg_migrate tables. Unique key on information_schema.tables should have prevented this.';
|
28
41
|
END;
|
29
42
|
|
30
43
|
BEGIN
|
31
|
-
SELECT * INTO STRICT found_pg_migrations FROM information_schema.tables WHERE table_name = 'pg_migrations';
|
44
|
+
SELECT * INTO STRICT found_pg_migrations FROM information_schema.tables WHERE table_name = 'pg_migrations' and table_schema = 'pgmigrate';
|
32
45
|
|
33
46
|
EXCEPTION
|
34
47
|
WHEN NO_DATA_FOUND THEN
|
35
|
-
CREATE TABLE pg_migrations(
|
48
|
+
CREATE TABLE pgmigrate.pg_migrations(
|
36
49
|
name VARCHAR(255) PRIMARY KEY,
|
37
50
|
ordinal INTEGER NOT NULL,
|
38
51
|
created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
39
52
|
finalized SMALLINT DEFAULT 1,
|
40
|
-
pg_migrate_id BIGINT NOT NULL REFERENCES pg_migrate(id));
|
53
|
+
pg_migrate_id BIGINT NOT NULL REFERENCES pgmigrate.pg_migrate(id));
|
41
54
|
WHEN TOO_MANY_ROWS THEN
|
42
55
|
RAISE EXCEPTION 'Multiple pg_migrations tables. Unique key on information_schema.tables should have prevented this.';
|
43
56
|
END;
|
@@ -46,23 +59,23 @@ END;
|
|
46
59
|
$$ LANGUAGE plpgsql;
|
47
60
|
|
48
61
|
|
49
|
-
SELECT bootstrap_pg_migrate();
|
62
|
+
SELECT pgmigrate.bootstrap_pg_migrate();
|
50
63
|
|
51
64
|
-- verifies that the specified migration name has the expected ordinal. No exception is thrown if no migration
|
52
65
|
-- of this name exists, and no exception is thrown if the migration + ordinal pair is found on a single row.
|
53
66
|
-- Only if the migrtion is found with the wrong row is an exception thrown.
|
54
|
-
CREATE OR REPLACE FUNCTION verify_against_existing_migrations(migration varchar(255), ordinal integer) RETURNS VOID AS $$
|
67
|
+
CREATE OR REPLACE FUNCTION pgmigrate.verify_against_existing_migrations(migration varchar(255), ordinal integer) RETURNS VOID AS $$
|
55
68
|
DECLARE
|
56
|
-
found_migration pg_migrations;
|
69
|
+
found_migration pgmigrate.pg_migrations;
|
57
70
|
BEGIN
|
58
71
|
BEGIN
|
59
|
-
EXECUTE 'SELECT * FROM pg_migrations WHERE name=$1' INTO STRICT found_migration USING migration;
|
72
|
+
EXECUTE 'SELECT * FROM pgmigrate.pg_migrations WHERE name=$1' INTO STRICT found_migration USING migration;
|
60
73
|
EXCEPTION
|
61
74
|
WHEN NO_DATA_FOUND THEN
|
62
75
|
-- if no data, then this migration is unrun. One more check remains...
|
63
76
|
-- if the last run migration's ordinal is 1 less than this one, we are ready to go.
|
64
|
-
IF coalesce((SELECT MAX(p.ordinal) FROM pg_migrations as p), -1) <> ordinal - 1 THEN
|
65
|
-
RAISE EXCEPTION 'pg_migrate: code=missing_migration, migration=%, ordinal=%, last_ordinal=%', migration, ordinal, (SELECT MAX(p.ordinal) FROM pg_migrations as p);
|
77
|
+
IF coalesce((SELECT MAX(p.ordinal) FROM pgmigrate.pg_migrations as p), -1) <> ordinal - 1 THEN
|
78
|
+
RAISE EXCEPTION 'pg_migrate: code=missing_migration, migration=%, ordinal=%, last_ordinal=%', migration, ordinal, (SELECT MAX(p.ordinal) FROM pgmigrate.pg_migrations as p);
|
66
79
|
END IF;
|
67
80
|
|
68
81
|
RETURN;
|
@@ -83,12 +96,12 @@ $$ LANGUAGE plpgsql;
|
|
83
96
|
-- checks if the current script has been executed or not, and throws an exception if so
|
84
97
|
-- callers should check for 'pg_migrate: code=migration_exists' to know whether they should quietly ignore exception.
|
85
98
|
-- psql can only do this by calling \set ON_ERROR_STOP 1 (which is done by templates already)
|
86
|
-
CREATE OR REPLACE FUNCTION bypass_existing_migration(migration varchar(255)) RETURNS VOID AS $$
|
99
|
+
CREATE OR REPLACE FUNCTION pgmigrate.bypass_existing_migration(migration varchar(255)) RETURNS VOID AS $$
|
87
100
|
DECLARE
|
88
|
-
found_migration pg_migrations;
|
101
|
+
found_migration pgmigrate.pg_migrations;
|
89
102
|
BEGIN
|
90
103
|
BEGIN
|
91
|
-
EXECUTE 'SELECT * FROM pg_migrations WHERE name=$1' INTO STRICT found_migration USING migration ;
|
104
|
+
EXECUTE 'SELECT * FROM pgmigrate.pg_migrations WHERE name=$1' INTO STRICT found_migration USING migration ;
|
92
105
|
EXCEPTION
|
93
106
|
WHEN NO_DATA_FOUND THEN
|
94
107
|
-- if no data, then success. just return with no exception thrown
|
@@ -103,8 +116,25 @@ END;
|
|
103
116
|
$$ LANGUAGE plpgsql;
|
104
117
|
|
105
118
|
|
119
|
+
-- used to verify that the migration being applied is the same as this set or newer. While the parameter
|
120
|
+
-- today is called 'manifest_version', in reality this is just the highest ordinal from the manifest.
|
121
|
+
-- so if we find that the database has a higher ordinal than the manifest that built this migration,
|
122
|
+
-- then we can kick this out
|
123
|
+
CREATE OR REPLACE FUNCTION pgmigrate.verify_manifest_is_not_old(manifest_version INTEGER) RETURNS VOID AS $$
|
124
|
+
DECLARE
|
125
|
+
max_ordinal INTEGER;
|
126
|
+
BEGIN
|
127
|
+
EXECUTE 'SELECT max(ordinal) FROM pgmigrate.pg_migrations' INTO max_ordinal;
|
128
|
+
|
129
|
+
IF max_ordinal > manifest_version THEN
|
130
|
+
RAISE EXCEPTION 'pg_migrate: code=old_manifest, max_ordinal_in_db=%, manifest_version=%', max_ordinal, manifest_version;
|
131
|
+
END IF;
|
132
|
+
END;
|
133
|
+
$$ LANGUAGE plpgsql;
|
134
|
+
|
135
|
+
|
106
136
|
-- used to mark a migration as finished
|
107
|
-
CREATE OR REPLACE FUNCTION record_migration(migration varchar(255), ordinal INTEGER, template_version VARCHAR(255), builder_version VARCHAR(255)) RETURNS VOID AS $$
|
137
|
+
CREATE OR REPLACE FUNCTION pgmigrate.record_migration(migration varchar(255), ordinal INTEGER, template_version VARCHAR(255), builder_version VARCHAR(255)) RETURNS VOID AS $$
|
108
138
|
DECLARE
|
109
139
|
found_pg_migrate_id BIGINT;
|
110
140
|
migrator_version VARCHAR(255);
|
@@ -116,7 +146,7 @@ BEGIN
|
|
116
146
|
-- first look for existing pg_migrate row satisfying version columns
|
117
147
|
-- but if not found, create that row
|
118
148
|
-- in either case, found_pg_migrate_id will have the row id
|
119
|
-
EXECUTE 'SELECT id FROM pg_migrate WHERE
|
149
|
+
EXECUTE 'SELECT id FROM pgmigrate.pg_migrate WHERE
|
120
150
|
template_version=$1 and builder_version=$2 and migrator_version=$3 and database_version=$4'
|
121
151
|
INTO found_pg_migrate_id USING template_version, builder_version, migrator_version, (select version());
|
122
152
|
EXCEPTION
|
@@ -128,12 +158,12 @@ BEGIN
|
|
128
158
|
END;
|
129
159
|
|
130
160
|
IF found_pg_migrate_id IS NULL THEN
|
131
|
-
INSERT INTO pg_migrate(id, template_version, builder_version, migrator_version, database_version)
|
161
|
+
INSERT INTO pgmigrate.pg_migrate(id, template_version, builder_version, migrator_version, database_version)
|
132
162
|
VALUES (default, template_version, builder_version, migrator_version, (select version())) RETURNING id INTO found_pg_migrate_id;
|
133
163
|
END IF;
|
134
164
|
|
135
165
|
-- create a new record in pg_migrations table, ensuring this migration won't be run again
|
136
|
-
EXECUTE 'INSERT INTO pg_migrations(name, ordinal, created, finalized, pg_migrate_id)
|
166
|
+
EXECUTE 'INSERT INTO pgmigrate.pg_migrations(name, ordinal, created, finalized, pg_migrate_id)
|
137
167
|
VALUES ($1, $2, CURRENT_TIMESTAMP, 1, $3)' USING migration, ordinal, found_pg_migrate_id;
|
138
168
|
|
139
169
|
END;
|
@@ -4,14 +4,16 @@
|
|
4
4
|
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
5
5
|
|
6
6
|
-- we want to ensure no one else is running this migration concurrently
|
7
|
-
LOCK TABLE pg_migrations IN ACCESS EXCLUSIVE MODE;
|
7
|
+
LOCK TABLE pgmigrate.pg_migrations IN ACCESS EXCLUSIVE MODE;
|
8
8
|
|
9
|
-
SELECT
|
9
|
+
SELECT pgmigrate.verify_manifest_is_not_old(<%= manifest_version %>);
|
10
|
+
|
11
|
+
SELECT pgmigrate.verify_against_existing_migrations('<%= migration_def.name %>', <%= migration_def.ordinal %>);
|
10
12
|
|
11
13
|
-- to allow exception in CHECK_IF_MIGRATED to cause rollback, not failure
|
12
14
|
\set ON_ERROR_STOP 0
|
13
15
|
|
14
|
-
SELECT bypass_existing_migration('<%= migration_def.name %>');
|
16
|
+
SELECT pgmigrate.bypass_existing_migration('<%= migration_def.name %>');
|
15
17
|
|
16
18
|
-- if the content of the migration is bad, we want psql to stop.
|
17
19
|
\set ON_ERROR_STOP 1
|
@@ -22,7 +24,7 @@ SELECT bypass_existing_migration('<%= migration_def.name %>');
|
|
22
24
|
|
23
25
|
-- beginning pg_migrate footer, migration=<%= migration_def.name %>
|
24
26
|
|
25
|
-
SELECT record_migration('<%= migration_def.name %>', <%= migration_def.ordinal %>, '0.0
|
27
|
+
SELECT pgmigrate.record_migration('<%= migration_def.name %>', <%= migration_def.ordinal %>, '0.1.0', '<%= builder_version %>');
|
26
28
|
|
27
29
|
COMMIT;
|
28
30
|
-- end pg_migrate migration, migration=<%= migration_def.name %>
|
data/lib/pg_migrate/version.rb
CHANGED
data/lib/pg_migrate.rb
CHANGED
@@ -2,12 +2,14 @@ require 'logging'
|
|
2
2
|
require 'pg'
|
3
3
|
require 'thor'
|
4
4
|
require "pg_migrate/version"
|
5
|
+
require "pg_migrate/props"
|
5
6
|
require "pg_migrate/migration"
|
6
7
|
require "pg_migrate/sql_reader"
|
7
8
|
require "pg_migrate/manifest_reader"
|
8
9
|
require "pg_migrate/migrator"
|
9
10
|
require "pg_migrate/config_parser"
|
10
11
|
require "pg_migrate/builder"
|
12
|
+
require "pg_migrate/package"
|
11
13
|
require "pg_migrate/command_line"
|
12
14
|
|
13
15
|
# name of the manifest file
|
@@ -21,7 +23,9 @@ TESTDIRNAME = 'test'
|
|
21
23
|
# name of the bootstrap.sql file
|
22
24
|
BOOTSTRAP_FILENAME = "bootstrap.sql"
|
23
25
|
# built manifest version header
|
24
|
-
BUILDER_VERSION_HEADER="# pg_migrate-"
|
26
|
+
BUILDER_VERSION_HEADER ="# pg_migrate-"
|
27
|
+
# name of project configuration defaults
|
28
|
+
PG_CONFIG ='.pg_migrate'
|
25
29
|
|
26
30
|
|
27
31
|
### SQL CONSTANTS ###
|
data/pg_migrate.gemspec
CHANGED
@@ -12,7 +12,6 @@ Gem::Specification.new do |gem|
|
|
12
12
|
|
13
13
|
gem.files = `git ls-files`.split($\)
|
14
14
|
gem.files += `cd #{lib}/pg_migrate/templates; git ls-files *.erb`.split($\).map {|f| "lib/pg_migrate/templates/#{f}"}
|
15
|
-
puts gem.files
|
16
15
|
gem.files.delete("lib/pg_migrate/templates")
|
17
16
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
18
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
@@ -24,5 +23,6 @@ Gem::Specification.new do |gem|
|
|
24
23
|
|
25
24
|
gem.add_dependency('pg', '0.14.0')
|
26
25
|
gem.add_dependency('thor', '0.15.4')
|
26
|
+
#gem.add_dependency('rubygems', '1.8.24')
|
27
27
|
end
|
28
28
|
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CommandLine do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
@dbutil = DbUtility.new
|
7
|
+
end
|
8
|
+
|
9
|
+
|
10
|
+
it "build using config file" do
|
11
|
+
|
12
|
+
single_manifest=File.expand_path('spec/pg_migrate/input_manifests/single_manifest')
|
13
|
+
single_manifest=File.join(single_manifest, '.')
|
14
|
+
|
15
|
+
input_dir = nil
|
16
|
+
target = Files.create :path => "target", :timestamp => false do
|
17
|
+
input_dir = dir "input_single_manifest", :src => single_manifest do
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
output_dir = File.join("target", 'output_single_manifest')
|
23
|
+
|
24
|
+
FileUtils.rm_rf(output_dir)
|
25
|
+
|
26
|
+
# make a properties file on the fly, with the out parameter specified
|
27
|
+
props = Properties.new
|
28
|
+
props['build.out'] = output_dir
|
29
|
+
props['build.force'] = "true"
|
30
|
+
#props['up.connopts'] = "dbname:pg_migrate_test host:localhost port:5432 user:postgres password:postgres"
|
31
|
+
|
32
|
+
# and put that properties file in the input dir
|
33
|
+
File.open(File.join(input_dir, PG_CONFIG), 'w') { |f| f.write(props) }
|
34
|
+
|
35
|
+
# invoke pg_migrate build, with the hopes that the output dir is honored
|
36
|
+
result = `bundle exec pg_migrate build -s #{input_dir}`
|
37
|
+
|
38
|
+
puts "pg_migrate build output: #{result}"
|
39
|
+
|
40
|
+
$?.exitstatus.should == 0
|
41
|
+
|
42
|
+
FileTest::exist?(output_dir).should == true
|
43
|
+
FileTest::exist?(File.join(output_dir, MANIFEST_FILENAME)).should == true
|
44
|
+
FileTest::exist?(File.join(output_dir, PG_CONFIG)).should == true
|
45
|
+
FileTest::exist?(File.join(output_dir, UP_DIRNAME)).should == true
|
46
|
+
FileTest::exist?(File.join(output_dir, UP_DIRNAME, BOOTSTRAP_FILENAME)).should == true
|
47
|
+
FileTest::exist?(File.join(output_dir, UP_DIRNAME, "single1.sql")).should == true
|
48
|
+
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
end
|
@@ -25,7 +25,7 @@ describe Migrator do
|
|
25
25
|
end
|
26
26
|
|
27
27
|
pg_migration_id = nil
|
28
|
-
transaction.exec("SELECT * FROM pg_migrations") do |result|
|
28
|
+
transaction.exec("SELECT * FROM pgmigrate.pg_migrations") do |result|
|
29
29
|
result.ntuples.should == 1
|
30
30
|
result[0]["name"].should == "single1.sql"
|
31
31
|
result[0]["ordinal"].should == "0"
|
@@ -34,9 +34,9 @@ describe Migrator do
|
|
34
34
|
pg_migration_id.should_not == nil
|
35
35
|
|
36
36
|
# verify that a database row in pg_migrate was created as side-effect
|
37
|
-
transaction.exec("SELECT * FROM pg_migrate WHERE id = $1", [pg_migration_id]) do |result|
|
37
|
+
transaction.exec("SELECT * FROM pgmigrate.pg_migrate WHERE id = $1", [pg_migration_id]) do |result|
|
38
38
|
result.ntuples.should == 1
|
39
|
-
result[0]["template_version"].should == "0.0
|
39
|
+
result[0]["template_version"].should == "0.1.0"
|
40
40
|
result[0]["builder_version"].should == "pg_migrate_ruby-#{PgMigrate::VERSION}"
|
41
41
|
result[0]["migrator_version"].should == "pg_migrate_ruby-#{PgMigrate::VERSION}"
|
42
42
|
result[0]["database_version"].should_not be nil
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Package do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
@manifest_reader = ManifestReader.new
|
7
|
+
@sql_reader = SqlReader.new
|
8
|
+
@builder = Builder.new(@manifest_reader, @sql_reader)
|
9
|
+
@packager = Package.new(@manifest_reader)
|
10
|
+
@dbutil = DbUtility.new
|
11
|
+
end
|
12
|
+
|
13
|
+
it "package single migration project" do
|
14
|
+
single_manifest=File.expand_path('spec/pg_migrate/input_manifests/single_manifest')
|
15
|
+
single_manifest = File.join(single_manifest, '.')
|
16
|
+
|
17
|
+
input_dir = nil
|
18
|
+
target = Files.create :path => "target", :timestamp => false do
|
19
|
+
input_dir = dir "input_single_manifest", :src => single_manifest do
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
build_output_dir = File.join('target', 'output_single_manifest')
|
25
|
+
package_output_dir = File.join('target', 'package_single_manifest')
|
26
|
+
|
27
|
+
FileUtils.rm_rf(build_output_dir)
|
28
|
+
|
29
|
+
|
30
|
+
# build first
|
31
|
+
@builder.build(input_dir, build_output_dir)
|
32
|
+
|
33
|
+
# then attempt a package
|
34
|
+
@packager.package(build_output_dir, package_output_dir, "crazy_gem", "0.0.1")
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pg_migrate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-07-
|
12
|
+
date: 2012-07-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: logging
|
@@ -82,17 +82,26 @@ files:
|
|
82
82
|
- lib/pg_migrate/manifest_reader.rb
|
83
83
|
- lib/pg_migrate/migration.rb
|
84
84
|
- lib/pg_migrate/migrator.rb
|
85
|
+
- lib/pg_migrate/package.rb
|
86
|
+
- lib/pg_migrate/package_templates/Gemfile.erb
|
87
|
+
- lib/pg_migrate/package_templates/bin/migrate.rb
|
88
|
+
- lib/pg_migrate/package_templates/gemspec.erb
|
89
|
+
- lib/pg_migrate/package_templates/lib/gem.rb
|
90
|
+
- lib/pg_migrate/package_templates/lib/gem/version.rb
|
91
|
+
- lib/pg_migrate/props.rb
|
85
92
|
- lib/pg_migrate/sql_reader.rb
|
86
93
|
- lib/pg_migrate/version.rb
|
87
94
|
- pg_migrate.gemspec
|
88
95
|
- spec/database.yml
|
89
96
|
- spec/pg_migrate/builder_spec.rb
|
97
|
+
- spec/pg_migrate/command_line_spec.rb
|
90
98
|
- spec/pg_migrate/config_parser_spec.rb
|
91
99
|
- spec/pg_migrate/db_utility.rb
|
92
100
|
- spec/pg_migrate/input_manifests/single_manifest/manifest
|
93
101
|
- spec/pg_migrate/input_manifests/single_manifest/up/single1.sql
|
94
102
|
- spec/pg_migrate/manifest_reader_spec.rb
|
95
103
|
- spec/pg_migrate/migrator_spec.rb
|
104
|
+
- spec/pg_migrate/package_spec.rb
|
96
105
|
- spec/pg_migrate/sql_reader_spec.rb
|
97
106
|
- spec/spec_helper.rb
|
98
107
|
- lib/pg_migrate/templates/bootstrap.erb
|
@@ -126,11 +135,13 @@ summary: Create migration scripts in raw SQL that work regardless if they are ru
|
|
126
135
|
test_files:
|
127
136
|
- spec/database.yml
|
128
137
|
- spec/pg_migrate/builder_spec.rb
|
138
|
+
- spec/pg_migrate/command_line_spec.rb
|
129
139
|
- spec/pg_migrate/config_parser_spec.rb
|
130
140
|
- spec/pg_migrate/db_utility.rb
|
131
141
|
- spec/pg_migrate/input_manifests/single_manifest/manifest
|
132
142
|
- spec/pg_migrate/input_manifests/single_manifest/up/single1.sql
|
133
143
|
- spec/pg_migrate/manifest_reader_spec.rb
|
134
144
|
- spec/pg_migrate/migrator_spec.rb
|
145
|
+
- spec/pg_migrate/package_spec.rb
|
135
146
|
- spec/pg_migrate/sql_reader_spec.rb
|
136
147
|
- spec/spec_helper.rb
|