From 771f14b96e058649ca5db7ce6c99e38108d4abec Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 2 Feb 2016 14:09:55 +0100 Subject: [PATCH] First version of "git archive" headers --- .../projects/repositories_controller.rb | 4 ++- app/services/archive_repository_service.rb | 23 ---------------- lib/api/repositories.rb | 7 ++--- lib/gitlab/workhorse.rb | 27 ++++++++++++++++--- .../projects/repositories_controller_spec.rb | 11 +++----- spec/lib/gitlab/workhorse_spec.rb | 18 +++++++++++++ .../archive_repository_service_spec.rb | 25 ----------------- 7 files changed, 49 insertions(+), 66 deletions(-) delete mode 100644 app/services/archive_repository_service.rb create mode 100644 spec/lib/gitlab/workhorse_spec.rb delete mode 100644 spec/services/archive_repository_service_spec.rb diff --git a/app/controllers/projects/repositories_controller.rb b/app/controllers/projects/repositories_controller.rb index ba9aea1c165..5c7614cfbaf 100644 --- a/app/controllers/projects/repositories_controller.rb +++ b/app/controllers/projects/repositories_controller.rb @@ -11,7 +11,9 @@ class Projects::RepositoriesController < Projects::ApplicationController end 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 logger.error("#{self.class.name}: #{ex}") return git_not_found! diff --git a/app/services/archive_repository_service.rb b/app/services/archive_repository_service.rb deleted file mode 100644 index 2160bf13e6d..00000000000 --- a/app/services/archive_repository_service.rb +++ /dev/null @@ -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 diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb index c95d2d2001d..0178289f57f 100644 --- a/lib/api/repositories.rb +++ b/lib/api/repositories.rb @@ -98,11 +98,8 @@ module API authorize! :download_code, user_project begin - ArchiveRepositoryService.new( - user_project, - params[:sha], - params[:format] - ).execute + RepositoryArchiveCacheWorker.perform_async + header *Gitlab::Workhorse.send_git_archive(@project, params[:ref], params[:format]) rescue not_found!('File') end diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb index a23120a4176..2f3e57156b6 100644 --- a/lib/gitlab/workhorse.rb +++ b/lib/gitlab/workhorse.rb @@ -4,18 +4,37 @@ require 'json' module Gitlab class Workhorse class << self + SEND_DATA_HEADER = 'Gitlab-Workhorse-Send-Data' + def send_git_blob(repository, blob) - params_hash = { + params = { 'RepoPath' => repository.path_to_repo, 'BlobId' => blob.id, } - params = Base64.urlsafe_encode64(JSON.dump(params_hash)) [ - 'Gitlab-Workhorse-Send-Data', - "git-blob:#{params}", + SEND_DATA_HEADER, + "git-blob:#{encode(params)}", ] 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 diff --git a/spec/controllers/projects/repositories_controller_spec.rb b/spec/controllers/projects/repositories_controller_spec.rb index 18a30033ed8..09ec4f18f9d 100644 --- a/spec/controllers/projects/repositories_controller_spec.rb +++ b/spec/controllers/projects/repositories_controller_spec.rb @@ -8,15 +8,10 @@ describe Projects::RepositoriesController do before do sign_in(user) project.team << [user, :developer] - - allow(ArchiveRepositoryService).to receive(:new).and_return(service) end - let(:service) { ArchiveRepositoryService.new(project, "master", "zip") } - - it "executes ArchiveRepositoryService" do - expect(ArchiveRepositoryService).to receive(:new).with(project, "master", "zip") - expect(service).to receive(:execute) + it "uses Gitlab::Workhorse" do + expect(Gitlab::Workhorse).to receive(:send_git_archive).with(project, "master", "zip") get :archive, namespace_id: project.namespace.path, project_id: project.path, ref: "master", format: "zip" end @@ -24,7 +19,7 @@ describe Projects::RepositoriesController do context "when the service raises an error" 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 it "renders Not Found" do diff --git a/spec/lib/gitlab/workhorse_spec.rb b/spec/lib/gitlab/workhorse_spec.rb new file mode 100644 index 00000000000..d940bf05061 --- /dev/null +++ b/spec/lib/gitlab/workhorse_spec.rb @@ -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 diff --git a/spec/services/archive_repository_service_spec.rb b/spec/services/archive_repository_service_spec.rb deleted file mode 100644 index bd871605c66..00000000000 --- a/spec/services/archive_repository_service_spec.rb +++ /dev/null @@ -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