dump 1.0.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.
Files changed (89) hide show
  1. data/.autotest +13 -0
  2. data/.gitignore +12 -0
  3. data/LICENSE.txt +20 -0
  4. data/README.markdown +250 -0
  5. data/dump.gemspec +22 -0
  6. data/lib/dump.rb +3 -0
  7. data/lib/dump/capistrano.rb +1 -0
  8. data/lib/dump/railtie.rb +8 -0
  9. data/lib/dump_rake.rb +85 -0
  10. data/lib/dump_rake/archive_tar_minitar_fix.rb +8 -0
  11. data/lib/dump_rake/assets.rb +22 -0
  12. data/lib/dump_rake/continious_timeout.rb +38 -0
  13. data/lib/dump_rake/dump.rb +175 -0
  14. data/lib/dump_rake/dump_reader.rb +289 -0
  15. data/lib/dump_rake/dump_writer.rb +119 -0
  16. data/lib/dump_rake/env.rb +139 -0
  17. data/lib/dump_rake/env/filter.rb +26 -0
  18. data/lib/dump_rake/rails_root.rb +12 -0
  19. data/lib/dump_rake/table_manipulation.rb +131 -0
  20. data/lib/generators/assets_config/assets_config_generator.rb +16 -0
  21. data/lib/generators/assets_config/templates/assets +8 -0
  22. data/lib/tasks/assets.rake +17 -0
  23. data/lib/tasks/dump.rake +27 -0
  24. data/recipes/dump.rb +343 -0
  25. data/script/update_readme +21 -0
  26. data/spec/.gitignore +1 -0
  27. data/spec/.tmignore +1 -0
  28. data/spec/cycle_spec.rb +229 -0
  29. data/spec/db/database.example.yml +19 -0
  30. data/spec/db/schema.rb +7 -0
  31. data/spec/dummy-3.1.3/.gitignore +15 -0
  32. data/spec/dummy-3.1.3/.rspec +1 -0
  33. data/spec/dummy-3.1.3/Gemfile +23 -0
  34. data/spec/dummy-3.1.3/Gemfile.lock +159 -0
  35. data/spec/dummy-3.1.3/README +261 -0
  36. data/spec/dummy-3.1.3/Rakefile +7 -0
  37. data/spec/dummy-3.1.3/app/assets/images/rails.png +0 -0
  38. data/spec/dummy-3.1.3/app/assets/javascripts/application.js +9 -0
  39. data/spec/dummy-3.1.3/app/assets/stylesheets/application.css +7 -0
  40. data/spec/dummy-3.1.3/app/controllers/application_controller.rb +3 -0
  41. data/spec/dummy-3.1.3/app/helpers/application_helper.rb +2 -0
  42. data/spec/dummy-3.1.3/app/mailers/.gitkeep +0 -0
  43. data/spec/dummy-3.1.3/app/models/.gitkeep +0 -0
  44. data/spec/dummy-3.1.3/app/views/layouts/application.html.erb +14 -0
  45. data/spec/dummy-3.1.3/config.ru +4 -0
  46. data/spec/dummy-3.1.3/config/application.rb +54 -0
  47. data/spec/dummy-3.1.3/config/boot.rb +6 -0
  48. data/spec/dummy-3.1.3/config/database.yml +25 -0
  49. data/spec/dummy-3.1.3/config/environment.rb +5 -0
  50. data/spec/dummy-3.1.3/config/environments/development.rb +30 -0
  51. data/spec/dummy-3.1.3/config/environments/production.rb +60 -0
  52. data/spec/dummy-3.1.3/config/environments/test.rb +39 -0
  53. data/spec/dummy-3.1.3/config/initializers/backtrace_silencers.rb +7 -0
  54. data/spec/dummy-3.1.3/config/initializers/inflections.rb +10 -0
  55. data/spec/dummy-3.1.3/config/initializers/mime_types.rb +5 -0
  56. data/spec/dummy-3.1.3/config/initializers/secret_token.rb +7 -0
  57. data/spec/dummy-3.1.3/config/initializers/session_store.rb +8 -0
  58. data/spec/dummy-3.1.3/config/initializers/wrap_parameters.rb +14 -0
  59. data/spec/dummy-3.1.3/config/locales/en.yml +5 -0
  60. data/spec/dummy-3.1.3/config/routes.rb +58 -0
  61. data/spec/dummy-3.1.3/db/seeds.rb +7 -0
  62. data/spec/dummy-3.1.3/doc/README_FOR_APP +2 -0
  63. data/spec/dummy-3.1.3/lib/assets/.gitkeep +0 -0
  64. data/spec/dummy-3.1.3/lib/tasks/.gitkeep +0 -0
  65. data/spec/dummy-3.1.3/log/.gitkeep +0 -0
  66. data/spec/dummy-3.1.3/public/404.html +26 -0
  67. data/spec/dummy-3.1.3/public/422.html +26 -0
  68. data/spec/dummy-3.1.3/public/500.html +26 -0
  69. data/spec/dummy-3.1.3/public/favicon.ico +0 -0
  70. data/spec/dummy-3.1.3/public/index.html +241 -0
  71. data/spec/dummy-3.1.3/public/robots.txt +5 -0
  72. data/spec/dummy-3.1.3/script/rails +6 -0
  73. data/spec/dummy-3.1.3/spec/spec_helper.rb +32 -0
  74. data/spec/dummy-3.1.3/vendor/assets/stylesheets/.gitkeep +0 -0
  75. data/spec/dummy-3.1.3/vendor/plugins/.gitkeep +0 -0
  76. data/spec/lib/dump_rake/dump_reader_spec.rb +638 -0
  77. data/spec/lib/dump_rake/dump_spec.rb +291 -0
  78. data/spec/lib/dump_rake/dump_writer_spec.rb +328 -0
  79. data/spec/lib/dump_rake/env/filter_spec.rb +56 -0
  80. data/spec/lib/dump_rake/env_spec.rb +139 -0
  81. data/spec/lib/dump_rake/rails_root_spec.rb +45 -0
  82. data/spec/lib/dump_rake/table_manipulation_spec.rb +256 -0
  83. data/spec/lib/dump_rake_spec.rb +326 -0
  84. data/spec/recipes/dump_spec.rb +553 -0
  85. data/spec/spec.opts +4 -0
  86. data/spec/spec_helper.rb +34 -0
  87. data/spec/tasks/assets_spec.rb +92 -0
  88. data/spec/tasks/dump_spec.rb +107 -0
  89. metadata +272 -0
@@ -0,0 +1,291 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe DumpRake::Dump do
4
+ def dump_path(file_name)
5
+ File.join(DumpRake::RailsRoot, 'dump', file_name)
6
+ end
7
+
8
+ def new_dump(file_name)
9
+ DumpRake::Dump.new(dump_path(file_name))
10
+ end
11
+
12
+ describe "lock" do
13
+ before do
14
+ @yield_receiver = mock('yield_receiver')
15
+ end
16
+
17
+ it "should not yield if file does not exist" do
18
+ @yield_receiver.should_not_receive(:fire)
19
+
20
+ File.should_receive(:open).and_return(nil)
21
+
22
+ DumpRake::Dump.new('hello').lock do
23
+ @yield_receiver.fire
24
+ end
25
+ end
26
+
27
+ it "should not yield if file can not be locked" do
28
+ @yield_receiver.should_not_receive(:fire)
29
+
30
+ @file = mock('file')
31
+ @file.should_receive(:flock).with(File::LOCK_EX | File::LOCK_NB).and_return(nil)
32
+ @file.should_receive(:flock).with(File::LOCK_UN)
33
+ @file.should_receive(:close)
34
+ File.should_receive(:open).and_return(@file)
35
+
36
+ DumpRake::Dump.new('hello').lock do
37
+ @yield_receiver.fire
38
+ end
39
+ end
40
+
41
+ it "should yield if file can not be locked" do
42
+ @yield_receiver.should_receive(:fire)
43
+
44
+ @file = mock('file')
45
+ @file.should_receive(:flock).with(File::LOCK_EX | File::LOCK_NB).and_return(true)
46
+ @file.should_receive(:flock).with(File::LOCK_UN)
47
+ @file.should_receive(:close)
48
+ File.should_receive(:open).and_return(@file)
49
+
50
+ DumpRake::Dump.new('hello').lock do
51
+ @yield_receiver.fire
52
+ end
53
+ end
54
+ end
55
+
56
+ describe "new" do
57
+ it "should init with path if String sent" do
58
+ DumpRake::Dump.new('hello').path.should == Pathname('hello')
59
+ end
60
+
61
+ it "should init with path if Pathname sent" do
62
+ DumpRake::Dump.new(Pathname('hello')).path.should == Pathname('hello')
63
+ end
64
+
65
+ describe "with options" do
66
+ before do
67
+ @time = mock('time')
68
+ @time.stub!(:utc).and_return(@time)
69
+ @time.stub!(:strftime).and_return('19650414065945')
70
+ Time.stub!(:now).and_return(@time)
71
+ end
72
+
73
+ it "should generate path with no options" do
74
+ DumpRake::Dump.new.path.should == Pathname('19650414065945.tgz')
75
+ end
76
+
77
+ it "should generate with dir" do
78
+ DumpRake::Dump.new(:dir => 'dump_dir').path.should == Pathname('dump_dir/19650414065945.tgz')
79
+ end
80
+
81
+ it "should generate path with description" do
82
+ DumpRake::Dump.new(:dir => 'dump_dir', :desc => 'hello world').path.should == Pathname('dump_dir/19650414065945-hello world.tgz')
83
+ end
84
+
85
+ it "should generate path with tags" do
86
+ DumpRake::Dump.new(:dir => 'dump_dir', :tags => ' mirror, hello world ').path.should == Pathname('dump_dir/19650414065945@hello world,mirror.tgz')
87
+ end
88
+
89
+ it "should generate path with description and tags" do
90
+ DumpRake::Dump.new(:dir => 'dump_dir', :desc => 'Anniversary backup', :tags => ' mirror, hello world ').path.should == Pathname('dump_dir/19650414065945-Anniversary backup@hello world,mirror.tgz')
91
+ end
92
+ end
93
+ end
94
+
95
+ describe "versions" do
96
+ describe "list" do
97
+ def stub_glob
98
+ paths = %w[123 345 567].map do |name|
99
+ path = dump_path("#{name}.tgz")
100
+ File.should_receive(:file?).with(path).at_least(1).and_return(true)
101
+ path
102
+ end
103
+ Dir.stub!(:[]).and_return(paths)
104
+ end
105
+
106
+ it "should search for files in dump dir when asked for list" do
107
+ Dir.should_receive(:[]).with(dump_path('*.tgz')).and_return([])
108
+ DumpRake::Dump.list
109
+ end
110
+
111
+ it "should return selves instances for each found file" do
112
+ stub_glob
113
+ DumpRake::Dump.list.all?{ |dump| dump.should be_a(DumpRake::Dump) }
114
+ end
115
+
116
+ it "should return dumps with name containting :like" do
117
+ stub_glob
118
+ DumpRake::Dump.list(:like => '3').should == DumpRake::Dump.list.values_at(0, 1)
119
+ end
120
+ end
121
+
122
+ describe "with tags" do
123
+ before do
124
+ # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
125
+ dumps_tags = [''] + %w[a a,d a,d,o a,d,s a,d,s,o a,o a,s a,s,o d d,o d,s d,s,o o s s,o z]
126
+ paths = dumps_tags.each_with_index.map do |dump_tags, i|
127
+ path = dump_path("196504140659#{10 + i}@#{dump_tags}.tgz")
128
+ File.should_receive(:file?).with(path).at_least(1).and_return(true)
129
+ path
130
+ end
131
+ Dir.stub!(:[]).and_return(paths)
132
+ end
133
+
134
+ it "should return all dumps if no tags send" do
135
+ DumpRake::Dump.list(:tags => '').should == DumpRake::Dump.list
136
+ end
137
+
138
+ {
139
+ 'x' => [],
140
+ '+x' => [],
141
+ 'z' => [16],
142
+ 'a,d,s,o' => [1..15],
143
+ '+a,+d,+s,+o' => [5],
144
+ '-o' => [0, 1, 2, 4, 7, 9, 11, 14, 16],
145
+ 'a,b,c,+s,-o' => [4, 7],
146
+ '+a,+d' => [2, 3, 4, 5],
147
+ '+d,+a' => [2, 3, 4, 5],
148
+ }.each do |tags, ids|
149
+ it "should return dumps filtered by #{tags}" do
150
+ DumpRake::Dump.list(:tags => tags).should == DumpRake::Dump.list.values_at(*ids)
151
+ end
152
+ end
153
+ end
154
+ end
155
+
156
+ describe "name" do
157
+ it "should return file name" do
158
+ new_dump("19650414065945.tgz").name.should == '19650414065945.tgz'
159
+ end
160
+ end
161
+
162
+ describe "parts" do
163
+ before do
164
+ @time = Time.utc(1965, 4, 14, 6, 59, 45)
165
+ end
166
+
167
+ def dump_name_parts(name)
168
+ dump = new_dump(name)
169
+ [dump.time, dump.description, dump.tags, dump.ext]
170
+ end
171
+
172
+ %w[tmp tgz].each do |ext|
173
+ it "should return empty results for dump with wrong name" do
174
+ dump_name_parts("196504140659.#{ext}").should == [nil, '', [], nil]
175
+ dump_name_parts("196504140659-lala.#{ext}").should == [nil, '', [], nil]
176
+ dump_name_parts("196504140659@lala.#{ext}").should == [nil, '', [], nil]
177
+ dump_name_parts("19650414065945.ops").should == [nil, '', [], nil]
178
+ end
179
+
180
+ it "should return tags for dump with tags" do
181
+ dump_name_parts("19650414065945.#{ext}").should == [@time, '', [], ext]
182
+ dump_name_parts("19650414065945- Hello world &&& .#{ext}").should == [@time, 'Hello world _', [], ext]
183
+ dump_name_parts("19650414065945- Hello world &&& @ test , hello world , bad tag ~~~~.#{ext}").should == [@time, 'Hello world _', ['bad tag _', 'hello world', 'test'], ext]
184
+ dump_name_parts("19650414065945@test, test , hello world , bad tag ~~~~.#{ext}").should == [@time, '', ['bad tag _', 'hello world', 'test'], ext]
185
+ dump_name_parts("19650414065945-Hello world@test,super tag.#{ext}").should == [@time, 'Hello world', ['super tag', 'test'], ext]
186
+ end
187
+ end
188
+ end
189
+
190
+ describe "path" do
191
+ it "should return path" do
192
+ new_dump("19650414065945.tgz").path.should == Pathname(File.join(DumpRake::RailsRoot, 'dump', "19650414065945.tgz"))
193
+ end
194
+ end
195
+
196
+ describe "tgz_path" do
197
+ it "should return path if extension is already tgz" do
198
+ new_dump("19650414065945.tgz").tgz_path.should == new_dump("19650414065945.tgz").path
199
+ end
200
+
201
+ it "should return path with tgz extension" do
202
+ new_dump("19650414065945.tmp").tgz_path.should == new_dump("19650414065945.tgz").path
203
+ end
204
+ end
205
+
206
+ describe "tmp_path" do
207
+ it "should return path if extension is already tmp" do
208
+ new_dump("19650414065945.tmp").tmp_path.should == new_dump("19650414065945.tmp").path
209
+ end
210
+
211
+ it "should return path with tmp extension" do
212
+ new_dump("19650414065945.tgz").tmp_path.should == new_dump("19650414065945.tmp").path
213
+ end
214
+ end
215
+
216
+ describe "clean_description" do
217
+ it "should shorten string to 50 chars and replace special symblos with '-'" do
218
+ DumpRake::Dump.new('').send(:clean_description, 'Special Dump #12837192837 (before fixind *&^*&^ photos)').should == 'Special Dump #12837192837 (before fixind _ photos)'
219
+ DumpRake::Dump.new('').send(:clean_description, "To#{'o' * 100} long description").should == "T#{'o' * 49}"
220
+ end
221
+
222
+ it "should accept non string" do
223
+ DumpRake::Dump.new('').send(:clean_description, nil).should == ''
224
+ end
225
+ end
226
+
227
+ describe "clean_tag" do
228
+ it "should shorten string to 20 chars and replace special symblos with '-'" do
229
+ DumpRake::Dump.new('').send(:clean_tag, 'Very special tag #12837192837 (fixind *&^*&^)').should == 'very special tag _12'
230
+ DumpRake::Dump.new('').send(:clean_tag, "To#{'o' * 100} long tag").should == "t#{'o' * 19}"
231
+ end
232
+
233
+ it "should not allow '-' or '+' to be first symbol" do
234
+ DumpRake::Dump.new('').send(:clean_tag, ' Very special tag').should == 'very special tag'
235
+ DumpRake::Dump.new('').send(:clean_tag, '-Very special tag').should == 'very special tag'
236
+ DumpRake::Dump.new('').send(:clean_tag, '-----------').should == ''
237
+ DumpRake::Dump.new('').send(:clean_tag, '+Very special tag').should == '_very special tag'
238
+ DumpRake::Dump.new('').send(:clean_tag, '+++++++++++').should == '_'
239
+ end
240
+
241
+ it "should accept non string" do
242
+ DumpRake::Dump.new('').send(:clean_tag, nil).should == ''
243
+ end
244
+ end
245
+
246
+ describe "clean_tags" do
247
+ it "should split string and return uniq non blank sorted tags" do
248
+ DumpRake::Dump.new('').send(:clean_tags, ' perfect tag , hello,Hello,this is (*^(*&').should == ['hello', 'perfect tag', 'this is _']
249
+ DumpRake::Dump.new('').send(:clean_tags, "l#{'o' * 100}ng tag").should == ["l#{'o' * 19}"]
250
+ end
251
+
252
+ it "should accept non string" do
253
+ DumpRake::Dump.new('').send(:clean_tags, nil).should == []
254
+ end
255
+ end
256
+
257
+ describe "get_filter_tags" do
258
+ it "should split string and return uniq non blank sorted tags" do
259
+ DumpRake::Dump.new('').send(:get_filter_tags, 'a,+b,+c,-d').should == {:simple => %w[a], :mandatory => %w[b c], :forbidden => %w[d]}
260
+ DumpRake::Dump.new('').send(:get_filter_tags, ' a , + b , + c , - d ').should == {:simple => %w[a], :mandatory => %w[b c], :forbidden => %w[d]}
261
+ DumpRake::Dump.new('').send(:get_filter_tags, ' a , + c , + b , - d ').should == {:simple => %w[a], :mandatory => %w[b c], :forbidden => %w[d]}
262
+ DumpRake::Dump.new('').send(:get_filter_tags, ' a , + b , + , - ').should == {:simple => %w[a], :mandatory => %w[b], :forbidden => []}
263
+ DumpRake::Dump.new('').send(:get_filter_tags, ' a , a , + b , + b , - d , - d ').should == {:simple => %w[a], :mandatory => %w[b], :forbidden => %w[d]}
264
+ proc{ DumpRake::Dump.new('').send(:get_filter_tags, 'a,+a') }.should_not raise_error
265
+ proc{ DumpRake::Dump.new('').send(:get_filter_tags, 'a,-a') }.should raise_error
266
+ proc{ DumpRake::Dump.new('').send(:get_filter_tags, '+a,-a') }.should raise_error
267
+ end
268
+
269
+ it "should accept non string" do
270
+ DumpRake::Dump.new('').send(:get_filter_tags, nil).should == {:simple => [], :mandatory => [], :forbidden => []}
271
+ end
272
+ end
273
+
274
+ describe "assets_root_link" do
275
+ it "should create tem dir, chdir there, symlink rails app root to assets, yield and unlink assets ever if something raised" do
276
+ Dir.should_receive(:mktmpdir).and_yield('/tmp/abc')
277
+ Dir.should_receive(:chdir).with('/tmp/abc').and_yield
278
+ File.should_receive(:symlink).with(DumpRake::RailsRoot, 'assets')
279
+ File.should_receive(:unlink).with('assets')
280
+ proc{
281
+ DumpRake::Dump.new('').send(:assets_root_link) do |dir, prefix|
282
+ dir.should == '/tmp/abc'
283
+ prefix.should == 'assets'
284
+ @yielded = true
285
+ raise 'just test'
286
+ end
287
+ }.should raise_error('just test')
288
+ @yielded.should == true
289
+ end
290
+ end
291
+ end
@@ -0,0 +1,328 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ require File.dirname(__FILE__) + '/../../../lib/dump_rake'
4
+
5
+ DumpWriter = DumpRake::DumpWriter
6
+ describe DumpWriter do
7
+ describe "create" do
8
+ it "should create selves instance and open" do
9
+ @dump = mock('dump')
10
+ @dump.should_receive(:open)
11
+ DumpWriter.should_receive(:new).with('/abc/123.tmp').and_return(@dump)
12
+ DumpWriter.create('/abc/123.tmp')
13
+ end
14
+
15
+ it "should call dump subroutines" do
16
+ @dump = mock('dump')
17
+ @dump.stub!(:open).and_yield(@dump)
18
+ DumpWriter.stub!(:new).and_return(@dump)
19
+
20
+ @dump.should_receive(:write_schema).ordered
21
+ @dump.should_receive(:write_tables).ordered
22
+ @dump.should_receive(:write_assets).ordered
23
+ @dump.should_receive(:write_config).ordered
24
+
25
+ DumpWriter.create('/abc/123.tmp')
26
+ end
27
+ end
28
+
29
+ describe "open" do
30
+ it "should create dir for dump" do
31
+ Zlib::GzipWriter.stub!(:open)
32
+ FileUtils.should_receive(:mkpath).with('/abc/def/ghi')
33
+ DumpWriter.new('/abc/def/ghi/123.tgz').open
34
+ end
35
+
36
+ it "should set stream to gzipped tar writer" do
37
+ FileUtils.stub!(:mkpath)
38
+ @gzip = mock('gzip')
39
+ @stream = mock('stream')
40
+ Zlib::GzipWriter.should_receive(:open).with(Pathname("123.tgz")).and_yield(@gzip)
41
+ Archive::Tar::Minitar::Output.should_receive(:open).with(@gzip).and_yield(@stream)
42
+ @gzip.should_receive(:mtime=).with(Time.utc(2000))
43
+
44
+ @dump = DumpWriter.new('123.tgz')
45
+ @dump.should_receive(:lock).and_yield
46
+ @dump.open do |dump|
47
+ dump.should == @dump
48
+ dump.stream.should == @stream
49
+ end
50
+ end
51
+ end
52
+
53
+ describe "subroutines" do
54
+ before do
55
+ @tar = mock('tar')
56
+ @stream = mock('stream', :tar => @tar)
57
+ @config = {:tables => {}}
58
+ @dump = DumpWriter.new('123.tgz')
59
+ @dump.stub!(:stream).and_return(@stream)
60
+ @dump.stub!(:config).and_return(@config)
61
+ Progress.stub!(:io).and_return(StringIO.new)
62
+ end
63
+
64
+ describe "create_file" do
65
+ it "should create temp file, yield it for writing, create file in tar and write it there" do
66
+ @temp = mock('temp', :open => true, :length => 6, :read => 'qwfpgj')
67
+ @temp.should_receive(:write).with('qwfpgj')
68
+ @temp.stub!(:eof?).and_return(false, true)
69
+ Tempfile.should_receive(:open).and_yield(@temp)
70
+
71
+ @file = mock('file')
72
+ @file.should_receive(:write).with('qwfpgj')
73
+
74
+ @stream.tar.should_receive(:add_file_simple).with('abc/def.txt', :mode => 0100444, :size => 6).and_yield(@file)
75
+
76
+ @dump.create_file('abc/def.txt') do |file|
77
+ file.should == @temp
78
+ file.write('qwfpgj')
79
+ end
80
+ end
81
+ end
82
+
83
+ describe "write_schema" do
84
+ it "should create file schema.rb" do
85
+ @dump.should_receive(:create_file).with('schema.rb')
86
+ @dump.write_schema
87
+ end
88
+
89
+ it "should set ENV[SCHEMA] to path of returned file" do
90
+ @file = mock('file', :path => 'db/schema.rb')
91
+ @dump.stub!(:create_file).and_yield(@file)
92
+ DumpRake::Env.should_receive(:with_env).with('SCHEMA' => 'db/schema.rb')
93
+ @dump.write_schema
94
+ end
95
+
96
+ it "should call rake task db:schema:dump" do
97
+ @file = mock('file', :path => 'db/schema.rb')
98
+ @dump.stub!(:create_file).and_yield(@file)
99
+ @task = mock('task')
100
+ Rake::Task.should_receive(:[]).with('db:schema:dump').and_return(@task)
101
+ @task.should_receive(:invoke)
102
+ @dump.write_schema
103
+ end
104
+ end
105
+
106
+ describe "write_tables" do
107
+ it "should verify connection" do
108
+ @dump.stub!(:tables_to_dump).and_return([])
109
+ @dump.should_receive(:verify_connection)
110
+ @dump.write_tables
111
+ end
112
+
113
+ it "should call write_table for each table returned by tables_to_dump" do
114
+ @dump.stub!(:verify_connection)
115
+ @dump.stub!(:tables_to_dump).and_return(%w[first second])
116
+
117
+ @dump.should_receive(:write_table).with('first')
118
+ @dump.should_receive(:write_table).with('second')
119
+
120
+ @dump.write_tables
121
+ end
122
+ end
123
+
124
+ describe "write_table" do
125
+ it "should get row count and store it to config" do
126
+ @dump.should_receive(:table_row_count).with('first').and_return(666)
127
+ @dump.stub!(:create_file)
128
+ @dump.write_table('first')
129
+ @config[:tables]['first'].should == 666
130
+ end
131
+
132
+ it "should create_file" do
133
+ @dump.stub!(:table_row_count).and_return(666)
134
+ @dump.should_receive(:create_file)
135
+ @dump.write_table('first')
136
+ end
137
+
138
+ it "should dump column names and values of each row" do
139
+ @column_definitions = [
140
+ mock('column', :name => 'id'),
141
+ mock('column', :name => 'name'),
142
+ mock('column', :name => 'associated_id')
143
+ ]
144
+ ActiveRecord::Base.connection.stub!(:columns).and_return(@column_definitions)
145
+ @rows = [
146
+ {'id' => 1, 'name' => 'a', 'associated_id' => 100},
147
+ {'id' => 2, 'name' => 'b', 'associated_id' => 666},
148
+ ]
149
+
150
+ @file = mock('file')
151
+ @dump.stub!(:table_row_count).and_return(666)
152
+ @dump.stub!(:create_file).and_yield(@file)
153
+
154
+ column_names = @column_definitions.map(&:name).sort
155
+ @file.should_receive(:write).with(Marshal.dump(column_names)).ordered
156
+ each_tabler_row_yielder = @dump.should_receive(:each_table_row)
157
+ @rows.each do |row|
158
+ each_tabler_row_yielder.and_yield(row)
159
+ @file.should_receive(:write).with(Marshal.dump(row.values_at(*column_names))).ordered
160
+ @column_definitions.each do |column_definition|
161
+ column_definition.should_receive(:type_cast).with(row[column_definition.name]).and_return(row[column_definition.name])
162
+ end
163
+ end
164
+
165
+ @dump.write_table('first')
166
+ end
167
+ end
168
+
169
+ describe "write_assets" do
170
+ before do
171
+ @dump.stub!(:assets_root_link).and_yield('/tmp', 'assets')
172
+ end
173
+
174
+ it "should call assets_to_dump" do
175
+ @dump.should_receive(:assets_to_dump).and_return([])
176
+ @dump.write_assets
177
+ end
178
+
179
+ it "should change root to rails app root" do
180
+ @file = mock('file')
181
+ @dump.stub!(:assets_to_dump).and_return(%w[images videos])
182
+ @dump.stub!(:create_file).and_yield(@file)
183
+
184
+ Dir.should_receive(:chdir).with(DumpRake::RailsRoot)
185
+ @dump.write_assets
186
+ end
187
+
188
+ it "should put assets to config" do
189
+ @file = mock('file')
190
+ @dump.stub!(:assets_to_dump).and_return(%w[images/* videos])
191
+ @dump.stub!(:create_file).and_yield(@file)
192
+ Dir.stub!(:chdir).and_yield
193
+ @tar = mock('tar_writer')
194
+ Archive::Tar::Minitar::Output.stub!(:open).and_yield(@tar)
195
+ Dir.stub!(:[]).and_return([])
196
+ Dir.should_receive(:[]).with(*%w[images/* videos]).and_return(%w[images/a images/b videos])
197
+
198
+ @dump.write_assets
199
+ counts = {:files => 0, :total => 0}
200
+ @config[:assets].should == {'images/a' => counts, 'images/b' => counts, 'videos' => counts}
201
+ end
202
+
203
+ it "should use glob to find files" do
204
+ @file = mock('file')
205
+ @dump.stub!(:assets_to_dump).and_return(%w[images/* videos])
206
+ @dump.stub!(:create_file).and_yield(@file)
207
+ Dir.stub!(:chdir).and_yield
208
+ @tar = mock('tar_writer')
209
+ Archive::Tar::Minitar::Output.stub!(:open).and_yield(@tar)
210
+
211
+ Dir.should_receive(:[]).with(*%w[images/* videos]).and_return(%w[images/a images/b videos])
212
+ Dir.should_receive(:[]).with('images/a/**/*').and_return([])
213
+ Dir.should_receive(:[]).with('images/b/**/*').and_return([])
214
+ Dir.should_receive(:[]).with('videos/**/*').and_return([])
215
+
216
+ @dump.write_assets
217
+ end
218
+
219
+ it "should pack each file from assets_root_link" do
220
+ @file = mock('file')
221
+ @dump.stub!(:assets_to_dump).and_return(%w[images/* videos])
222
+ @dump.stub!(:create_file).and_yield(@file)
223
+ Dir.stub!(:chdir).and_yield
224
+ @tar = mock('tar_writer')
225
+ Archive::Tar::Minitar::Output.stub!(:open).and_yield(@tar)
226
+
227
+ Dir.should_receive(:[]).with(*%w[images/* videos]).and_return(%w[images/a images/b videos])
228
+ Dir.should_receive(:[]).with('images/a/**/*').and_return([])
229
+ Dir.should_receive(:[]).with('images/b/**/*').and_return([])
230
+ Dir.should_receive(:[]).with('videos/**/*').and_return([])
231
+
232
+ @dump.should_receive(:assets_root_link).exactly(3).times
233
+
234
+ @dump.write_assets
235
+ end
236
+
237
+ it "should pack each file" do
238
+ @file = mock('file')
239
+ @dump.stub!(:assets_to_dump).and_return(%w[images/* videos])
240
+ @dump.stub!(:create_file).and_yield(@file)
241
+ Dir.stub!(:chdir).and_yield
242
+ @tar = mock('tar_writer')
243
+ Archive::Tar::Minitar::Output.stub!(:open).and_yield(@tar)
244
+
245
+ Dir.should_receive(:[]).with(*%w[images/* videos]).and_return(%w[images/a images/b videos])
246
+ Dir.should_receive(:[]).with('images/a/**/*').and_return(%w[a.jpg b.jpg])
247
+ Dir.should_receive(:[]).with('images/b/**/*').and_return(%w[c.jpg d.jpg])
248
+ Dir.should_receive(:[]).with('videos/**/*').and_return(%w[a.mov b.mov])
249
+
250
+ %w[a.jpg b.jpg c.jpg d.jpg a.mov b.mov].each do |file_name|
251
+ Archive::Tar::Minitar.should_receive(:pack_file).with("assets/#{file_name}", @stream)
252
+ end
253
+
254
+ @dump.write_assets
255
+ end
256
+
257
+ it "should not raise if something fails when packing" do
258
+ @file = mock('file')
259
+ @dump.stub!(:assets_to_dump).and_return(%w[videos])
260
+ @dump.stub!(:create_file).and_yield(@file)
261
+ Dir.stub!(:chdir).and_yield
262
+ @tar = mock('tar_writer')
263
+ Archive::Tar::Minitar::Output.stub!(:open).and_yield(@tar)
264
+
265
+ Dir.should_receive(:[]).with(*%w[videos]).and_return(%w[videos])
266
+ Dir.should_receive(:[]).with('videos/**/*').and_return(%w[a.mov b.mov])
267
+
268
+ Archive::Tar::Minitar.should_receive(:pack_file).with('assets/a.mov', @stream).and_raise('file not found')
269
+ Archive::Tar::Minitar.should_receive(:pack_file).with('assets/b.mov', @stream)
270
+
271
+ grab_output {
272
+ @dump.write_assets
273
+ }
274
+ end
275
+
276
+ end
277
+
278
+ describe "write_config" do
279
+ it "should create file config" do
280
+ @dump.should_receive(:create_file).with('config')
281
+ @dump.write_config
282
+ end
283
+
284
+ it "should dump column names and values of each row" do
285
+ @file = mock('file')
286
+ @dump.stub!(:create_file).and_yield(@file)
287
+ @config.replace({:tables => {'first' => 1, 'second' => 2}, :assets => %w[images videos]})
288
+
289
+ @file.should_receive(:write).with(Marshal.dump(@config))
290
+ @dump.write_config
291
+ end
292
+ end
293
+
294
+ describe "assets_to_dump" do
295
+ it "should call rake task assets" do
296
+ @task = mock('task')
297
+ Rake::Task.should_receive(:[]).with('assets').and_return(@task)
298
+ @task.should_receive(:invoke)
299
+ @dump.assets_to_dump
300
+ end
301
+
302
+ it "should return array of assets if separator is colon" do
303
+ @task = mock('task')
304
+ Rake::Task.stub!(:[]).and_return(@task)
305
+ @task.stub!(:invoke)
306
+ DumpRake::Env.with_env(:assets => 'images:videos') do
307
+ @dump.assets_to_dump.should == %w[images videos]
308
+ end
309
+ end
310
+
311
+ it "should return array of assets if separator is comma" do
312
+ @task = mock('task')
313
+ Rake::Task.stub!(:[]).and_return(@task)
314
+ @task.stub!(:invoke)
315
+ DumpRake::Env.with_env(:assets => 'images,videos') do
316
+ @dump.assets_to_dump.should == %w[images videos]
317
+ end
318
+ end
319
+
320
+ it "should return empty array if calling rake task assets raises an exception" do
321
+ Rake::Task.stub!(:[]).and_raise('task assets not found')
322
+ DumpRake::Env.with_env(:assets => 'images:videos') do
323
+ @dump.assets_to_dump.should == []
324
+ end
325
+ end
326
+ end
327
+ end
328
+ end