Commits API: Preserve file content in move operations if unspecified

This commit is contained in:
Nick Thomas 2018-11-27 16:27:51 +00:00
parent a54352406a
commit 14076062df
No known key found for this signature in database
GPG key ID: 2A313A47AFADACE9
6 changed files with 51 additions and 13 deletions

View file

@ -272,7 +272,7 @@ GEM
gettext_i18n_rails (>= 0.7.1)
po_to_json (>= 1.0.0)
rails (>= 3.2.0)
gitaly-proto (1.1.0)
gitaly-proto (1.2.0)
grpc (~> 1.0)
github-markup (1.7.0)
gitlab-markup (1.6.5)
@ -998,7 +998,7 @@ DEPENDENCIES
gettext (~> 3.2.2)
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.3)
gitaly-proto (~> 1.1.0)
gitaly-proto (~> 1.2.0)
github-markup (~> 1.7.0)
gitlab-markup (~> 1.6.5)
gitlab-sidekiq-fetcher

View file

@ -8,6 +8,7 @@ module Files
transformer = Lfs::FileTransformer.new(project, @branch_name)
actions = actions_after_lfs_transformation(transformer, params[:actions])
actions = transform_move_actions(actions)
commit_actions!(actions)
end
@ -26,6 +27,16 @@ module Files
end
end
# When moving a file, `content: nil` means "use the contents of the previous
# file", while `content: ''` means "move the file and set it to empty"
def transform_move_actions(actions)
actions.map do |action|
action[:infer_content] = true if action[:content].nil?
action
end
end
def commit_actions!(actions)
repository.multi_action(
current_user,

View file

@ -0,0 +1,5 @@
---
title: 'Commits API: Preserve file content in move operations if unspecified'
merge_request: 23387
author:
type: fixed

View file

@ -87,7 +87,7 @@ POST /projects/:id/repository/commits
| `action` | string | yes | The action to perform, `create`, `delete`, `move`, `update`, `chmod`|
| `file_path` | string | yes | Full path to the file. Ex. `lib/class.rb` |
| `previous_path` | string | no | Original full path to the file being moved. Ex. `lib/class1.rb`. Only considered for `move` action. |
| `content` | string | no | File content, required for all except `delete` and `chmod`. Optional for `move` |
| `content` | string | no | File content, required for all except `delete`, `chmod`, and `move`. Move actions that do not specify `content` will preserve the existing file content, and any other value of `content` will overwrite the file content. |
| `encoding` | string | no | `text` or `base64`. `text` is default. |
| `last_commit_id` | string | no | Last known file commit id. Will be only considered in update, move and delete actions. |
| `execute_filemode` | boolean | no | When `true/false` enables/disables the execute flag on the file. Only considered for `chmod` action. |

View file

@ -385,7 +385,8 @@ module Gitlab
file_path: encode_binary(action[:file_path]),
previous_path: encode_binary(action[:previous_path]),
base64_content: action[:encoding] == 'base64',
execute_filemode: !!action[:execute_filemode]
execute_filemode: !!action[:execute_filemode],
infer_content: !!action[:infer_content]
)
rescue RangeError
raise ArgumentError, "Unknown action '#{action[:action]}'"

View file

@ -122,26 +122,47 @@ describe Files::MultiService do
let(:action) { 'move' }
let(:new_file_path) { 'files/ruby/new_popen.rb' }
let(:result) { subject.execute }
let(:blob) { repository.blob_at_branch(branch_name, new_file_path) }
context 'when original file has been updated' do
before do
update_file(original_file_path)
end
it 'rejects the commit' do
results = subject.execute
expect(results[:status]).to eq(:error)
expect(results[:message]).to match(original_file_path)
expect(result[:status]).to eq(:error)
expect(result[:message]).to match(original_file_path)
end
end
context 'when original file have not been updated' do
context 'when original file has not been updated' do
it 'moves the file' do
results = subject.execute
blob = project.repository.blob_at_branch(branch_name, new_file_path)
expect(results[:status]).to eq(:success)
expect(result[:status]).to eq(:success)
expect(blob).to be_present
expect(blob.data).to eq(file_content)
end
context 'when content is nil' do
let(:file_content) { nil }
it 'moves the existing content untouched' do
original_content = repository.blob_at_branch(branch_name, original_file_path).data
expect(result[:status]).to eq(:success)
expect(blob).to be_present
expect(blob.data).to eq(original_content)
end
end
context 'when content is an empty string' do
let(:file_content) { '' }
it 'moves the file and empties it' do
expect(result[:status]).to eq(:success)
expect(blob).not_to be_nil
expect(blob.data).to eq('')
end
end
end
end