Commit 8c5b3d03 authored by Bob Van Landuyt's avatar Bob Van Landuyt

Allow streaming io objects into Gitaly

This allows us to set the encoding of an IO passed without reading it
into memory.

This is useful if we want to stream files into Gitaly. Like we do when
uploading a new file to the repository.
parent 57cba4d1
...@@ -172,8 +172,7 @@ class Projects::BlobController < Projects::ApplicationController ...@@ -172,8 +172,7 @@ class Projects::BlobController < Projects::ApplicationController
end end
if params[:file].present? if params[:file].present?
params[:content] = Base64.encode64(params[:file].read) params[:content] = params[:file]
params[:encoding] = 'base64'
end end
@commit_params = { @commit_params = {
......
...@@ -76,8 +76,11 @@ module Gitlab ...@@ -76,8 +76,11 @@ module Gitlab
str.dup.force_encoding(Encoding::ASCII_8BIT) str.dup.force_encoding(Encoding::ASCII_8BIT)
end end
def binary_stringio(str) def binary_io(str_or_io)
StringIO.new(str.freeze || '').tap { |io| io.set_encoding(Encoding::ASCII_8BIT) } io = str_or_io.to_io.dup if str_or_io.respond_to?(:to_io)
io ||= StringIO.new(str_or_io.to_s.freeze)
io.tap { |io| io.set_encoding(Encoding::ASCII_8BIT) }
end end
private private
......
...@@ -37,7 +37,7 @@ module Gitlab ...@@ -37,7 +37,7 @@ module Gitlab
end end
def resolve_conflicts(target_repository, resolution, source_branch, target_branch) def resolve_conflicts(target_repository, resolution, source_branch, target_branch)
reader = binary_stringio(resolution.files.to_json) reader = binary_io(resolution.files.to_json)
req_enum = Enumerator.new do |y| req_enum = Enumerator.new do |y|
header = resolve_conflicts_request_header(target_repository, resolution, source_branch, target_branch) header = resolve_conflicts_request_header(target_repository, resolution, source_branch, target_branch)
......
...@@ -294,7 +294,7 @@ module Gitlab ...@@ -294,7 +294,7 @@ module Gitlab
action: Gitaly::UserCommitFilesAction.new(header: action_header) action: Gitaly::UserCommitFilesAction.new(header: action_header)
) )
reader = binary_stringio(action[:content]) reader = binary_io(action[:content])
until reader.eof? until reader.eof?
chunk = reader.read(MAX_MSG_SIZE) chunk = reader.read(MAX_MSG_SIZE)
...@@ -327,7 +327,7 @@ module Gitlab ...@@ -327,7 +327,7 @@ module Gitlab
user: Gitlab::Git::User.from_gitlab(user).to_gitaly, user: Gitlab::Git::User.from_gitlab(user).to_gitaly,
target_branch: encode_binary(branch_name) target_branch: encode_binary(branch_name)
) )
reader = binary_stringio(patches) reader = binary_io(patches)
chunks = Enumerator.new do |chunk| chunks = Enumerator.new do |chunk|
chunk.yield Gitaly::UserApplyPatchRequest.new(header: header) chunk.yield Gitaly::UserApplyPatchRequest.new(header: header)
......
...@@ -22,7 +22,7 @@ module Gitlab ...@@ -22,7 +22,7 @@ module Gitlab
commit_details: gitaly_commit_details(commit_details) commit_details: gitaly_commit_details(commit_details)
) )
strio = binary_stringio(content) strio = binary_io(content)
enum = Enumerator.new do |y| enum = Enumerator.new do |y|
until strio.eof? until strio.eof?
...@@ -49,7 +49,7 @@ module Gitlab ...@@ -49,7 +49,7 @@ module Gitlab
commit_details: gitaly_commit_details(commit_details) commit_details: gitaly_commit_details(commit_details)
) )
strio = binary_stringio(content) strio = binary_io(content)
enum = Enumerator.new do |y| enum = Enumerator.new do |y|
until strio.eof? until strio.eof?
......
...@@ -189,14 +189,23 @@ describe Gitlab::EncodingHelper do ...@@ -189,14 +189,23 @@ describe Gitlab::EncodingHelper do
end end
end end
describe '#binary_stringio' do describe '#binary_io' do
it 'does not mutate the original string encoding' do it 'does not mutate the original string encoding' do
test = 'my-test' test = 'my-test'
io_stream = ext_class.binary_stringio(test) io_stream = ext_class.binary_io(test)
expect(io_stream.external_encoding.name).to eq('ASCII-8BIT') expect(io_stream.external_encoding.name).to eq('ASCII-8BIT')
expect(test.encoding.name).to eq('UTF-8') expect(test.encoding.name).to eq('UTF-8')
end end
it 'returns a copy of the IO with the correct encoding' do
test = fixture_file_upload('spec/fixtures/doc_sample.txt').to_io
io_stream = ext_class.binary_io(test)
expect(io_stream.external_encoding.name).to eq('ASCII-8BIT')
expect(test).not_to eq(io_stream)
end
end end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment