xmigra 1.2.0 → 1.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3e69aae7f431f58d88125bfc0a31adb4a0f3b76c
4
- data.tar.gz: 65f872a4d23fd7515bf6231c636c0f10725effc7
3
+ metadata.gz: 5e70e491aa62e8fdf597baa7794b6c342ebb074d
4
+ data.tar.gz: 6d95f99d62ca23e9fb0f801dc37e0eaca2656cd0
5
5
  SHA512:
6
- metadata.gz: 299d09f45384c3dc16473c59e6d2494583c8486d776a3edef6ab4123e2245374e4cbe13472b73c013f9c82081f44fdef0a242b6048f694d666f2b5102b6a988d
7
- data.tar.gz: 5016ef96078d289add80ec678ca6a5e989fcaac0a9dc4fd30ce186c0fc7e766ab22c00c752f5f62c0c11ccdf6621b808d920709792b2dae8d0df774e3e61c158
6
+ metadata.gz: ddf810521f87c7ecf49c5aef49d8f51ce913c9e7ae6b0bb3ba14395560d965c9ff538ebd80872b97c1870e986f09e7f523e58054caf1b2387b80a44be4558ad5
7
+ data.tar.gz: 54aea5341db82a73aa972f6ad6e27f11a9c24780d5f83bd146f6c4c25b9cc1376aa99081177ddb14310720b0cb68081c1a4fa2d1fd67b91fa1dc961bad43f670
@@ -12,6 +12,8 @@ module XMigra
12
12
  $/ix
13
13
  STATISTICS_FILE = 'statistics-objects.yaml'
14
14
 
15
+ ID_COLLATION = 'Latin1_General_CS_AS'
16
+
15
17
  class StatisticsObject
16
18
  def initialize(name, params)
17
19
  (@name = name.dup).freeze
@@ -153,7 +155,7 @@ IF NOT EXISTS (
153
155
  )
154
156
  BEGIN
155
157
  CREATE TABLE [xmigra].[applied] (
156
- [MigrationID] nvarchar(80) NOT NULL,
158
+ [MigrationID] nvarchar(80) COLLATE #{ID_COLLATION} NOT NULL,
157
159
  [ApplicationOrder] int IDENTITY(1,1) NOT NULL,
158
160
  [VersionBridgeMark] bit NOT NULL,
159
161
  [Description] nvarchar(max) NOT NULL,
@@ -171,6 +173,45 @@ BEGIN
171
173
  END;
172
174
  GO
173
175
 
176
+ IF NOT EXISTS (
177
+ SELECT * FROM sys.columns
178
+ WHERE object_id = OBJECT_ID(N'[xmigra].[applied]')
179
+ AND name = N'MigrationID'
180
+ AND collation_name = N'#{ID_COLLATION}'
181
+ )
182
+ BEGIN
183
+ ALTER TABLE xmigra.applied DROP CONSTRAINT PK_version;
184
+ ALTER TABLE xmigra.applied ALTER COLUMN [MigrationID] nvarchar(80) COLLATE Latin1_General_CS_AS NOT NULL;
185
+ ALTER TABLE xmigra.applied ADD CONSTRAINT PK_version PRIMARY KEY ([MigrationID] ASC) WITH (
186
+ PAD_INDEX = OFF,
187
+ STATISTICS_NORECOMPUTE = OFF,
188
+ IGNORE_DUP_KEY = OFF,
189
+ ALLOW_ROW_LOCKS = ON,
190
+ ALLOW_PAGE_LOCKS = ON
191
+ ) ON [PRIMARY];
192
+ END;
193
+
194
+ IF NOT EXISTS (
195
+ SELECT * FROM sys.objects
196
+ WHERE object_id = OBJECT_ID(N'[xmigra].[previous_states]')
197
+ AND type IN (N'U')
198
+ )
199
+ BEGIN
200
+ CREATE TABLE [xmigra].[previous_states] (
201
+ [Changed] datetime NOT NULL,
202
+ [MigrationApplicationOrder] int NOT NULL,
203
+ [FromMigrationID] nvarchar(80) COLLATE #{ID_COLLATION},
204
+ [ToRangeStartMigrationID] nvarchar(80) COLLATE #{ID_COLLATION} NOT NULL,
205
+ [ToRangeEndMigrationID] nvarchar(80) COLLATE #{ID_COLLATION} NOT NULL,
206
+
207
+ CONSTRAINT [PK_previous_states] PRIMARY KEY CLUSTERED (
208
+ [Changed] ASC,
209
+ [MigrationApplicationOrder] ASC
210
+ )
211
+ );
212
+ END;
213
+ GO
214
+
174
215
  IF NOT EXISTS (
175
216
  SELECT * FROM sys.objects
176
217
  WHERE object_id = OBJECT_ID(N'[xmigra].[DF_version_VersionBridgeMark]')
@@ -244,6 +285,30 @@ BEGIN
244
285
  [CompletesMigration] nvarchar(80) NULL
245
286
  ) ON [PRIMARY];
246
287
  END;
288
+
289
+ IF EXISTS (
290
+ SELECT * FROM sys.objects
291
+ WHERE object_id = OBJECT_ID(N'[xmigra].[last_applied_migrations]')
292
+ AND type IN (N'V')
293
+ )
294
+ BEGIN
295
+ DROP VIEW [xmigra].[last_applied_migrations];
296
+ END;
297
+ GO
298
+
299
+ CREATE VIEW [xmigra].[last_applied_migrations] AS
300
+ SELECT
301
+ ROW_NUMBER() OVER (ORDER BY a.[ApplicationOrder] DESC) AS [RevertOrder],
302
+ a.[Description]
303
+ FROM
304
+ [xmigra].[applied] a
305
+ WHERE
306
+ a.[ApplicationOrder] > COALESCE((
307
+ SELECT TOP (1) ps.[MigrationApplicationOrder]
308
+ FROM [xmigra].[previous_states] ps
309
+ JOIN [xmigra].[applied] a2 ON ps.[ToRangeStartMigrationID] = a2.[MigrationID]
310
+ ORDER BY ps.[Changed] DESC
311
+ ), 0);
247
312
  END_OF_SQL
248
313
  end
249
314
 
@@ -260,7 +325,7 @@ END;
260
325
  GO
261
326
 
262
327
  CREATE TABLE [xmigra].[migrations] (
263
- [MigrationID] nvarchar(80) NOT NULL,
328
+ [MigrationID] nvarchar(80) COLLATE #{ID_COLLATION} NOT NULL,
264
329
  [ApplicationOrder] int NOT NULL,
265
330
  [Description] ntext NOT NULL,
266
331
  [Install] bit NOT NULL DEFAULT(0)
@@ -472,6 +537,38 @@ ELSE BEGIN
472
537
  )
473
538
  AND [ApplicationOrder] > @BridgePoint;
474
539
  END;
540
+
541
+ INSERT INTO [xmigra].[previous_states] (
542
+ [Changed],
543
+ [MigrationApplicationOrder],
544
+ [FromMigrationID],
545
+ [ToRangeStartMigrationID],
546
+ [ToRangeEndMigrationID]
547
+ )
548
+ SELECT TOP (1)
549
+ CURRENT_TIMESTAMP,
550
+ -- Application order of last installed migration --
551
+ COALESCE(
552
+ (
553
+ SELECT TOP(1) [ApplicationOrder] FROM [xmigra].[applied]
554
+ ORDER BY [ApplicationOrder] DESC
555
+ ),
556
+ 0
557
+ ),
558
+ ( -- Last installed migration --
559
+ SELECT TOP (1) [MigrationID]
560
+ FROM [xmigra].[applied]
561
+ ORDER BY [ApplicationOrder] DESC
562
+ ),
563
+ m.[MigrationID],
564
+ ( -- Last migration to install --
565
+ SELECT TOP(1) [MigrationID] FROM [xmigra].[migrations]
566
+ WHERE [Install] <> 0
567
+ ORDER BY [ApplicationOrder] DESC
568
+ )
569
+ FROM [xmigra].[migrations] m
570
+ WHERE m.[Install] <> 0
571
+ ORDER BY m.[ApplicationOrder] ASC;
475
572
  END_OF_SQL
476
573
  end
477
574
 
@@ -885,6 +982,10 @@ END;
885
982
  end.join("\n"))
886
983
  end
887
984
 
985
+ def reversion_tracking_sql
986
+ "DELETE FROM [xmigra].[applied] WHERE [MigrationID] = '#{id}';\n"
987
+ end
988
+
888
989
  def each_batch(sql)
889
990
  current_batch_lines = []
890
991
  sql.each_line do |line|
@@ -111,6 +111,24 @@ module XMigra
111
111
  );
112
112
  END IF;
113
113
 
