pg_migrate 0.1.7 → 0.1.11

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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +34 -34
  3. data/.gitmodules +3 -3
  4. data/Gemfile +9 -9
  5. data/Gemfile.lock +39 -39
  6. data/LICENSE +21 -21
  7. data/README.md +33 -33
  8. data/Rakefile +2 -2
  9. data/bin/pg_migrate +6 -6
  10. data/lib/pg_migrate/builder.rb +214 -214
  11. data/lib/pg_migrate/command_line.rb +242 -242
  12. data/lib/pg_migrate/config_parser.rb +48 -48
  13. data/lib/pg_migrate/manifest_reader.rb +102 -102
  14. data/lib/pg_migrate/migration.rb +11 -11
  15. data/lib/pg_migrate/migrator.rb +94 -94
  16. data/lib/pg_migrate/package.rb +152 -152
  17. data/lib/pg_migrate/package_templates/Gemfile.erb +3 -3
  18. data/lib/pg_migrate/package_templates/bin/migrate.rb +9 -9
  19. data/lib/pg_migrate/package_templates/gemspec.erb +21 -21
  20. data/lib/pg_migrate/package_templates/lib/gem/version.rb +3 -3
  21. data/lib/pg_migrate/package_templates/lib/gem.rb +12 -12
  22. data/lib/pg_migrate/props.rb +19 -19
  23. data/lib/pg_migrate/sql_reader.rb +51 -51
  24. data/lib/pg_migrate/templates/bootstrap.erb +175 -175
  25. data/lib/pg_migrate/templates/up.erb +30 -30
  26. data/lib/pg_migrate/util.rb +73 -73
  27. data/lib/pg_migrate/version.rb +3 -3
  28. data/lib/pg_migrate.rb +40 -40
  29. data/pg_migrate.gemspec +29 -28
  30. data/spec/database.yml +8 -8
  31. data/spec/pg_migrate/builder_spec.rb +113 -113
  32. data/spec/pg_migrate/command_line_spec.rb +53 -53
  33. data/spec/pg_migrate/config_parser_spec.rb +18 -18
  34. data/spec/pg_migrate/db_utility.rb +73 -73
  35. data/spec/pg_migrate/input_manifests/single_manifest/manifest +3 -3
  36. data/spec/pg_migrate/input_manifests/single_manifest/up/single1.sql +29 -29
  37. data/spec/pg_migrate/manifest_reader_spec.rb +19 -19
  38. data/spec/pg_migrate/migrator_spec.rb +68 -68
  39. data/spec/pg_migrate/package_spec.rb +38 -38
  40. data/spec/pg_migrate/sql_reader_spec.rb +21 -21
  41. data/spec/spec_helper.rb +15 -15
  42. metadata +5 -5
