Merge branch '14256-upload-destroy-removes-file' into 'master'
Uploads should delete files when destroyed Closes #14256 See merge request gitlab-org/gitlab-ce!16799
This commit is contained in:
commit
9ab4c5b735
5 changed files with 54 additions and 0 deletions
|
@ -12,6 +12,10 @@ class Upload < ActiveRecord::Base
|
|||
before_save :calculate_checksum!, if: :foreground_checksummable?
|
||||
after_commit :schedule_checksum, if: :checksummable?
|
||||
|
||||
# as the FileUploader is not mounted, the default CarrierWave ActiveRecord
|
||||
# hooks are not executed and the file will not be deleted
|
||||
after_destroy :delete_file!, if: -> { uploader_class <= FileUploader }
|
||||
|
||||
def self.hexdigest(path)
|
||||
Digest::SHA256.file(path).hexdigest
|
||||
end
|
||||
|
@ -49,6 +53,10 @@ class Upload < ActiveRecord::Base
|
|||
|
||||
private
|
||||
|
||||
def delete_file!
|
||||
build_uploader.remove!
|
||||
end
|
||||
|
||||
def checksummable?
|
||||
checksum.nil? && local? && exist?
|
||||
end
|
||||
|
|
|
@ -15,6 +15,8 @@ class FileUploader < GitlabUploader
|
|||
|
||||
storage :file
|
||||
|
||||
after :remove, :prune_store_dir
|
||||
|
||||
def self.root
|
||||
File.join(options.storage_path, 'uploads')
|
||||
end
|
||||
|
@ -140,6 +142,10 @@ class FileUploader < GitlabUploader
|
|||
end
|
||||
end
|
||||
|
||||
def prune_store_dir
|
||||
storage.delete_dir!(store_dir) # only remove when empty
|
||||
end
|
||||
|
||||
def markdown_name
|
||||
(image_or_video? ? File.basename(filename, File.extname(filename)) : filename).gsub("]", "\\]")
|
||||
end
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Deleting an upload will correctly clean up the filesystem.
|
||||
merge_request: 16799
|
||||
author:
|
||||
type: fixed
|
|
@ -43,6 +43,18 @@ describe Upload do
|
|||
.to(a_string_matching(/\A\h{64}\z/))
|
||||
end
|
||||
end
|
||||
|
||||
describe 'after_destroy' do
|
||||
context 'uploader is FileUploader-based' do
|
||||
subject { create(:upload, :issuable_upload) }
|
||||
|
||||
it 'calls delete_file!' do
|
||||
is_expected.to receive(:delete_file!)
|
||||
|
||||
subject.destroy
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#absolute_path' do
|
||||
|
|
|
@ -48,6 +48,29 @@ describe FileUploader do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'callbacks' do
|
||||
describe '#prune_store_dir after :remove' do
|
||||
before do
|
||||
uploader.store!(fixture_file_upload('spec/fixtures/doc_sample.txt'))
|
||||
end
|
||||
|
||||
def store_dir
|
||||
File.expand_path(uploader.store_dir, uploader.root)
|
||||
end
|
||||
|
||||
it 'is called' do
|
||||
expect(uploader).to receive(:prune_store_dir).once
|
||||
|
||||
uploader.remove!
|
||||
end
|
||||
|
||||
it 'prune the store directory' do
|
||||
expect { uploader.remove! }
|
||||
.to change { File.exist?(store_dir) }.from(true).to(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#secret' do
|
||||
it 'generates a secret if none is provided' do
|
||||
expect(described_class).to receive(:generate_secret).and_return('secret')
|
||||
|
|
Loading…
Reference in a new issue