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 CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pg_migrate (0.0.1)
4
+ pg_migrate (0.1.0)
5
5
  logging (= 1.7.2)
6
6
  pg (= 0.14.0)
7
7
  thor (= 0.15.4)
@@ -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 create_output_dir=true"
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
- builder_version="pg_migrate_ruby-#{PgMigrate::VERSION}"
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 => '.', :lazy_default => '.', :banner => 'input directory', :desc => "a pg_migrate built manifest. Should contain your processed manifest and up|down|test folders"
6
- method_option :connopts, :aliases => "-o", :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"
7
- method_option :verbose, :aliases => "-v", :type => :boolean, :default => false, :banner => "verbose", :desc=> "set to raise verbosity"
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
- bootstrap_logger(options[:verbose])
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 = options[:connopts]
16
- if !connopts[:port].nil?
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(options[:source])
48
+ migrator.migrate(source)
24
49
  rescue Exception => e
25
- if !options[:verbose]
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 '#{options[:source]}' . Check -s|--source option and run again."
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 => '.', :lazy_default => '.', :banner => 'input directory', :desc => "the input directory containing a manifest file and up|down|test folders"
51
- method_option :out, :aliases => "-o", :required => true, :banner => "output directory", :desc => "where the processed migrations will be placed"
52
- method_option :force, :aliases => "-f", :default => false, :type => :boolean, :banner => "overwrite out", :desc => "if specified, the out directory will be created before processing occurs, replacing any existing directory"
53
- method_option :verbose, :aliases => "-v", :type => :boolean, :default => false, :banner => "verbose", :desc=> "set to raise verbosity"
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
- bootstrap_logger(options[:verbose])
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(options[:source], options[:out], :force => options[:force])
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 #{manifest_path}"
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 #{manifest_path}"
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: '#{manifest_path}'"
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 manifest #{migration_name} with ordinal #{ordinal}"
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
@@ -1,6 +1,6 @@
1
1
  module PgMigrate
2
2
  class Migration
3
- attr_accessor :name, :ordinal, :md5, :created, :production, :filepath
3
+ attr_accessor :name, :ordinal, :created, :production, :filepath
4
4
 
5
5
  def initialize(name, ordinal, filepath)
6
6
  @name = name
@@ -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 #{migration_path}'
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 occured, and we should just treat it like a continue
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,4 @@
1
+ # A sample Gemfile
2
+ source "https://rubygems.org"
3
+
4
+ gemspec
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pg_migrate'
4
+ require '<%= name %>'
5
+
6
+ include PgMigrate
7
+
8
+ CommandLine.packaged_source = File.expand_path('../../lib/<%= name %>/schemas', __FILE__)
9
+
10
+ CommandLine.start
@@ -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,3 @@
1
+ module <%= constant_name %>
2
+ VERSION = "<%= version %>"
3
+ 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
- if current_statement =~ /(plpgsql|plperl|plpythonu|pltcl|sql)\s*;$/i
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
- CREATE OR REPLACE FUNCTION bootstrap_pg_migrate() RETURNS void AS $$
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 verify_against_existing_migrations('<%= migration_def.name %>', <%= migration_def.ordinal %>);
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.1', '<%= builder_version %>');
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 %>
@@ -1,3 +1,3 @@
1
1
  module PgMigrate
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
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
 
@@ -71,6 +71,8 @@ describe Builder do
71
71
 
72
72
  output_dir = File.join('target', 'output_single_manifest')
73
73
 
74
+ FileUtils.rm_rf(output_dir)
75
+
74
76
  @standard_builder.build(input_dir, output_dir)
75
77
 
76
78
  @dbutil.create_new_test_database()
@@ -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.1"
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.1
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-19 00:00:00.000000000 Z
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