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.
- data/.autotest +13 -0
- data/.gitignore +12 -0
- data/LICENSE.txt +20 -0
- data/README.markdown +250 -0
- data/dump.gemspec +22 -0
- data/lib/dump.rb +3 -0
- data/lib/dump/capistrano.rb +1 -0
- data/lib/dump/railtie.rb +8 -0
- data/lib/dump_rake.rb +85 -0
- data/lib/dump_rake/archive_tar_minitar_fix.rb +8 -0
- data/lib/dump_rake/assets.rb +22 -0
- data/lib/dump_rake/continious_timeout.rb +38 -0
- data/lib/dump_rake/dump.rb +175 -0
- data/lib/dump_rake/dump_reader.rb +289 -0
- data/lib/dump_rake/dump_writer.rb +119 -0
- data/lib/dump_rake/env.rb +139 -0
- data/lib/dump_rake/env/filter.rb +26 -0
- data/lib/dump_rake/rails_root.rb +12 -0
- data/lib/dump_rake/table_manipulation.rb +131 -0
- data/lib/generators/assets_config/assets_config_generator.rb +16 -0
- data/lib/generators/assets_config/templates/assets +8 -0
- data/lib/tasks/assets.rake +17 -0
- data/lib/tasks/dump.rake +27 -0
- data/recipes/dump.rb +343 -0
- data/script/update_readme +21 -0
- data/spec/.gitignore +1 -0
- data/spec/.tmignore +1 -0
- data/spec/cycle_spec.rb +229 -0
- data/spec/db/database.example.yml +19 -0
- data/spec/db/schema.rb +7 -0
- data/spec/dummy-3.1.3/.gitignore +15 -0
- data/spec/dummy-3.1.3/.rspec +1 -0
- data/spec/dummy-3.1.3/Gemfile +23 -0
- data/spec/dummy-3.1.3/Gemfile.lock +159 -0
- data/spec/dummy-3.1.3/README +261 -0
- data/spec/dummy-3.1.3/Rakefile +7 -0
- data/spec/dummy-3.1.3/app/assets/images/rails.png +0 -0
- data/spec/dummy-3.1.3/app/assets/javascripts/application.js +9 -0
- data/spec/dummy-3.1.3/app/assets/stylesheets/application.css +7 -0
- data/spec/dummy-3.1.3/app/controllers/application_controller.rb +3 -0
- data/spec/dummy-3.1.3/app/helpers/application_helper.rb +2 -0
- data/spec/dummy-3.1.3/app/mailers/.gitkeep +0 -0
- data/spec/dummy-3.1.3/app/models/.gitkeep +0 -0
- data/spec/dummy-3.1.3/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy-3.1.3/config.ru +4 -0
- data/spec/dummy-3.1.3/config/application.rb +54 -0
- data/spec/dummy-3.1.3/config/boot.rb +6 -0
- data/spec/dummy-3.1.3/config/database.yml +25 -0
- data/spec/dummy-3.1.3/config/environment.rb +5 -0
- data/spec/dummy-3.1.3/config/environments/development.rb +30 -0
- data/spec/dummy-3.1.3/config/environments/production.rb +60 -0
- data/spec/dummy-3.1.3/config/environments/test.rb +39 -0
- data/spec/dummy-3.1.3/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy-3.1.3/config/initializers/inflections.rb +10 -0
- data/spec/dummy-3.1.3/config/initializers/mime_types.rb +5 -0
- data/spec/dummy-3.1.3/config/initializers/secret_token.rb +7 -0
- data/spec/dummy-3.1.3/config/initializers/session_store.rb +8 -0
- data/spec/dummy-3.1.3/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy-3.1.3/config/locales/en.yml +5 -0
- data/spec/dummy-3.1.3/config/routes.rb +58 -0
- data/spec/dummy-3.1.3/db/seeds.rb +7 -0
- data/spec/dummy-3.1.3/doc/README_FOR_APP +2 -0
- data/spec/dummy-3.1.3/lib/assets/.gitkeep +0 -0
- data/spec/dummy-3.1.3/lib/tasks/.gitkeep +0 -0
- data/spec/dummy-3.1.3/log/.gitkeep +0 -0
- data/spec/dummy-3.1.3/public/404.html +26 -0
- data/spec/dummy-3.1.3/public/422.html +26 -0
- data/spec/dummy-3.1.3/public/500.html +26 -0
- data/spec/dummy-3.1.3/public/favicon.ico +0 -0
- data/spec/dummy-3.1.3/public/index.html +241 -0
- data/spec/dummy-3.1.3/public/robots.txt +5 -0
- data/spec/dummy-3.1.3/script/rails +6 -0
- data/spec/dummy-3.1.3/spec/spec_helper.rb +32 -0
- data/spec/dummy-3.1.3/vendor/assets/stylesheets/.gitkeep +0 -0
- data/spec/dummy-3.1.3/vendor/plugins/.gitkeep +0 -0
- data/spec/lib/dump_rake/dump_reader_spec.rb +638 -0
- data/spec/lib/dump_rake/dump_spec.rb +291 -0
- data/spec/lib/dump_rake/dump_writer_spec.rb +328 -0
- data/spec/lib/dump_rake/env/filter_spec.rb +56 -0
- data/spec/lib/dump_rake/env_spec.rb +139 -0
- data/spec/lib/dump_rake/rails_root_spec.rb +45 -0
- data/spec/lib/dump_rake/table_manipulation_spec.rb +256 -0
- data/spec/lib/dump_rake_spec.rb +326 -0
- data/spec/recipes/dump_spec.rb +553 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +34 -0
- data/spec/tasks/assets_spec.rb +92 -0
- data/spec/tasks/dump_spec.rb +107 -0
- metadata +272 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# based on Timeout
|
|
2
|
+
|
|
3
|
+
module ContiniousTimeout
|
|
4
|
+
class TimeoutException < ::Exception
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
class RestartException < ::Exception
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class Deferer
|
|
11
|
+
def initialize(thread)
|
|
12
|
+
@thread = thread
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def defer
|
|
16
|
+
@thread.raise RestartException.new
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.timeout(sec)
|
|
21
|
+
begin
|
|
22
|
+
x = Thread.current
|
|
23
|
+
y = Thread.start do
|
|
24
|
+
1.times do
|
|
25
|
+
begin
|
|
26
|
+
sleep sec
|
|
27
|
+
rescue RestartException => e
|
|
28
|
+
retry
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
x.raise TimeoutException, "execution expired" if x.alive?
|
|
32
|
+
end
|
|
33
|
+
yield Deferer.new(y)
|
|
34
|
+
ensure
|
|
35
|
+
y.kill if y and y.alive?
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
class DumpRake
|
|
4
|
+
class Dump
|
|
5
|
+
include TableManipulation
|
|
6
|
+
def self.list(options = {})
|
|
7
|
+
dumps = Dir[File.join(DumpRake::RailsRoot, 'dump', options[:all] ? '*.*' : '*.tgz')].sort.select{ |path| File.file?(path) }.map{ |path| new(path) }
|
|
8
|
+
dumps = dumps.select{ |dump| dump.name[options[:like]] } if options[:like]
|
|
9
|
+
if options[:tags]
|
|
10
|
+
tags = get_filter_tags(options[:tags])
|
|
11
|
+
dumps = dumps.select{ |dump| (dump.tags & tags[:simple]).present? } if tags[:simple].present?
|
|
12
|
+
dumps = dumps.select{ |dump| (dump.tags & tags[:mandatory]) == tags[:mandatory] } if tags[:mandatory].present?
|
|
13
|
+
dumps = dumps.reject{ |dump| (dump.tags & tags[:forbidden]).present? } if tags[:forbidden].present?
|
|
14
|
+
end
|
|
15
|
+
dumps
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def initialize(path_or_options = {})
|
|
19
|
+
if path_or_options.is_a?(Hash)
|
|
20
|
+
options = path_or_options
|
|
21
|
+
|
|
22
|
+
name = Time.now.utc.strftime("%Y%m%d%H%M%S")
|
|
23
|
+
|
|
24
|
+
description = clean_description(options[:desc])
|
|
25
|
+
name += "-#{description}" unless description.blank?
|
|
26
|
+
|
|
27
|
+
tags = clean_tags(options[:tags])
|
|
28
|
+
name += "@#{tags * ','}" unless tags.empty?
|
|
29
|
+
|
|
30
|
+
tgz_name = "#{name}.tgz"
|
|
31
|
+
|
|
32
|
+
@path = options[:dir] ? Pathname(options[:dir]) + tgz_name : Pathname(tgz_name)
|
|
33
|
+
|
|
34
|
+
else
|
|
35
|
+
@path = Pathname(path_or_options)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
attr_reader :path
|
|
40
|
+
|
|
41
|
+
def tgz_path
|
|
42
|
+
path_with_ext('tgz')
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def tmp_path
|
|
46
|
+
path_with_ext('tmp')
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def ==(other)
|
|
50
|
+
path == other.path
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def parts
|
|
54
|
+
@parts ||=
|
|
55
|
+
if m = name.match(/^(\d{#{4+2+2 + 2+2+2}})(-[^@]+)?((?:@[^@]+)+)?\.(tmp|tgz)$/)
|
|
56
|
+
{
|
|
57
|
+
:time => m[1],
|
|
58
|
+
:desc => m[2] && m[2][1, m[2].length],
|
|
59
|
+
:tags => m[3] && m[3][1, m[3].length],
|
|
60
|
+
:ext => m[4]
|
|
61
|
+
}
|
|
62
|
+
else
|
|
63
|
+
{}
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def time
|
|
68
|
+
parts[:time] && Time.utc(*parts[:time].match(/(\d{4})#{'(\d{2})' * 5}/)[1..6])
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def description
|
|
72
|
+
clean_description(parts[:desc])
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def tags
|
|
76
|
+
clean_tags(parts[:tags])
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def ext
|
|
80
|
+
parts[:ext]
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def name
|
|
84
|
+
@name ||= File.basename(path)
|
|
85
|
+
end
|
|
86
|
+
alias to_s name
|
|
87
|
+
|
|
88
|
+
def size
|
|
89
|
+
File.size(path) rescue nil
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def human_size
|
|
93
|
+
number = size
|
|
94
|
+
return nil if number.nil?
|
|
95
|
+
degree = 0
|
|
96
|
+
symbols = %W[B K M G T]
|
|
97
|
+
while number >= 1000 && degree < symbols.length - 1
|
|
98
|
+
degree += 1
|
|
99
|
+
number /= 1024.0
|
|
100
|
+
end
|
|
101
|
+
"#{'%.2f' % number}#{symbols[degree]}"
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def inspect
|
|
105
|
+
"#<%s:0x%x %s>" % [self.class, object_id, path.to_s.sub(/^.+(?=..\/[^\/]*$)/, '…')]
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def lock
|
|
109
|
+
if lock = File.open(path, 'r')
|
|
110
|
+
begin
|
|
111
|
+
if lock.flock(File::LOCK_EX | File::LOCK_NB)
|
|
112
|
+
yield
|
|
113
|
+
end
|
|
114
|
+
ensure
|
|
115
|
+
lock.flock(File::LOCK_UN)
|
|
116
|
+
lock.close
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
protected
|
|
122
|
+
|
|
123
|
+
def assets_root_link
|
|
124
|
+
prefix = 'assets'
|
|
125
|
+
Dir.mktmpdir do |dir|
|
|
126
|
+
Dir.chdir(dir) do
|
|
127
|
+
File.symlink(DumpRake::RailsRoot, prefix)
|
|
128
|
+
begin
|
|
129
|
+
yield dir, prefix
|
|
130
|
+
ensure
|
|
131
|
+
File.unlink(prefix)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def path_with_ext(ext)
|
|
138
|
+
Pathname(path.to_s.sub(/#{parts[:ext]}$/, ext))
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
module CleanNParse
|
|
142
|
+
def clean_str(str, additional = nil)
|
|
143
|
+
str.to_s.strip.gsub(/\s+/, ' ').gsub(/[^A-Za-z0-9 \-_#{Regexp.escape(additional.to_s) if additional}]+/, '_')
|
|
144
|
+
end
|
|
145
|
+
def clean_description(description)
|
|
146
|
+
clean_str(description, '()#')[0, 50].strip
|
|
147
|
+
end
|
|
148
|
+
def clean_tag(tag)
|
|
149
|
+
clean_str(tag).downcase.sub(/^\-+/, '')[0, 20].strip
|
|
150
|
+
end
|
|
151
|
+
def clean_tags(tags)
|
|
152
|
+
tags.to_s.split(',').map{ |tag| clean_tag(tag) }.uniq.reject(&:blank?).sort
|
|
153
|
+
end
|
|
154
|
+
def get_filter_tags(tags)
|
|
155
|
+
groups = Hash.new{ |hash, key| hash[key] = SortedSet.new }
|
|
156
|
+
tags.to_s.split(',').each do |tag|
|
|
157
|
+
if m = tag.strip.match(/^(\-|\+)?(.*)$/)
|
|
158
|
+
type = {'+' => :mandatory, '-' => :forbidden}[m[1]] || :simple
|
|
159
|
+
unless (claned_tag = clean_tag(m[2])).blank?
|
|
160
|
+
groups[type] << claned_tag
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
[:simple, :mandatory].each do |type|
|
|
165
|
+
if (clashing = (groups[type] & groups[:forbidden])).present?
|
|
166
|
+
raise "#{type} tags clashes with forbidden ones: #{clashing}"
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
groups.each_with_object({}){ |(key, value), hsh| hsh[key] = value.to_a }
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
include CleanNParse
|
|
173
|
+
extend CleanNParse
|
|
174
|
+
end
|
|
175
|
+
end
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
class DumpRake
|
|
2
|
+
class DumpReader < Dump
|
|
3
|
+
attr_reader :stream, :config
|
|
4
|
+
|
|
5
|
+
def self.restore(path)
|
|
6
|
+
new(path).open do |dump|
|
|
7
|
+
ActiveRecord::Base.logger.silence do
|
|
8
|
+
dump.read_config
|
|
9
|
+
dump.migrate_down
|
|
10
|
+
dump.read_schema
|
|
11
|
+
|
|
12
|
+
dump.read_tables
|
|
13
|
+
dump.read_assets
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class Summary
|
|
19
|
+
attr_reader :text
|
|
20
|
+
alias_method :to_s, :text
|
|
21
|
+
def initialize
|
|
22
|
+
@text = ''
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def header(header)
|
|
26
|
+
@text << " #{header}:\n"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def data(entries)
|
|
30
|
+
entries.each do |entry|
|
|
31
|
+
@text << " #{entry}\n"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# from ActionView::Helpers::TextHelper
|
|
36
|
+
def self.pluralize(count, singular)
|
|
37
|
+
"#{count} #{count == 1 ? singular : singular.pluralize}"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def self.summary(path, options = {})
|
|
42
|
+
new(path).open do |dump|
|
|
43
|
+
dump.read_config
|
|
44
|
+
|
|
45
|
+
sum = Summary.new
|
|
46
|
+
|
|
47
|
+
tables = dump.config[:tables]
|
|
48
|
+
sum.header 'Tables'
|
|
49
|
+
sum.data tables.sort.map{ |(table, rows)|
|
|
50
|
+
"#{table}: #{Summary.pluralize(rows, 'row')}"
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
assets = dump.config[:assets]
|
|
54
|
+
if assets.present?
|
|
55
|
+
sum.header 'Assets'
|
|
56
|
+
sum.data assets.sort.map{ |entry|
|
|
57
|
+
if String === entry
|
|
58
|
+
entry
|
|
59
|
+
else
|
|
60
|
+
asset, paths = entry
|
|
61
|
+
if Hash === paths
|
|
62
|
+
"#{asset}: #{Summary.pluralize paths[:files], 'file'} (#{Summary.pluralize paths[:total], 'entry'} total)"
|
|
63
|
+
else
|
|
64
|
+
"#{asset}: #{Summary.pluralize paths, 'entry'}"
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
}
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
if options[:schema]
|
|
71
|
+
sum.header 'Schema'
|
|
72
|
+
sum.data dump.schema.split("\n")
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
sum
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def open
|
|
80
|
+
Zlib::GzipReader.open(path) do |gzip|
|
|
81
|
+
Archive::Tar::Minitar.open(gzip, 'r') do |stream|
|
|
82
|
+
@stream = stream
|
|
83
|
+
yield(self)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def find_entry(matcher)
|
|
89
|
+
stream.each do |entry|
|
|
90
|
+
if matcher === entry.full_name
|
|
91
|
+
# we can not return entry - after exiting stream.each the entry will be invalid and will read from tar start
|
|
92
|
+
return yield(entry)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def read_entry(matcher)
|
|
98
|
+
find_entry(matcher) do |entry|
|
|
99
|
+
return entry.read
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def read_entry_to_file(matcher)
|
|
104
|
+
find_entry(matcher) do |entry|
|
|
105
|
+
Tempfile.open('dumper') do |temp|
|
|
106
|
+
temp.write(entry.read(4096)) until entry.eof?
|
|
107
|
+
temp.rewind
|
|
108
|
+
yield(temp)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def read_config
|
|
114
|
+
@config = Marshal.load(read_entry('config'))
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def migrate_down
|
|
118
|
+
case
|
|
119
|
+
when DumpRake::Env.downcase(:migrate_down) == 'reset'
|
|
120
|
+
Rake::Task['db:drop'].invoke
|
|
121
|
+
Rake::Task['db:create'].invoke
|
|
122
|
+
when !DumpRake::Env.no?(:migrate_down)
|
|
123
|
+
if avaliable_tables.include?('schema_migrations')
|
|
124
|
+
find_entry("schema_migrations.dump") do |entry|
|
|
125
|
+
migrated = table_rows('schema_migrations').map{ |row| row['version'] }
|
|
126
|
+
|
|
127
|
+
dump_migrations = []
|
|
128
|
+
Marshal.load(entry) # skip header
|
|
129
|
+
dump_migrations << Marshal.load(entry).first until entry.eof?
|
|
130
|
+
|
|
131
|
+
migrate_down = (migrated - dump_migrations)
|
|
132
|
+
|
|
133
|
+
unless migrate_down.empty?
|
|
134
|
+
migrate_down.reverse.with_progress('Migrating down') do |version|
|
|
135
|
+
DumpRake::Env.with_env('VERSION' => version) do
|
|
136
|
+
Rake::Task['db:migrate:down'].tap do |task|
|
|
137
|
+
begin
|
|
138
|
+
task.invoke
|
|
139
|
+
rescue ActiveRecord::IrreversibleMigration
|
|
140
|
+
$stderr.puts "Irreversible migration: #{version}"
|
|
141
|
+
end
|
|
142
|
+
task.reenable
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def restore_schema?
|
|
153
|
+
!DumpRake::Env.no?(:restore_schema)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def read_schema
|
|
157
|
+
if restore_schema?
|
|
158
|
+
read_entry_to_file('schema.rb') do |f|
|
|
159
|
+
DumpRake::Env.with_env('SCHEMA' => f.path) do
|
|
160
|
+
Rake::Task['db:schema:load'].invoke
|
|
161
|
+
end
|
|
162
|
+
Rake::Task['db:schema:dump'].invoke
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def schema
|
|
168
|
+
read_entry('schema.rb')
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def read_tables
|
|
172
|
+
verify_connection
|
|
173
|
+
config[:tables].with_progress('Tables') do |table, rows|
|
|
174
|
+
if (restore_schema? && schema_tables.include?(table)) || DumpRake::Env.filter(:restore_tables).pass?(table)
|
|
175
|
+
read_table(table, rows)
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def read_table(table, rows_count)
|
|
181
|
+
find_entry("#{table}.dump") do |entry|
|
|
182
|
+
table_sql = quote_table_name(table)
|
|
183
|
+
clear_table(table_sql)
|
|
184
|
+
|
|
185
|
+
columns = Marshal.load(entry)
|
|
186
|
+
columns_sql = columns_insert_sql(columns)
|
|
187
|
+
Progress.start(table, rows_count) do
|
|
188
|
+
until entry.eof?
|
|
189
|
+
rows_sql = []
|
|
190
|
+
1000.times do
|
|
191
|
+
rows_sql << values_insert_sql(Marshal.load(entry)) unless entry.eof?
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
begin
|
|
195
|
+
insert_into_table(table_sql, columns_sql, rows_sql)
|
|
196
|
+
Progress.step(rows_sql.length)
|
|
197
|
+
rescue
|
|
198
|
+
rows_sql.each do |row_sql|
|
|
199
|
+
insert_into_table(table_sql, columns_sql, row_sql)
|
|
200
|
+
Progress.step
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
fix_sequence!(table)
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def read_assets
|
|
210
|
+
unless config[:assets].blank?
|
|
211
|
+
assets = config[:assets]
|
|
212
|
+
if Hash === assets
|
|
213
|
+
assets_count = assets.values.sum{ |value| Hash === value ? value[:total] : value }
|
|
214
|
+
assets_paths = assets.keys
|
|
215
|
+
else
|
|
216
|
+
assets_count, assets_paths = nil, assets
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
if DumpRake::Env[:restore_assets]
|
|
220
|
+
assets_paths.each do |asset|
|
|
221
|
+
DumpRake::Assets.glob_asset_children(asset, '**/*').reverse.each do |child|
|
|
222
|
+
if read_asset?(child, DumpRake::RailsRoot)
|
|
223
|
+
case
|
|
224
|
+
when File.file?(child)
|
|
225
|
+
File.unlink(child)
|
|
226
|
+
when File.directory?(child)
|
|
227
|
+
begin
|
|
228
|
+
Dir.unlink(child)
|
|
229
|
+
rescue Errno::ENOTEMPTY
|
|
230
|
+
nil
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
else
|
|
237
|
+
DumpRake::Env.with_env(:assets => assets_paths.join(':')) do
|
|
238
|
+
Rake::Task['assets:delete'].invoke
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
read_assets_entries(assets_paths, assets_count) do |stream, root, entry, prefix|
|
|
243
|
+
if !DumpRake::Env[:restore_assets] || read_asset?(entry.full_name, prefix)
|
|
244
|
+
stream.extract_entry(root, entry)
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def read_asset?(path, prefix)
|
|
251
|
+
DumpRake::Env.filter(:restore_assets, DumpRake::Assets::SPLITTER).custom_pass? do |value|
|
|
252
|
+
File.fnmatch(File.join(prefix, value), path) ||
|
|
253
|
+
File.fnmatch(File.join(prefix, value, '**'), path)
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def read_assets_entries(assets_paths, assets_count)
|
|
258
|
+
Progress.start('Assets', assets_count || 1) do
|
|
259
|
+
found_assets = false
|
|
260
|
+
# old style — in separate tar
|
|
261
|
+
find_entry('assets.tar') do |assets_tar|
|
|
262
|
+
def assets_tar.rewind
|
|
263
|
+
# rewind will fail - it must go to center of gzip
|
|
264
|
+
# also we don't need it - this is last step in dump restore
|
|
265
|
+
end
|
|
266
|
+
Archive::Tar::Minitar.open(assets_tar) do |inp|
|
|
267
|
+
inp.each do |entry|
|
|
268
|
+
yield inp, DumpRake::RailsRoot, entry, nil
|
|
269
|
+
Progress.step if assets_count
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
found_assets = true
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
unless found_assets
|
|
276
|
+
# new style — in same tar
|
|
277
|
+
assets_root_link do |tmpdir, prefix|
|
|
278
|
+
stream.each do |entry|
|
|
279
|
+
if entry.full_name.starts_with?("#{prefix}/")
|
|
280
|
+
yield stream, tmpdir, entry, prefix
|
|
281
|
+
Progress.step if assets_count
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
end
|