114
+ IF NOT EXISTS(
115
+ SELECT * FROM information_schema.tables
116
+ WHERE table_schema = 'xmigra' AND table_name = 'previous_states'
117
+ ) THEN
118
+ CREATE TABLE xmigra.previous_states (
119
+ "Changed" timestamp NOT NULL,
120
+ "MigrationApplicationOrder" int NOT NULL,
121
+ "FromMigrationID" varchar(80),
122
+ "ToRangeStartMigrationID" varchar(80) NOT NULL,
123
+ "ToRangeEndMigrationID" varchar(80) NOT NULL,
124
+
125
+ CONSTRAINT PK_previous_states PRIMARY KEY (
126
+ "Changed",
127
+ "MigrationApplicationOrder"
128
+ )
129
+ );
130
+ END IF;
131
+
114
132
  IF NOT EXISTS(
115
133
  SELECT * FROM information_schema.tables
116
134
  WHERE table_schema = 'xmigra' AND table_name = 'access_objects'
@@ -145,6 +163,26 @@ module XMigra
145
163
  );
146
164
  END IF;
147
165
 
166
+ IF NOT EXISTS(
167
+ SELECT * FROM information_schema.views
168
+ WHERE table_schema = 'xmigra' and table_name = 'last_applied_migrations'
169
+ ) THEN
170
+ CREATE VIEW xmigra.last_applied_migrations AS
171
+ SELECT
172
+ row_number() OVER (ORDER BY a."ApplicationOrder" DESC) AS "RevertOrder",
173
+ a."Description"
174
+ FROM
175
+ xmigra.applied a
176
+ WHERE
177
+ a."ApplicationOrder" > COALESCE((
178
+ SELECT ps."MigrationApplicationOrder"
179
+ FROM xmigra.previous_states ps
180
+ JOIN xmigra.applied a2 ON ps."ToRangeStartMigrationID" = a2."MigrationID"
181
+ ORDER BY ps."Changed" DESC
182
+ LIMIT 1
183
+ ), 0);
184
+ END IF;
185
+
148
186
  RAISE NOTICE ' done';
149
187
  }
150
188
  end
@@ -292,6 +330,40 @@ module XMigra
292
330
  );
293
331
  END IF;
294
332
 
333
+ INSERT INTO xmigra.previous_states (
334
+ "Changed",
335
+ "MigrationApplicationOrder",
336
+ "FromMigrationID",
337
+ "ToRangeStartMigrationID",
338
+ "ToRangeEndMigrationID"
339
+ )
340
+ SELECT
341
+ CURRENT_TIMESTAMP,
342
+ -- Application order of last installed migration --
343
+ COALESCE(
344
+ (
345
+ SELECT "ApplicationOrder" FROM xmigra.applied
346
+ ORDER BY "ApplicationOrder" DESC
347
+ ),
348
+ 0
349
+ ),
350
+ ( -- Last installed migration --
351
+ SELECT "MigrationID" FROM xmigra.applied
352
+ ORDER BY "ApplicationOrder" DESC
353
+ LIMIT 1
354
+ ),
355
+ m."MigrationID",
356
+ ( -- Last migration to install --
357
+ SELECT "MigrationID" FROM temp$xmigra_migrations
358
+ WHERE "Install"
359
+ ORDER BY "ApplicationOrder" DESC
360
+ LIMIT 1
361
+ )
362
+ FROM temp$xmigra_migrations m
363
+ WHERE "Install"
364
+ ORDER BY "ApplicationOrder" ASC
365
+ LIMIT 1;
366
+
295
367
  RAISE NOTICE ' done';
296
368
  })
297
369
  end
@@ -490,6 +562,10 @@ module XMigra
490
562
  }
491
563
  end
492
564
 
565
+ def reversion_tracking_sql
566
+ %Q{DELETE FROM xmigra.applied WHERE "MigrationID" = '#{id}';\n}
567
+ end
568
+
493
569
  def check_existence_sql(for_existence, error_message)
494
570
  error_message_literal = PgSQLSpecifics.string_literal sprintf(error_message, quoted_name)
495
571
 
@@ -591,7 +667,7 @@ module XMigra
591
667
  DELETE FROM xmigra.applied WHERE "MigrationID" = CompletedMigration.applied;
592
668
 
593
669
  INSERT INTO xmigra.applied ("MigrationID", "VersionBridgeMark", "Description")
