pg_migrate 0.0.1 → 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.
- 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
|