First version of "git archive" headers
This commit is contained in:
parent
b1f22aa35a
commit
771f14b96e
7 changed files with 49 additions and 66 deletions
|
@ -11,7 +11,9 @@ class Projects::RepositoriesController < Projects::ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def archive
|
def archive
|
||||||
render json: ArchiveRepositoryService.new(@project, params[:ref], params[:format]).execute
|
RepositoryArchiveCacheWorker.perform_async
|
||||||
|
headers.store(*Gitlab::Workhorse.send_git_archive(@project, params[:ref], params[:format]))
|
||||||
|
head :ok
|
||||||
rescue => ex
|
rescue => ex
|
||||||
logger.error("#{self.class.name}: #{ex}")
|
logger.error("#{self.class.name}: #{ex}")
|
||||||
return git_not_found!
|
return git_not_found!
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
class ArchiveRepositoryService
|
|
||||||
attr_reader :project, :ref, :format
|
|
||||||
|
|
||||||
def initialize(project, ref, format)
|
|
||||||
format ||= 'tar.gz'
|
|
||||||
@project, @ref, @format = project, ref, format.downcase
|
|
||||||
end
|
|
||||||
|
|
||||||
def execute(options = {})
|
|
||||||
RepositoryArchiveCacheWorker.perform_async
|
|
||||||
|
|
||||||
metadata = project.repository.archive_metadata(ref, storage_path, format)
|
|
||||||
raise "Repository or ref not found" if metadata.empty?
|
|
||||||
|
|
||||||
metadata
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def storage_path
|
|
||||||
Gitlab.config.gitlab.repository_downloads_path
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -98,11 +98,8 @@ module API
|
||||||
authorize! :download_code, user_project
|
authorize! :download_code, user_project
|
||||||
|
|
||||||
begin
|
begin
|
||||||
ArchiveRepositoryService.new(
|
RepositoryArchiveCacheWorker.perform_async
|
||||||
user_project,
|
header *Gitlab::Workhorse.send_git_archive(@project, params[:ref], params[:format])
|
||||||
params[:sha],
|
|
||||||
params[:format]
|
|
||||||
).execute
|
|
||||||
rescue
|
rescue
|
||||||
not_found!('File')
|
not_found!('File')
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,18 +4,37 @@ require 'json'
|
||||||
module Gitlab
|
module Gitlab
|
||||||
class Workhorse
|
class Workhorse
|
||||||
class << self
|
class << self
|
||||||
|
SEND_DATA_HEADER = 'Gitlab-Workhorse-Send-Data'
|
||||||
|
|
||||||
def send_git_blob(repository, blob)
|
def send_git_blob(repository, blob)
|
||||||
params_hash = {
|
params = {
|
||||||
'RepoPath' => repository.path_to_repo,
|
'RepoPath' => repository.path_to_repo,
|
||||||
'BlobId' => blob.id,
|
'BlobId' => blob.id,
|
||||||
}
|
}
|
||||||
params = Base64.urlsafe_encode64(JSON.dump(params_hash))
|
|
||||||
|
|
||||||
[
|
[
|
||||||
'Gitlab-Workhorse-Send-Data',
|
SEND_DATA_HEADER,
|
||||||
"git-blob:#{params}",
|
"git-blob:#{encode(params)}",
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def send_git_archive(project, ref, format)
|
||||||
|
format ||= 'tar.gz'
|
||||||
|
format.downcase!
|
||||||
|
params = project.repository.archive_metadata(ref, Gitlab.config.gitlab.repository_downloads_path, format)
|
||||||
|
raise "Repository or ref not found" if params.empty?
|
||||||
|
|
||||||
|
[
|
||||||
|
SEND_DATA_HEADER,
|
||||||
|
"git-archive:#{encode(params)}",
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def encode(hash)
|
||||||
|
Base64.urlsafe_encode64(JSON.dump(hash))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,15 +8,10 @@ describe Projects::RepositoriesController do
|
||||||
before do
|
before do
|
||||||
sign_in(user)
|
sign_in(user)
|
||||||
project.team << [user, :developer]
|
project.team << [user, :developer]
|
||||||
|
|
||||||
allow(ArchiveRepositoryService).to receive(:new).and_return(service)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:service) { ArchiveRepositoryService.new(project, "master", "zip") }
|
it "uses Gitlab::Workhorse" do
|
||||||
|
expect(Gitlab::Workhorse).to receive(:send_git_archive).with(project, "master", "zip")
|
||||||
it "executes ArchiveRepositoryService" do
|
|
||||||
expect(ArchiveRepositoryService).to receive(:new).with(project, "master", "zip")
|
|
||||||
expect(service).to receive(:execute)
|
|
||||||
|
|
||||||
get :archive, namespace_id: project.namespace.path, project_id: project.path, ref: "master", format: "zip"
|
get :archive, namespace_id: project.namespace.path, project_id: project.path, ref: "master", format: "zip"
|
||||||
end
|
end
|
||||||
|
@ -24,7 +19,7 @@ describe Projects::RepositoriesController do
|
||||||
context "when the service raises an error" do
|
context "when the service raises an error" do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(service).to receive(:execute).and_raise("Archive failed")
|
allow(Gitlab::Workhorse).to receive(:send_git_archive).and_raise("Archive failed")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "renders Not Found" do
|
it "renders Not Found" do
|
||||||
|
|
18
spec/lib/gitlab/workhorse_spec.rb
Normal file
18
spec/lib/gitlab/workhorse_spec.rb
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe Gitlab::Workhorse, lib: true do
|
||||||
|
let(:project) { create(:project) }
|
||||||
|
let(:subject) { Gitlab::Workhorse }
|
||||||
|
|
||||||
|
describe "#send_git_archive" do
|
||||||
|
context "when the repository doesn't have an archive file path" do
|
||||||
|
before do
|
||||||
|
allow(project.repository).to receive(:archive_metadata).and_return(Hash.new)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises an error" do
|
||||||
|
expect { subject.send_git_archive(project, "master", "zip") }.to raise_error(RuntimeError)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,25 +0,0 @@
|
||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe ArchiveRepositoryService, services: true do
|
|
||||||
let(:project) { create(:project) }
|
|
||||||
subject { ArchiveRepositoryService.new(project, "master", "zip") }
|
|
||||||
|
|
||||||
describe "#execute" do
|
|
||||||
it "cleans old archives" do
|
|
||||||
expect(RepositoryArchiveCacheWorker).to receive(:perform_async)
|
|
||||||
|
|
||||||
subject.execute(timeout: 0.0)
|
|
||||||
end
|
|
||||||
|
|
||||||
context "when the repository doesn't have an archive file path" do
|
|
||||||
before do
|
|
||||||
allow(project.repository).to receive(:archive_metadata).and_return(Hash.new)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "raises an error" do
|
|
||||||
expect { subject.execute(timeout: 0.0) }.to raise_error(RuntimeError)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
Loading…
Reference in a new issue