diff options
-rw-r--r-- | CHANGELOG | 1 | ||||
-rw-r--r-- | app/services/projects/import_export/export_service.rb | 6 | ||||
-rw-r--r-- | app/uploaders/avatar_uploader.rb | 4 | ||||
-rw-r--r-- | lib/gitlab/import_export/avatar_restorer.rb | 31 | ||||
-rw-r--r-- | lib/gitlab/import_export/avatar_saver.rb | 31 | ||||
-rw-r--r-- | lib/gitlab/import_export/command_line_util.rb | 9 | ||||
-rw-r--r-- | lib/gitlab/import_export/importer.rb | 6 | ||||
-rw-r--r-- | lib/gitlab/import_export/uploads_saver.rb | 8 | ||||
-rw-r--r-- | spec/lib/gitlab/import_export/avatar_restorer_spec.rb | 25 | ||||
-rw-r--r-- | spec/lib/gitlab/import_export/avatar_saver_spec.rb | 27 |
10 files changed, 140 insertions, 8 deletions
diff --git a/CHANGELOG b/CHANGELOG index 93a47b87d63..9c8c39a758f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -130,6 +130,7 @@ v 8.10.0 (unreleased) - Render only commit message title in builds (Katarzyna Kobierska Ula Budziszewska) - Allow bulk (un)subscription from issues in issue index - Fix MR diff encoding issues exporting GitLab projects + - Export and import avatar as part of project import/export v 8.9.6 - Fix importing of events under notes for GitLab projects. !5154 diff --git a/app/services/projects/import_export/export_service.rb b/app/services/projects/import_export/export_service.rb index 998789d64d2..06252c7b625 100644 --- a/app/services/projects/import_export/export_service.rb +++ b/app/services/projects/import_export/export_service.rb @@ -9,7 +9,7 @@ module Projects private def save_all - if [version_saver, project_tree_saver, uploads_saver, repo_saver, wiki_repo_saver].all?(&:save) + if [version_saver, avatar_saver, project_tree_saver, uploads_saver, repo_saver, wiki_repo_saver].all?(&:save) Gitlab::ImportExport::Saver.save(project: project, shared: @shared) notify_success else @@ -21,6 +21,10 @@ module Projects Gitlab::ImportExport::VersionSaver.new(shared: @shared) end + def avatar_saver + Gitlab::ImportExport::AvatarSaver.new(project: project, shared: @shared) + end + def project_tree_saver Gitlab::ImportExport::ProjectTreeSaver.new(project: project, shared: @shared) end diff --git a/app/uploaders/avatar_uploader.rb b/app/uploaders/avatar_uploader.rb index 6135c3ad96f..03d9329a14e 100644 --- a/app/uploaders/avatar_uploader.rb +++ b/app/uploaders/avatar_uploader.rb @@ -14,4 +14,8 @@ class AvatarUploader < CarrierWave::Uploader::Base def reset_events_cache(file) model.reset_events_cache if model.is_a?(User) end + + def exists? + model.avatar.file && model.avatar.file.exists? + end end diff --git a/lib/gitlab/import_export/avatar_restorer.rb b/lib/gitlab/import_export/avatar_restorer.rb new file mode 100644 index 00000000000..352539eb594 --- /dev/null +++ b/lib/gitlab/import_export/avatar_restorer.rb @@ -0,0 +1,31 @@ +module Gitlab + module ImportExport + class AvatarRestorer + + def initialize(project:, shared:) + @project = project + @shared = shared + end + + def restore + return true unless avatar_export_file + + @project.avatar = File.open(avatar_export_file) + @project.save! + rescue => e + @shared.error(e) + false + end + + private + + def avatar_export_file + @avatar_export_file ||= Dir["#{avatar_export_path}/*"].first + end + + def avatar_export_path + File.join(@shared.export_path, 'avatar') + end + end + end +end diff --git a/lib/gitlab/import_export/avatar_saver.rb b/lib/gitlab/import_export/avatar_saver.rb new file mode 100644 index 00000000000..998c21e2586 --- /dev/null +++ b/lib/gitlab/import_export/avatar_saver.rb @@ -0,0 +1,31 @@ +module Gitlab + module ImportExport + class AvatarSaver + include Gitlab::ImportExport::CommandLineUtil + + def initialize(project:, shared:) + @project = project + @shared = shared + end + + def save + return true unless @project.avatar.exists? + + copy_files(avatar_path, avatar_export_path) + rescue => e + @shared.error(e) + false + end + + private + + def avatar_export_path + File.join(@shared.export_path, 'avatar', @project.avatar_identifier) + end + + def avatar_path + @project.avatar.path + end + end + end +end diff --git a/lib/gitlab/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb index 2249904145c..5dd0e34c18e 100644 --- a/lib/gitlab/import_export/command_line_util.rb +++ b/lib/gitlab/import_export/command_line_util.rb @@ -36,6 +36,15 @@ module Gitlab def git_bin_path Gitlab.config.git.bin_path end + + def copy_files(source, destination) + # if we are copying files, create the destination folder + destination_folder = File.file?(source) ? File.dirname(destination) : destination + + FileUtils.mkdir_p(destination_folder) + FileUtils.copy_entry(source, destination) + true + end end end end diff --git a/lib/gitlab/import_export/importer.rb b/lib/gitlab/import_export/importer.rb index 6b69a653f12..e9ee47fc090 100644 --- a/lib/gitlab/import_export/importer.rb +++ b/lib/gitlab/import_export/importer.rb @@ -9,7 +9,7 @@ module Gitlab end def execute - if import_file && check_version! && [project_tree, repo_restorer, wiki_restorer, uploads_restorer].all?(&:restore) + if import_file && check_version! && [project_tree, avatar_restorer, repo_restorer, wiki_restorer, uploads_restorer].all?(&:restore) project_tree.restored_project else raise Projects::ImportService::Error.new(@shared.errors.join(', ')) @@ -35,6 +35,10 @@ module Gitlab project: @project) end + def avatar_restorer + Gitlab::ImportExport::AvatarRestorer.new(project: project_tree.restored_project, shared: @shared) + end + def repo_restorer Gitlab::ImportExport::RepoRestorer.new(path_to_bundle: repo_path, shared: @shared, diff --git a/lib/gitlab/import_export/uploads_saver.rb b/lib/gitlab/import_export/uploads_saver.rb index d6f4fa57510..62a2553675c 100644 --- a/lib/gitlab/import_export/uploads_saver.rb +++ b/lib/gitlab/import_export/uploads_saver.rb @@ -1,6 +1,8 @@ module Gitlab module ImportExport class UploadsSaver + include Gitlab::ImportExport::CommandLineUtil + def initialize(project:, shared:) @project = project @shared = shared @@ -17,12 +19,6 @@ module Gitlab private - def copy_files(source, destination) - FileUtils.mkdir_p(destination) - FileUtils.copy_entry(source, destination) - true - end - def uploads_export_path File.join(@shared.export_path, 'uploads') end diff --git a/spec/lib/gitlab/import_export/avatar_restorer_spec.rb b/spec/lib/gitlab/import_export/avatar_restorer_spec.rb new file mode 100644 index 00000000000..5ae178414cc --- /dev/null +++ b/spec/lib/gitlab/import_export/avatar_restorer_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +describe Gitlab::ImportExport::AvatarRestorer, lib: true do + let(:shared) { Gitlab::ImportExport::Shared.new(relative_path: 'test') } + let(:project) { create(:empty_project) } + + before do + allow_any_instance_of(described_class).to receive(:avatar_export_file) + .and_return(Rails.root + "spec/fixtures/dk.png") + end + + after do + project.remove_avatar! + end + + it 'restores a project avatar' do + expect(described_class.new(project: project, shared: shared).restore).to be true + end + + it 'saves the avatar into the project' do + described_class.new(project: project, shared: shared).restore + + expect(project.reload.avatar.file.exists?).to be true + end +end diff --git a/spec/lib/gitlab/import_export/avatar_saver_spec.rb b/spec/lib/gitlab/import_export/avatar_saver_spec.rb new file mode 100644 index 00000000000..d6ee94442cb --- /dev/null +++ b/spec/lib/gitlab/import_export/avatar_saver_spec.rb @@ -0,0 +1,27 @@ +require 'spec_helper' + +describe Gitlab::ImportExport::AvatarSaver, lib: true do + let(:shared) { Gitlab::ImportExport::Shared.new(relative_path: 'test') } + let(:export_path) { "#{Dir::tmpdir}/project_tree_saver_spec" } + let(:project_with_avatar) { create(:empty_project, avatar: fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png")) } + let(:project) { create(:empty_project) } + + before do + FileUtils.mkdir_p("#{shared.export_path}/avatar/") + allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path) + end + + after do + FileUtils.rm_rf("#{shared.export_path}/avatar") + end + + it 'saves a project avatar' do + described_class.new(project: project_with_avatar, shared: shared).save + + expect(File).to exist("#{shared.export_path}/avatar/dk.png") + end + + it 'is fine not to have an avatar' do + expect(described_class.new(project: project, shared: shared).save).to be true + end +end |