diff options
author | Grzegorz Bizon <grzesiek.bizon@gmail.com> | 2016-03-24 12:28:43 +0100 |
---|---|---|
committer | Grzegorz Bizon <grzesiek.bizon@gmail.com> | 2016-03-30 10:44:18 +0200 |
commit | 701976e0815c273ff4a4c6e4d3489db0ce2f0860 (patch) | |
tree | e519cfebe16a9684bb6162421c2be159243142ba | |
parent | cff3497f2c06dd4e1785af3c844040ed7939dcb0 (diff) | |
download | gitlab-ce-701976e0815c273ff4a4c6e4d3489db0ce2f0860.tar.gz |
Add uploads rewriter and use it when moving issue
-rw-r--r-- | app/services/issues/move_service.rb | 39 | ||||
-rw-r--r-- | lib/gitlab/gfm/uploads_rewriter.rb | 56 | ||||
-rw-r--r-- | spec/lib/gitlab/gfm/uploads_rewriter_spec.rb | 49 | ||||
-rw-r--r-- | spec/services/issues/move_service_spec.rb | 19 |
4 files changed, 151 insertions, 12 deletions
diff --git a/app/services/issues/move_service.rb b/app/services/issues/move_service.rb index a5efb21fab6..e15e25ee536 100644 --- a/app/services/issues/move_service.rb +++ b/app/services/issues/move_service.rb @@ -43,7 +43,7 @@ module Issues def create_new_issue new_params = { id: nil, iid: nil, label_ids: [], milestone: nil, project: @new_project, author: @old_issue.author, - description: unfold_references(@old_issue.description) } + description: rewrite_content(@old_issue.description) } new_params = @old_issue.serializable_hash.merge(new_params) CreateService.new(@new_project, @current_user, new_params).execute @@ -53,7 +53,7 @@ module Issues @old_issue.notes.find_each do |note| new_note = note.dup new_params = { project: @new_project, noteable: @new_issue, - note: unfold_references(new_note.note), + note: rewrite_content(new_note.note), created_at: note.created_at, updated_at: note.updated_at } @@ -61,6 +61,29 @@ module Issues end end + def rewrite_content(content) + rewrite_uploads( + unfold_references(content) + ) + end + + def unfold_references(content) + return unless content + + rewriter = Gitlab::Gfm::ReferenceRewriter.new(content, @old_project, + @current_user) + rewriter.rewrite(@new_project) + end + + def rewrite_uploads(content) + return unless content + + rewriter = Gitlab::Gfm::UploadsRewriter.new(content, @old_project, + @current_user) + return content unless rewriter.has_uploads? + rewriter.rewrite(@new_project) + end + def close_issue close_service = CloseService.new(@old_project, @current_user) close_service.execute(@old_issue, notifications: false, system_note: false) @@ -78,20 +101,12 @@ module Issues direction: :to) end - def unfold_references(content) - return unless content - - rewriter = Gitlab::Gfm::ReferenceRewriter.new(content, @old_project, - @current_user) - rewriter.rewrite(@new_project) + def mark_as_moved + @old_issue.update(moved_to: @new_issue) end def notify_participants notification_service.issue_moved(@old_issue, @new_issue, @current_user) end - - def mark_as_moved - @old_issue.update(moved_to: @new_issue) - end end end diff --git a/lib/gitlab/gfm/uploads_rewriter.rb b/lib/gitlab/gfm/uploads_rewriter.rb new file mode 100644 index 00000000000..778b6fe9f9d --- /dev/null +++ b/lib/gitlab/gfm/uploads_rewriter.rb @@ -0,0 +1,56 @@ +module Gitlab + module Gfm + ## + # Class that rewrites markdown links for uploads + # + # Using a pattern defined in `FileUploader` copies files to a new project + # and rewrites all links to uploads in ain a given text. + # + class UploadsRewriter + def initialize(text, source_project, _current_user) + @text = text + @source_project = source_project + @pattern = FileUploader::MARKDOWN_PATTERN + end + + def rewrite(target_project) + return unless @text + + new_uploader = file_uploader(target_project) + @text.gsub(@pattern) do |markdown_link| + old_file = find_file(@source_project, $~[:secret], $~[:file]) + return markdown_link unless old_file.exists? + + new_uploader.store!(old_file) + new_uploader.to_h[:markdown] + end + end + + def has_uploads? + !(@text =~ @pattern).nil? + end + + def files + referenced_files = @text.scan(@pattern).map do + find_file(@source_project, $~[:secret], $~[:file]) + end + + referenced_files.compact.select(&:exists?) + end + + private + + def find_file(project, secret, file) + uploader = file_uploader(project, secret) + uploader.retrieve_from_store!(file) + uploader.file + end + + def file_uploader(*args) + uploader = FileUploader.new(*args) + uploader.define_singleton_method(:move_to_store) { false } + uploader + end + end + end +end diff --git a/spec/lib/gitlab/gfm/uploads_rewriter_spec.rb b/spec/lib/gitlab/gfm/uploads_rewriter_spec.rb new file mode 100644 index 00000000000..7027954ef27 --- /dev/null +++ b/spec/lib/gitlab/gfm/uploads_rewriter_spec.rb @@ -0,0 +1,49 @@ +require 'spec_helper' + +describe Gitlab::Gfm::UploadsRewriter do + let(:user) { create(:user) } + let(:old_project) { create(:project) } + let(:new_project) { create(:project) } + let(:rewriter) { described_class.new(text, old_project, user) } + + context 'text contains links to uploads' do + let(:path) { Rails.root + 'spec/fixtures/rails_sample.jpg' } + let(:file) { fixture_file_upload(path, 'image/jpg') } + let(:uploader) { FileUploader.new(old_project) } + let!(:store) { uploader.store!(file) } # TODO, see #xxx (carrierwave issue) + let(:markdown) { uploader.to_h[:markdown] } + let(:text) { "Text and #{markdown}"} + + describe '#rewrite' do + let!(:new_text) { rewriter.rewrite(new_project) } + let(:new_rewriter) { described_class.new(new_text, new_project, user) } + let(:old_file) { rewriter.files.first } + let(:new_file) { new_rewriter.files.first } + + it 'rewrites content' do + expect(new_text).to_not eq text + expect(new_text.length).to eq text.length + end + + it 'copies files' do + expect(new_file.exists?).to eq true + expect(old_file.path).to_not eq new_file.path + expect(new_file.path).to include new_project.path_with_namespace + end + + it 'does not remove old files' do + expect(old_file.exists?).to be true + end + end + + describe '#has_uploads?' do + subject { rewriter.has_uploads? } + it { is_expected.to eq true } + end + + describe '#files' do + subject { rewriter.files } + it { is_expected.to be_an(Array) } + end + end +end diff --git a/spec/services/issues/move_service_spec.rb b/spec/services/issues/move_service_spec.rb index 9b0c73aaf37..1cc2daa908f 100644 --- a/spec/services/issues/move_service_spec.rb +++ b/spec/services/issues/move_service_spec.rb @@ -160,6 +160,25 @@ describe Issues::MoveService, services: true do .to eq "Note with reference to merge request #{old_project.to_reference}!1" end end + + context 'issue description with uploads' do + let(:path) { Rails.root + 'spec/fixtures/rails_sample.jpg' } + let(:file) { fixture_file_upload(path, 'image/jpg') } + let(:uploader) { FileUploader.new(old_project) } + let!(:store) { uploader.store!(file) } + let(:markdown) { uploader.to_h[:markdown] } + let(:description) { "Text and #{markdown}"} + + include_context 'issue move executed' + + it 'rewrites uploads in description' do + expect(new_issue.description).to_not eq description + expect(new_issue.description) + .to match(/Text and #{FileUploader::MARKDOWN_PATTERN}/) + end + + after { uploader.remove! } + end end describe 'rewritting references' do |