594
- VALUE (CompletedMigration.applied, TRUE, 'Branch upgrade from branch ' || CompletedMigration.old_branch || '.');
670
+ VALUES (CompletedMigration.applied, TRUE, 'Branch upgrade from branch ' || CompletedMigration.old_branch || '.');
595
671
 
596
672
  RAISE NOTICE ' done';
597
673
  END IF;
@@ -1,3 +1,5 @@
1
+ require 'pathname'
2
+ require 'xmigra/revert_file'
1
3
 
2
4
  module XMigra
3
5
  class Migration
@@ -18,6 +20,15 @@ module XMigra
18
20
  attr_reader :id, :follows, :sql, :description, :changes
19
21
  attr_accessor :file_path
20
22
 
23
+ def schema_dir
24
+ Pathname(file_path).dirname.join('..')
25
+ end
26
+
27
+ def reversion
28
+ result = RevertFile.new(self)
29
+ return result if result.exist?
30
+ end
31
+
21
32
  class << self
22
33
  def id_from_filename(fname)
23
34
  XMigra.secure_digest(fname.upcase) # Base64 encoded digest
@@ -184,7 +184,7 @@ END_OF_HELP
184
184
 
185
185
  def output_to(fpath_or_nil)
186
186
  if fpath_or_nil.nil?
187
- yield(STDOUT)
187
+ yield($stdout)
188
188
  else
189
189
  File.open(fpath_or_nil, "w") do |stream|
190
190
  yield(stream)
@@ -457,6 +457,7 @@ system shall be targeted for the generation of scripts. Currently the
457
457
  supported values are:
458
458
 
459
459
  - Microsoft SQL Server
460
+ - PostgreSQL
460
461
 
461
462
  Each system can also have sub-settings that modify the generated scripts.
462
463
 
@@ -671,6 +672,36 @@ END_OF_HELP
671
672
  end
672
673
  end
673
674
 
675
+ subcommand 'reversions', "Generate a script file containing reversions" do |argv|
676
+ args, options = command_line(argv, {:outfile=>true},
677
+ :help=> <<END_OF_HELP)
678
+ This command generates a script file containing parts that can be run to
679
+ revert individual migrations in reverse of the order they are applied. The
680
+ SQL for reverting the migration is taken from a file with the same basename
681
+ as the migration it reverts, but in the 'rollback' subfolder and with a
682
+ '.sql' extension. The output file will not run as a viable script; a
683
+ contiguous section starting at the first SQL command and terminating at a
684
+ migration boundary should be run. Subsequent sections, consecutive with those
685
+ previously run, may also be run to further revert the database if necessary.
686
+
687
+ It may be helpful to execute the query:
688
+
689
+ SELECT * FROM xmigra.last_applied_migrations ORDER BY "RevertOrder";
690
+
691
+ This query lists the migrations applied by the last upgrade script that was
692
+ run.
693
+ END_OF_HELP
694
+
695
+ argument_error_unless(args.length == 0,
696
+ "'%prog %cmd' does not take any arguments.")
697
+
698
+ sql_gen = SchemaUpdater.new(options.source_dir).extend(WarnToStderr)
699
+
700
+ output_to(options.outfile) do |out_stream|
701
+ out_stream.print(sql_gen.reversion_script)
702
+ end
703
+ end
704
+
674
705
  subcommand 'render', "Generate SQL script for an access object" do |argv|