@@ -1,103 +1,103 @@
1
- require 'pathname'
2
-
3
- module PgMigrate
4
- class ManifestReader
5
-
6
- def initialize
7
- @log = Logging.logger[self]
8
- end
9
-
10
- # returns array of migration paths
11
- def load_input_manifest(manifest_path)
12
- manifest, version = load_manifest(manifest_path, false)
13
- return manifest
14
- end
15
-
16
- # returns [array of migration paths, version]
17
- def load_output_manifest(manifest_path)
18
- return load_manifest(manifest_path, true)
19
- end
20
-
21
-
22
- # verify that the migration files exist
23
- def validate_migration_paths(manifest_path, manifest)
24
- # each item in the manifest should be a valid file
25
- manifest.each do |item|
26
- item_path = build_migration_path(manifest_path, item.name)
27
- if !Pathname.new(item_path).exist?
28
- raise "manifest reference #{item.name} does not exist at path #{item_path}"
29
- end
30
- end
31
- end
32
-
33
- # construct a migration file path location based on the manifest basedir and the name of the migration
34
- def build_migration_path(manifest_path, migration_name)
35
- File.join(manifest_path, UP_DIRNAME, "#{migration_name}")
36
- end
37
-
38
- def hash_loaded_manifest(loaded_manifest)
39
- hash = {}
40
- loaded_manifest.each do |manifest|
41
- hash[manifest.name] = manifest
42
- end
43
- return hash
44
- end
45
-
46
- # read in the manifest, saving each migration declaration in order as they are found
47
- private
48
- def load_manifest(manifest_path, is_output)
49
-
50
- manifest = []
51
- version = nil
52
-
53
- manifest_filepath = File.join(manifest_path, MANIFEST_FILENAME)
54
-
55
- @log.debug "loading manifest from #{manifest_filepath}"
56
-
57
- # there should be a file called 'manifest' at this location
58
- if !FileTest::exist?(manifest_filepath)
59
- raise "ManifestReader: code=unloadable_manifest: manifest not found at #{manifest_filepath}"
60
- end
61
-
62
- manifest_lines = IO.readlines(manifest_filepath)
63
-
64
- ordinal = 0
65
- manifest_lines.each_with_index do |line, index|
66
- migration_name = line.strip
67
-
68
- @log.debug "processing line:#{index} #{line}"
69
-
70
- # output files must have a version header as 1st line o file
71
- if is_output
72
- if index == 0
73
- # the first line must be the version comment. if not, error out.
74
- if migration_name.index(BUILDER_VERSION_HEADER) == 0 && migration_name.length > BUILDER_VERSION_HEADER.length
75
- version = migration_name[BUILDER_VERSION_HEADER.length..-1]
76
- @log.debug "manifest has builder_version #{version}"
77
- else
78
- raise "manifest invalid: missing/malformed version. expecting '# pg_migrate-VERSION' to begin first line '#{line}' of manifest file: '#{manifest_filepath}'"
79
- end
80
- end
81
- end
82
-
83
- # ignore comments
84
- if migration_name.empty? or migration_name.start_with?('#')
85
- # ignored!
86
- else
87
- @log.debug "adding migration #{migration_name} with ordinal #{ordinal}"
88
- manifest.push(Migration.new(migration_name, ordinal, build_migration_path(manifest_path, migration_name)))
89
- ordinal += 1
90
- end
91
-
92
- # the logic above wouldn't get upset with an empty manifest
93
- if is_output
94
- if version.nil?
95
- raise "manifest invalid: empty"
96
- end
97
- end
98
- end
99
- return manifest, version
100
- end
101
-
102
- end
1
+ require 'pathname'
2
+
3
+ module PgMigrate
4
+ class ManifestReader
5
+
6
+ def initialize
7
+ @log = Logging.logger[self]
8
+ end
9
+
10
+ # returns array of migration paths
11
+ def load_input_manifest(manifest_path)
12
+ manifest, version = load_manifest(manifest_path, false)
13
+ return manifest
14
+ end
15
+
16
+ # returns [array of migration paths, version]
17
+ def load_output_manifest(manifest_path)
18
+ return load_manifest(manifest_path, true)
19
+ end
20
+
21
+
22
+ # verify that the migration files exist
23
+ def validate_migration_paths(manifest_path, manifest)
24
+ # each item in the manifest should be a valid file
25
+ manifest.each do |item|
26
+ item_path = build_migration_path(manifest_path, item.name)
27
+ if !Pathname.new(item_path).exist?
28
+ raise "manifest reference #{item.name} does not exist at path #{item_path}"
29
+ end
30
+ end
31
+ end
32
+
33
+ # construct a migration file path location based on the manifest basedir and the name of the migration
34
+ def build_migration_path(manifest_path, migration_name)
35
+ File.join(manifest_path, UP_DIRNAME, "#{migration_name}")
36
+ end
37
+
38
+ def hash_loaded_manifest(loaded_manifest)
39
+ hash = {}
40
+ loaded_manifest.each do |manifest|
41
+ hash[manifest.name] = manifest
42
+ end
43
+ return hash
44
+ end
45
+
46
+ # read in the manifest, saving each migration declaration in order as they are found
47
+ private
48
+ def load_manifest(manifest_path, is_output)
49
+
50
+ manifest = []
51
+ version = nil
52
+
53
+ manifest_filepath = File.join(manifest_path, MANIFEST_FILENAME)
54
+
55
+ @log.debug "loading manifest from #{manifest_filepath}"
56
+
57
+ # there should be a file called 'manifest' at this location
58
+ if !FileTest::exist?(manifest_filepath)
59
+ raise "ManifestReader: code=unloadable_manifest: manifest not found at #{manifest_filepath}"
60
+ end
61
+
62
+ manifest_lines = IO.readlines(manifest_filepath)
63
+
64
+ ordinal = 0
65
+ manifest_lines.each_with_index do |line, index|
66
+ migration_name = line.strip
67
+
68
+ @log.debug "processing line:#{index} #{line}"
69
+
70
+ # output files must have a version header as 1st line o file
71
+ if is_output
72
+ if index == 0
73
+ # the first line must be the version comment. if not, error out.
74
+ if migration_name.index(BUILDER_VERSION_HEADER) == 0 && migration_name.length > BUILDER_VERSION_HEADER.length
75
+ version = migration_name[BUILDER_VERSION_HEADER.length..-1]
76
+ @log.debug "manifest has builder_version #{version}"
77
+ else
78
+ raise "manifest invalid: missing/malformed version. expecting '# pg_migrate-VERSION' to begin first line '#{line}' of manifest file: '#{manifest_filepath}'"
79
+ end
80
+ end
81
+ end
82
+
83
+ # ignore comments
84
+ if migration_name.empty? or migration_name.start_with?('#')
85
+ # ignored!
86
+ else
87
+ @log.debug "adding migration #{migration_name} with ordinal #{ordinal}"
88
+ manifest.push(Migration.new(migration_name, ordinal, build_migration_path(manifest_path, migration_name)))
89
+ ordinal += 1
90
+ end
91
+
92
+ # the logic above wouldn't get upset with an empty manifest
93
+ if is_output
94
+ if version.nil?
95
+ raise "manifest invalid: empty"
96
+ end
97
+ end
98
+ end
99
+ return manifest, version
100
+ end
101
+
102
+ end
103
103
  end
@@ -1,12 +1,12 @@
1
- module PgMigrate
2
- class Migration
3
- attr_accessor :name, :ordinal, :created, :production, :filepath
4
-
5
- def initialize(name, ordinal, filepath)
6
- @name = name
7
- @ordinal = ordinal
8
- @filepath = filepath
9
- end
10
-
11
- end
1
+ module PgMigrate
2
+ class Migration
3
+ attr_accessor :name, :ordinal, :created, :production, :filepath
4
+
5
+ def initialize(name, ordinal, filepath)
6
+ @name = name
7
+ @ordinal = ordinal
8
+ @filepath = filepath
9
+ end
10
+
11
+ end
12
12
  end
@@ -1,94 +1,94 @@
1
- module PgMigrate
2
-
3
- class Migrator
4
-
5
- attr_accessor :conn, :connection_hash, :manifest_path, :manifest, :manifest_reader, :sql_reader
6
-
7
- # options = gem 'pg' connection_hash options, or connstring => dbname=test port=5432, or pgconn => PG::Connection object
8
- def initialize(manifest_reader, sql_reader, options = {})
9
- @log = Logging.logger[self]
10
- @connection_hash = options
11
- @manifest = nil
12
- @builder_version = nil
13
- @manifest_reader = manifest_reader
14
- @sql_reader = sql_reader
15
- end
16
-
17
- # 'migrate' attempt to migrate your database based on the contents of your built manifest
18
- # The manifest_path argument should point to your manifest
19
- # manifest_path = the directory containing your 'manifest' file, 'up' directory, 'down' directory, 'test' directory
20
- # this method will throw an exception if anything goes wrong (such as bad SQL in the migrations themselves)
21
- def migrate(manifest_path)
22
- @manifest_path = manifest_path
23
-
24
- @conn = Util::get_conn(@connection_hash)
25
-
26
- # this is used to record the version of the 'migrator' in the pg_migrate table
27
- @conn.exec("SET application_name = 'pg_migrate_ruby-#{PgMigrate::VERSION}'")
28
-
29
- # load the manifest, and version of the builder that made it
30
- process_manifest()
31
-
32
- # execute the migrations
33
- run_migrations(@manifest)
34
- end
35
-
36
-
37
- # load the manifest's migration declarations, and validate that each migration points to a real file
38
- def process_manifest
39
- @manifest, @builder_version = @manifest_reader.load_output_manifest(@manifest_path)
40
- @manifest_reader.validate_migration_paths(@manifest_path, @manifest)
41
- end
42
-
43
- # run all necessary migrations
44
- def run_migrations(manifest)
45
-
46
- # run bootstrap before user migrations to prepare database
47
- run_bootstrap
48
-
49
- # loop through the manifest, executing migrations in turn
50
- manifest.each_with_index do |migration, index|
51
- execute_migration(migration.name, migration.filepath)
52
- end
53
-
54
- end
55
-
56
- # executes the bootstrap method
57
- def run_bootstrap
58
- bootstrap = File.join(@manifest_path, UP_DIRNAME, BOOTSTRAP_FILENAME)
59
- execute_migration('bootstrap.sql', bootstrap)
60
- end
61
-
62
- # execute a single migration by loading it's statements from file, and then executing each
63
- def execute_migration(name, filepath)
64
- @log.info "executing migration #{filepath}"
65
-
66
- statements = @sql_reader.load_migration(filepath)
67
- if statements.length == 0
68
- raise 'no statements found in migration #{filepath}'
69
- end
70
- run_migration(name, statements)
71
- end
72
-
73
- # execute all the statements of a single migration
74
- def run_migration(name, statements)
75
-
76
- begin
77
- statements.each do |statement|
78
- conn.exec(statement).clear
79
- end
80
- rescue Exception => e
81
- # we make a special allowance for one exception; it just means this migration
82
- # has already occurred, and we should just treat it like a continue
83
- if e.message.index('pg_migrate: code=migration_exists').nil?
84
- conn.exec("ROLLBACK")
85
- raise e
86
- else
87
- conn.exec("ROLLBACK")
88
- @log.info "migration #{name} already run"
89
- end
90
- end
91
- end
92
- end
93
- end
94
-
1
+ module PgMigrate
2
+
3
+ class Migrator
4
+
5
+ attr_accessor :conn, :connection_hash, :manifest_path, :manifest, :manifest_reader, :sql_reader
6
+
7
+ # options = gem 'pg' connection_hash options, or connstring => dbname=test port=5432, or pgconn => PG::Connection object
8
+ def initialize(manifest_reader, sql_reader, options = {})
9
+ @log = Logging.logger[self]
10
+ @connection_hash = options
11
+ @manifest = nil
12
+ @builder_version = nil
13
+ @manifest_reader = manifest_reader
14
+ @sql_reader = sql_reader
15
+ end
16
+
17
+ # 'migrate' attempt to migrate your database based on the contents of your built manifest
18
+ # The manifest_path argument should point to your manifest
19
+ # manifest_path = the directory containing your 'manifest' file, 'up' directory, 'down' directory, 'test' directory
20
+ # this method will throw an exception if anything goes wrong (such as bad SQL in the migrations themselves)
21
+ def migrate(manifest_path)
22
+ @manifest_path = manifest_path
23
+
24
+ @conn = Util::get_conn(@connection_hash)
25
+
26
+ # this is used to record the version of the 'migrator' in the pg_migrate table
27
+ @conn.exec("SET application_name = 'pg_migrate_ruby-#{PgMigrate::VERSION}'")
28
+
29
+ # load the manifest, and version of the builder that made it
30
+ process_manifest()
31
+
32
+ # execute the migrations
33
+ run_migrations(@manifest)
34
+ end
35
+
36
+
37
+ # load the manifest's migration declarations, and validate that each migration points to a real file
38
+ def process_manifest
39
+ @manifest, @builder_version = @manifest_reader.load_output_manifest(@manifest_path)
40
+ @manifest_reader.validate_migration_paths(@manifest_path, @manifest)
41
+ end
42
+
43
+ # run all necessary migrations
44
+ def run_migrations(manifest)
45
+
46
+ # run bootstrap before user migrations to prepare database
47
+ run_bootstrap
48
+
49
+ # loop through the manifest, executing migrations in turn
50
+ manifest.each_with_index do |migration, index|
51
+ execute_migration(migration.name, migration.filepath)
52
+ end
53
+
54
+ end
55
+
56
+ # executes the bootstrap method
57
+ def run_bootstrap
58
+ bootstrap = File.join(@manifest_path, UP_DIRNAME, BOOTSTRAP_FILENAME)
59
+ execute_migration('bootstrap.sql', bootstrap)
60
+ end
61
+
62
+ # execute a single migration by loading it's statements from file, and then executing each
63
+ def execute_migration(name, filepath)
64
+ @log.info "executing migration #{filepath}"
65
+
66
+ statements = @sql_reader.load_migration(filepath)
67
+ if statements.length == 0
68
+ raise 'no statements found in migration #{filepath}'
69
+ end
70
+ run_migration(name, statements)
71
+ end
72
+
73
+ # execute all the statements of a single migration
74
+ def run_migration(name, statements)
75
+
76
+ begin
77
+ statements.each do |statement|
78
+ conn.exec(statement).clear
79
+ end
80
+ rescue Exception => e
81
+ # we make a special allowance for one exception; it just means this migration
82
+ # has already occurred, and we should just treat it like a continue
83
+ if e.message.index('pg_migrate: code=migration_exists').nil?
84
+ conn.exec("ROLLBACK")
85
+ raise e
86
+ else
87
+ conn.exec("ROLLBACK")
88
+ @log.info "migration #{name} already run"
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+