mirror of
https://github.com/discourse/discourse.git
synced 2025-02-20 06:48:47 +08:00
FEATURE: new 'uploads:migrate_to_new_pattern' rake task
This commit is contained in:
parent
9ded21e4c6
commit
5e527178b9
|
@ -277,3 +277,141 @@ def regenerate_missing_optimized
|
||||||
missing_uploads.sort.each { |u| puts u }
|
missing_uploads.sort.each { |u| puts u }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
task "uploads:migrate_to_new_pattern" => :environment do
|
||||||
|
ENV["RAILS_DB"] ? migrate_to_new_pattern : migrate_to_new_pattern_all_sites
|
||||||
|
end
|
||||||
|
|
||||||
|
def migrate_to_new_pattern_all_sites
|
||||||
|
RailsMultisite::ConnectionManagement.each_connection { migrate_to_new_pattern }
|
||||||
|
end
|
||||||
|
|
||||||
|
def migrate_to_new_pattern
|
||||||
|
db = RailsMultisite::ConnectionManagement.current_db
|
||||||
|
|
||||||
|
puts "Migrating uploads to new pattern for '#{db}'..."
|
||||||
|
migrate_uploads_to_new_pattern
|
||||||
|
|
||||||
|
puts "Migrating optimized images to new pattern for '#{db}'..."
|
||||||
|
migrate_optimized_images_to_new_pattern
|
||||||
|
|
||||||
|
puts "Done!"
|
||||||
|
end
|
||||||
|
|
||||||
|
def migrate_uploads_to_new_pattern
|
||||||
|
if Upload.where(sha1: nil).exists?
|
||||||
|
puts "Computing missing SHAs..."
|
||||||
|
|
||||||
|
Upload.where(sha1: nil).find_each do |upload|
|
||||||
|
path = Discourse.store.path_for(upload)
|
||||||
|
size = File.size(path) rescue 0
|
||||||
|
if size > 0
|
||||||
|
upload.sha1 = Digest::SHA1.file(path).hexdigest
|
||||||
|
upload.save
|
||||||
|
putc "."
|
||||||
|
else
|
||||||
|
upload.destroy
|
||||||
|
putc "X"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
puts
|
||||||
|
end
|
||||||
|
|
||||||
|
puts "Moving uploads to new location..."
|
||||||
|
Upload.where.not(sha1: nil)
|
||||||
|
.where("url LIKE '/uploads/%'")
|
||||||
|
.where("url NOT LIKE '/uploads/%/original/%'")
|
||||||
|
.find_each do |upload|
|
||||||
|
path = Discourse.store.path_for(upload)
|
||||||
|
if File.exists?(path)
|
||||||
|
file = File.open(path)
|
||||||
|
# copy file to new location
|
||||||
|
url = Discourse.store.store_upload(file, upload)
|
||||||
|
file.try(:close!) rescue nil
|
||||||
|
# remap URLs
|
||||||
|
remap(upload.url, url)
|
||||||
|
# remove old file
|
||||||
|
FileUtils.rm(path, force: true) rescue nil
|
||||||
|
putc "."
|
||||||
|
else
|
||||||
|
# upload.destroy
|
||||||
|
putc "X"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
puts
|
||||||
|
end
|
||||||
|
|
||||||
|
def migrate_optimized_images_to_new_pattern
|
||||||
|
if OptimizedImage.where(sha1: nil).exists?
|
||||||
|
puts "Computing missing SHAs..."
|
||||||
|
|
||||||
|
OptimizedImage.where(sha1: nil).find_each do |optimized_image|
|
||||||
|
path = Discourse.store.path_for(optimized_image)
|
||||||
|
size = File.size(path) rescue 0
|
||||||
|
if size > 0
|
||||||
|
optimized_image.sha1 = Digest::SHA1.file(path).hexdigest
|
||||||
|
optimized_image.save
|
||||||
|
putc "."
|
||||||
|
else
|
||||||
|
optimized_image.destroy
|
||||||
|
putc "X"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
puts
|
||||||
|
end
|
||||||
|
|
||||||
|
puts "Moving optimized images to new location..."
|
||||||
|
OptimizedImage.where.not(sha1: nil)
|
||||||
|
.where("width > 0 AND height > 0")
|
||||||
|
.where("url LIKE '/uploads/%/_optimized/%'")
|
||||||
|
.where("url NOT LIKE '/uploads/%/optimized/%'")
|
||||||
|
.find_each do |optimized_image|
|
||||||
|
path = Discourse.store.path_for(optimized_image)
|
||||||
|
if File.exists?(path)
|
||||||
|
file = File.open(path)
|
||||||
|
# copy file to new location
|
||||||
|
url = Discourse.store.store_optimized_image(file, optimized_image)
|
||||||
|
file.try(:close!) rescue nil
|
||||||
|
# remap URLs
|
||||||
|
remap(optimized_image.url, url)
|
||||||
|
# remove old file
|
||||||
|
FileUtils.rm(path, force: true) rescue nil
|
||||||
|
putc "."
|
||||||
|
else
|
||||||
|
optimized_image.destroy
|
||||||
|
putc "X"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
puts
|
||||||
|
end
|
||||||
|
|
||||||
|
REMAP_SQL ||= "
|
||||||
|
SELECT table_name, column_name
|
||||||
|
FROM information_schema.columns
|
||||||
|
WHERE table_schema = 'public'
|
||||||
|
AND is_updatable = 'YES'
|
||||||
|
AND (data_type LIKE 'char%' OR data_type LIKE 'text%')
|
||||||
|
ORDER BY table_name, column_name
|
||||||
|
"
|
||||||
|
|
||||||
|
def remap(from, to)
|
||||||
|
connection ||= ActiveRecord::Base.connection.raw_connection
|
||||||
|
remappable_columns ||= connection.async_exec(REMAP_SQL).to_a
|
||||||
|
|
||||||
|
remappable_columns.each do |rc|
|
||||||
|
table_name = rc["table_name"]
|
||||||
|
column_name = rc["column_name"]
|
||||||
|
begin
|
||||||
|
connection.async_exec("
|
||||||
|
UPDATE #{table_name}
|
||||||
|
SET #{column_name} = REPLACE(#{column_name}, $1, $2)
|
||||||
|
WHERE #{column_name} IS NOT NULL
|
||||||
|
AND #{column_name} <> REPLACE(#{column_name}, $1, $2)", [from, to])
|
||||||
|
rescue
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
Loading…
Reference in New Issue
Block a user