summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKamil Trzcinski <ayufan@ayufan.eu>2015-11-19 19:22:46 +0100
committerKamil Trzcinski <ayufan@ayufan.eu>2015-11-19 19:28:14 +0100
commit888821f9ffb56c6fdf762f28dd42cf3b7226652f (patch)
tree2f064509ed562fe5cbe81cdb465b1184a63400b5
parent56476f18475deb896c09b47e967dc5146f66778b (diff)
downloadgitlab-ce-lfs-batch-download.tar.gz
Add support for batch download operationlfs-batch-download
-rw-r--r--lib/gitlab/lfs/response.rb105
-rw-r--r--lib/gitlab/lfs/router.rb2
-rw-r--r--spec/lib/gitlab/lfs/lfs_router_spec.rb25
3 files changed, 96 insertions, 36 deletions
diff --git a/lib/gitlab/lfs/response.rb b/lib/gitlab/lfs/response.rb
index 4202c786466..ddadc07ebba 100644
--- a/lib/gitlab/lfs/response.rb
+++ b/lib/gitlab/lfs/response.rb
@@ -26,7 +26,7 @@ module Gitlab
def render_download_object_response(oid)
render_response_to_download do
- if check_download_sendfile_header? && check_download_accept_header?
+ if check_download_sendfile_header?
render_lfs_sendfile(oid)
else
render_not_found
@@ -34,20 +34,15 @@ module Gitlab
end
end
- def render_lfs_api_auth
- render_response_to_push do
- request_body = JSON.parse(@request.body.read)
- return render_not_found if request_body.empty? || request_body['objects'].empty?
-
- response = build_response(request_body['objects'])
- [
- 200,
- {
- "Content-Type" => "application/json; charset=utf-8",
- "Cache-Control" => "private",
- },
- [JSON.dump(response)]
- ]
+ def render_batch_operation_response
+ request_body = JSON.parse(@request.body.read)
+ case request_body["operation"]
+ when "download"
+ render_batch_download(request_body)
+ when "upload"
+ render_batch_upload(request_body)
+ else
+ render_forbidden
end
end
@@ -142,6 +137,38 @@ module Gitlab
end
end
+ def render_batch_upload(body)
+ return render_not_found if body.empty? || body['objects'].nil?
+
+ render_response_to_push do
+ response = build_upload_batch_response(body['objects'])
+ [
+ 200,
+ {
+ "Content-Type" => "application/json; charset=utf-8",
+ "Cache-Control" => "private",
+ },
+ [JSON.dump(response)]
+ ]
+ end
+ end
+
+ def render_batch_download(body)
+ return render_not_found if body.empty? || body['objects'].nil?
+
+ render_response_to_download do
+ response = build_download_batch_response(body['objects'])
+ [
+ 200,
+ {
+ "Content-Type" => "application/json; charset=utf-8",
+ "Cache-Control" => "private",
+ },
+ [JSON.dump(response)]
+ ]
+ end
+ end
+
def render_lfs_download_hypermedia(oid)
return render_not_found unless oid.present?
@@ -266,10 +293,16 @@ module Gitlab
@project.lfs_objects.where(oid: objects_oids).pluck(:oid).to_set
end
- def build_response(objects)
+ def build_upload_batch_response(objects)
selected_objects = select_existing_objects(objects)
- upload_hypermedia(objects, selected_objects)
+ upload_hypermedia_links(objects, selected_objects)
+ end
+
+ def build_download_batch_response(objects)
+ selected_objects = select_existing_objects(objects)
+
+ download_hypermedia_links(objects, selected_objects)
end
def download_hypermedia(oid)
@@ -279,7 +312,6 @@ module Gitlab
{
'href' => "#{@origin_project.http_url_to_repo}/gitlab-lfs/objects/#{oid}",
'header' => {
- 'Accept' => "application/vnd.git-lfs+json; charset=utf-8",
'Authorization' => @env['HTTP_AUTHORIZATION']
}.compact
}
@@ -287,21 +319,40 @@ module Gitlab
}
end
- def upload_hypermedia(all_objects, existing_objects)
+ def download_hypermedia_links(all_objects, existing_objects)
all_objects.each do |object|
- object['_links'] = hypermedia_links(object) unless existing_objects.include?(object['oid'])
+ # generate links only for existing objects
+ next unless existing_objects.include?(object['oid'])
+
+ object['_links'] = {
+ 'download' => {
+ 'href' => "#{@origin_project.http_url_to_repo}/gitlab-lfs/objects/#{object['oid']}",
+ 'header' => {
+ 'Authorization' => @env['HTTP_AUTHORIZATION']
+ }.compact
+ }
+ }
end
{ 'objects' => all_objects }
end
- def hypermedia_links(object)
- {
- "upload" => {
- 'href' => "#{@origin_project.http_url_to_repo}/gitlab-lfs/objects/#{object['oid']}/#{object['size']}",
- 'header' => { 'Authorization' => @env['HTTP_AUTHORIZATION'] }
- }.compact
- }
+ def upload_hypermedia_links(all_objects, existing_objects)
+ all_objects.each do |object|
+ # generate links only for non-existing objects
+ next if existing_objects.include?(object['oid'])
+
+ object['_links'] = {
+ 'upload' => {
+ 'href' => "#{@origin_project.http_url_to_repo}/gitlab-lfs/objects/#{object['oid']}/#{object['size']}",
+ 'header' => {
+ 'Authorization' => @env['HTTP_AUTHORIZATION']
+ }.compact
+ }
+ }
+ end
+
+ { 'objects' => all_objects }
end
end
end
diff --git a/lib/gitlab/lfs/router.rb b/lib/gitlab/lfs/router.rb
index 4809e834984..2b3f2e8e958 100644
--- a/lib/gitlab/lfs/router.rb
+++ b/lib/gitlab/lfs/router.rb
@@ -48,7 +48,7 @@ module Gitlab
# Check for Batch API
if post_path[0].ends_with?("/info/lfs/objects/batch")
- lfs.render_lfs_api_auth
+ lfs.render_batch_operation_response
else
nil
end
diff --git a/spec/lib/gitlab/lfs/lfs_router_spec.rb b/spec/lib/gitlab/lfs/lfs_router_spec.rb
index cebcb5bc887..5eafaad79c9 100644
--- a/spec/lib/gitlab/lfs/lfs_router_spec.rb
+++ b/spec/lib/gitlab/lfs/lfs_router_spec.rb
@@ -66,7 +66,7 @@ describe Gitlab::Lfs::Router do
json_response = ActiveSupport::JSON.decode(lfs_router_auth.try_call.last.first)
expect(json_response['_links']['download']['href']).to eq("#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}")
- expect(json_response['_links']['download']['header']).to eq("Authorization" => @auth, "Accept" => "application/vnd.git-lfs+json; charset=utf-8")
+ expect(json_response['_links']['download']['header']).to eq("Authorization" => @auth)
end
end
@@ -107,7 +107,7 @@ describe Gitlab::Lfs::Router do
json_response = ActiveSupport::JSON.decode(lfs_router_public_auth.try_call.last.first)
expect(json_response['_links']['download']['href']).to eq("#{Gitlab.config.gitlab.url}/#{public_project.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}")
- expect(json_response['_links']['download']['header']).to eq("Accept" => "application/vnd.git-lfs+json; charset=utf-8")
+ expect(json_response['_links']['download']['header']).to eq({})
end
end
@@ -117,7 +117,7 @@ describe Gitlab::Lfs::Router do
json_response = ActiveSupport::JSON.decode(lfs_router_public_noauth.try_call.last.first)
expect(json_response['_links']['download']['href']).to eq("#{Gitlab.config.gitlab.url}/#{public_project.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}")
- expect(json_response['_links']['download']['header']).to eq("Accept" => "application/vnd.git-lfs+json; charset=utf-8")
+ expect(json_response['_links']['download']['header']).to eq({})
end
end
end
@@ -191,7 +191,7 @@ describe Gitlab::Lfs::Router do
json_response = ActiveSupport::JSON.decode(lfs_router_forked_auth.try_call.last.first)
expect(json_response['_links']['download']['href']).to eq("#{Gitlab.config.gitlab.url}/#{forked_project.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}")
- expect(json_response['_links']['download']['header']).to eq("Accept" => "application/vnd.git-lfs+json; charset=utf-8")
+ expect(json_response['_links']['download']['header']).to eq({})
end
end
@@ -219,7 +219,7 @@ describe Gitlab::Lfs::Router do
json_response = ActiveSupport::JSON.decode(lfs_router_forked_auth.try_call.last.first)
expect(json_response['_links']['download']['href']).to eq("#{Gitlab.config.gitlab.url}/#{forked_project.path_with_namespace}.git/gitlab-lfs/objects/91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897")
- expect(json_response['_links']['download']['header']).to eq("Accept" => "application/vnd.git-lfs+json; charset=utf-8", "Authorization" => @auth)
+ expect(json_response['_links']['download']['header']).to eq("Authorization" => @auth)
end
end
@@ -250,7 +250,8 @@ describe Gitlab::Lfs::Router do
body = { 'objects' => [{
'oid' => sample_oid,
'size' => sample_size
- }]
+ }],
+ 'operation' => 'upload'
}.to_json
env['rack.input'] = StringIO.new(body)
end
@@ -286,7 +287,8 @@ describe Gitlab::Lfs::Router do
'objects' => [{
'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897',
'size' => 1575078
- }]
+ }],
+ 'operation' => 'upload'
}.to_json
env['rack.input'] = StringIO.new(body)
end
@@ -315,7 +317,8 @@ describe Gitlab::Lfs::Router do
{ 'oid' => sample_oid,
'size' => sample_size
}
- ]
+ ],
+ 'operation' => 'upload'
}.to_json
env['rack.input'] = StringIO.new(body)
public_project.lfs_objects << lfs_object
@@ -351,6 +354,12 @@ describe Gitlab::Lfs::Router do
end
context 'when user is not authenticated' do
+ before do
+ env['rack.input'] = StringIO.new(
+ { 'objects' => [], 'operation' => 'upload' }.to_json
+ )
+ end
+
context 'when user has push access' do
before do
project.team << [user, :master]