675
706
  args, options = command_line(argv, {:outfile=>true},
676
707
  :argument_desc=>"ACCESS_OBJECT_FILE",
@@ -0,0 +1,40 @@
1
+
2
+ module XMigra
3
+ module ReversionScriptBuilding
4
+ # This module is intended to be included into XMigra::SchemaUpdater
5
+
6
+ def reversions
7
+ if @reversions.nil?
8
+ @reversions = []
9
+ migrations.reverse_each do |m|
10
+ reversion = m.reversion
11
+ break unless reversion
12
+ @reversions << reversion
13
+ end
14
+ end
15
+
16
+ return @reversions if @reversions
17
+ end
18
+
19
+ def reversion_script
20
+ return nil if reversions.empty?
21
+
22
+ usage_note = [
23
+ "Run the reversion scripts below (separated by -- ======= -- dividers) in",
24
+ "the order given to revert changes as far as desired. Migrations should",
25
+ "always be reverted in the order given in this file. If any migration is",
26
+ "not reverted and one further down this file is, XMigra will no longer be",
27
+ "able to update the database schema.\n",
28
+ "The query:",
29
+ "",
30
+ " SELECT * FROM xmigra.last_applied_migrations ORDER BY \"RevertOrder\";",
31
+ "",
32
+ "lists the migrations applied by the last upgrade script run against this",
33
+ "database.\n",
34
+ ].collect {|l| '-- ' + l + "\n"}.join('')
35
+
36
+ return usage_note + "========================================\n" + \
37
+ reversions.join("-- ================================== --\n")
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,42 @@
1
+ require 'pathname'
2
+
3
+ module XMigra
4
+ class RevertFile
5
+ REVERSION_SUBDIR = 'rollback'
6
+
7
+ def initialize(migration)
8
+ @migration = migration
9
+ mig_path = Pathname(migration.file_path)
10
+ @description = "REVERT #{migration.description} (#{mig_path.basename})"
11
+ @path = migration.schema_dir.join(
12
+ REVERSION_SUBDIR,
13
+ mig_path.basename.to_s.sub(/\..*?$/, '.sql')
14
+ )
15
+ end
16
+
17
+ attr_reader :path, :description
18
+
19
+ def to_s
20
+ if @path.exist?
21
+ @sql ||= "-- %s:\n\n%s\n%s" % [
22
+ @description,
23
+ @path.read,
24
+ @migration.reversion_tracking_sql
25
+ ]
26
+ else
27
+ "-- #@description: No reversion given\n"
28
+ end
29
+ end
30
+
31
+ def inspect
32
+ "#<#{self.class.name} %s%s>" % [
33
+ @path,
34
+ (" (missing)" unless @path.exist?),
35
+ ]
36
+ end
37
+
38
+ def exist?
39
+ @path.exist?
40
+ end
41
+ end
42
+ end
@@ -1,8 +1,11 @@
1
1
 
2
2
  require 'xmigra/schema_manipulator'
3
+ require 'xmigra/reversion_script_building'
3
4
 
4
5
  module XMigra
5
6
  class SchemaUpdater < SchemaManipulator
7
+ include ReversionScriptBuilding
8
+
6
9
  DEV_SCRIPT_WARNING = <<-"END_OF_TEXT"
7
10
  *********************************************************
8
11
  *** WARNING ***
@@ -8,7 +8,7 @@ module XMigra
8
8
 
9
9
  class << self
10
10
  def manages(path)
11
- run_git(:status, :check_exit=>true)
11
+ run_git(:status, :check_exit=>true, :quiet=>true)
12
12
  end
13
13
 
14
14
  def run_git(subcmd, *args)
@@ -1,3 +1,3 @@
1
1
  module XMigra
2
- VERSION = "1.2.0"
2
+ VERSION = "1.3.0"
3
3
  end
@@ -0,0 +1,97 @@
1
+
2
+ def in_xmigra_schema
3
+ 1.temp_dirs do |schema|
4
+ Dir.chdir(schema) do
5
+ initialize_xmigra_schema
6
+ yield
7
+ end
8
+ end
9
+ end
10
+
11
+ def add_migration(migration_name, reversion_sql=nil)
12
+ tool = XMigra::NewMigrationAdder.new('.')
13
+ mig_path = tool.add_migration migration_name
14
+ mig_chain = XMigra::MigrationChain.new('structure')
15
+ migration = mig_chain[-1]
16
+ unless reversion_sql.nil?
17
+ class <<migration
18
+ def reversion_tracking_sql
19
+ '-- TRACK REVERSION OF MIGRATION --'
20
+ end
21
+ end
22
+ rev_file = XMigra::RevertFile.new(migration)
23
+ rev_file.path.dirname.mkpath
24
+ rev_file.path.open('w') do |rev_stream|
25
+ rev_stream.puts reversion_sql
26
+ end
27
+ end
28
+ return migration
29
+ end
30
+
31
+ def add_migration_reversion_pair(migration_name, reversion_sql)
32
+ return [add_migration(migration_name, reversion_sql), reversion_sql]
33
+ end
34
+
35
+ run_test "Generate upgrade with no reversions" do
36
+ in_xmigra_schema do
37
+ XMigra::NewMigrationAdder.new('.').tap do |tool|
38
+ tool.add_migration "Create foo table"
39
+ end
40
+ XMigra::Program.run(['upgrade', '--outfile=/dev/null'])
41
+ end
42
+ end
43
+
44
+ run_test "Generate reversions script with no reversions" do
45
+ in_xmigra_schema do
46
+ XMigra::NewMigrationAdder.new('.').tap do |tool|
47
+ tool.add_migration "Create foo table"
48
+ end
49
+ XMigra::Program.run(['reversions', '--outfile=/dev/null'])
50
+ end
51
+ end
52
+
53
+ run_test "Migration reversion contains SQL in reversion file" do
54
+ in_xmigra_schema do
55
+ reversion_sql = "DROP TABLE foo;"
56
+ migration = add_migration("Create foo table", reversion_sql)
57
+ assert("Reversion commands did not contain expected SQL") {
58
+ migration.reversion.to_s.include? reversion_sql
59
+ }
60
+ end
61
+ end
62
+
63
+ run_test "Generated revisions script for one migration" do
64
+ in_xmigra_schema do
65
+ reversion_sql = "DROP TABLE foo;"
66
+ migration = add_migration("Create foo table", reversion_sql)
67
+ assert("Reversions script did not contain reversion SQL") {
68
+ XMigra::Program.run(['reversions'])
69
+ test_output.include? reversion_sql
70
+ }
71
+ end
72
+ end
73
+
74
+ run_test "Generated revisions script for one migration removes application record" do
75
+ in_xmigra_schema do
76
+ reversion_sql = "DROP TABLE foo;"
77
+ migration = add_migration("Create foo table", reversion_sql)
78
+ assert("Reversions script does not remove migration application record") {
79
+ XMigra::Program.run(['reversions'])
80
+ script = test_output
81
+ script =~ /DELETE\s+FROM\s+.?xmigra.?\..?applied.?\s+WHERE\s+.?MigrationID.?\s*=\s*'#{migration.id}'\s*;/
82
+ }
83
+ end
84
+ end
85
+
86
+ run_test "Generate reversions script for two migrations" do
87
+ in_xmigra_schema do
88
+ migrations = []
89
+ migrations << add_migration_reversion_pair("Create foo table", "DROP TABLE foo;")
90
+ migrations << add_migration_reversion_pair("Add bar column to foo table", "ALTER TABLE foo DROP bar;")
91
+ assert("ALTER TABLE appeared after DROP TABLE") {
92
+ XMigra::Program.run(['reversions'])
93
+ script = test_output
94
+ (script =~ /ALTER\s+TABLE/) < (script =~ /DROP\s+TABLE/)
95
+ }
96
+ end
97
+ end
data/test/runner.rb CHANGED
@@ -7,6 +7,7 @@ require 'tmpdir'
7
7
 
8
8
  TESTS = %w[
9
9
  git_vcs
10
+ reversions
10
11
  ]
11
12
 
12
13
  $:.unshift Pathname(__FILE__).expand_path.dirname.dirname + 'lib'
@@ -48,7 +49,13 @@ def run_test(name, &block)
48
49
  end
49
50
  else
50
51
  begin
51
- block.call
52
+ prev_stdout = $stdout
53
+ $stdout = StringIO.new
54
+ begin
55
+ block.call
56
+ ensure
57
+ $stdout = prev_stdout
58
+ end
52
59
  exit! 0
53
60
  rescue AssertionFailure
54
61
  exit! 2
@@ -95,6 +102,11 @@ def initialize_xmigra_schema(path='.', options={})
95
102
  end
96
103
  end
97
104
 
105
+ def test_output
106
+ return nil unless $stdout.kind_of? StringIO
107
+ return $stdout.string
108
+ end
109
+
98
110
  def assert(message=nil, &block)
99
111
  get_message = proc {
100
112
  if !message and File.exist?(block.source_location[0])
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xmigra
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Next IT Corporation
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-12-08 00:00:00.000000000 Z
12
+ date: 2015-02-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -73,6 +73,8 @@ files:
73
73
  - lib/xmigra/new_migration_adder.rb
74
74
  - lib/xmigra/permission_script_writer.rb
75
75
  - lib/xmigra/program.rb
76
+ - lib/xmigra/reversion_script_building.rb
77
+ - lib/xmigra/revert_file.rb
76
78
  - lib/xmigra/schema_manipulator.rb
77
79
  - lib/xmigra/schema_updater.rb
78
80
  - lib/xmigra/stored_procedure.rb
@@ -82,6 +84,7 @@ files:
82
84
  - lib/xmigra/version.rb
83
85
  - lib/xmigra/view.rb
84
86
  - test/git_vcs.rb
87
+ - test/reversions.rb
85
88
  - test/runner.rb
86
89
  - xmigra.gemspec
87
90
  homepage: https://github.com/rtweeks/xmigra