Skip to content
Snippets Groups Projects
Commit 37be2007 authored by Robert Speicher's avatar Robert Speicher
Browse files

Merge branch 'workhorse-helpers' into 'master'

Add workhorse controller and API helpers

Adds `send_git_blob` and `send_git_archive` controller and API helpers to reduce duplication and make Workhorse easier for a developer to work with.

See merge request !4486
parents d6de8169 701e2df7
No related branches found
No related tags found
No related merge requests found
Showing
with 61 additions and 34 deletions
Loading
@@ -55,6 +55,7 @@ v 8.9.0 (unreleased)
Loading
@@ -55,6 +55,7 @@ v 8.9.0 (unreleased)
- Remove duplicated notification settings - Remove duplicated notification settings
- Put project Files and Commits tabs under Code tab - Put project Files and Commits tabs under Code tab
- Replace Colorize with Rainbow for coloring console output in Rake tasks. - Replace Colorize with Rainbow for coloring console output in Rake tasks.
- Add workhorse controller and API helpers
- An indicator is now displayed at the top of the comment field for confidential issues. - An indicator is now displayed at the top of the comment field for confidential issues.
- RepositoryCheck::SingleRepositoryWorker public and private methods are now instrumented - RepositoryCheck::SingleRepositoryWorker public and private methods are now instrumented
- Improve issuables APIs performance when accessing notes !4471 - Improve issuables APIs performance when accessing notes !4471
Loading
Loading
Loading
@@ -6,6 +6,7 @@ class ApplicationController < ActionController::Base
Loading
@@ -6,6 +6,7 @@ class ApplicationController < ActionController::Base
include Gitlab::GonHelper include Gitlab::GonHelper
include GitlabRoutingHelper include GitlabRoutingHelper
include PageLayoutHelper include PageLayoutHelper
include WorkhorseHelper
   
before_action :authenticate_user_from_token! before_action :authenticate_user_from_token!
before_action :authenticate_user! before_action :authenticate_user!
Loading
Loading
Loading
@@ -10,10 +10,7 @@ class Projects::AvatarsController < Projects::ApplicationController
Loading
@@ -10,10 +10,7 @@ class Projects::AvatarsController < Projects::ApplicationController
   
return if cached_blob? return if cached_blob?
   
headers.store(*Gitlab::Workhorse.send_git_blob(@repository, @blob)) send_git_blob @repository, @blob
headers['Content-Disposition'] = 'inline'
headers['Content-Type'] = safe_content_type(@blob)
head :ok # 'render nothing: true' messes up the Content-Type
else else
render_404 render_404
end end
Loading
Loading
Loading
@@ -61,12 +61,9 @@ class Projects::MergeRequestsController < Projects::ApplicationController
Loading
@@ -61,12 +61,9 @@ class Projects::MergeRequestsController < Projects::ApplicationController
format.json { render json: @merge_request } format.json { render json: @merge_request }
format.patch { render text: @merge_request.to_patch } format.patch { render text: @merge_request.to_patch }
format.diff do format.diff do
headers.store(*Gitlab::Workhorse.send_git_diff(@project.repository, return render_404 unless @merge_request.diff_refs
@merge_request.diff_base_commit.id,
@merge_request.last_commit.id))
headers['Content-Disposition'] = 'inline'
   
head :ok send_git_diff @project.repository, @merge_request.diff_refs
end end
end end
end end
Loading
Loading
Loading
@@ -18,10 +18,7 @@ class Projects::RawController < Projects::ApplicationController
Loading
@@ -18,10 +18,7 @@ class Projects::RawController < Projects::ApplicationController
if @blob.lfs_pointer? if @blob.lfs_pointer?
send_lfs_object send_lfs_object
else else
headers.store(*Gitlab::Workhorse.send_git_blob(@repository, @blob)) send_git_blob @repository, @blob
headers['Content-Disposition'] = 'inline'
headers['Content-Type'] = safe_content_type(@blob)
head :ok # 'render nothing: true' messes up the Content-Type
end end
else else
render_404 render_404
Loading
Loading
Loading
@@ -11,8 +11,7 @@ class Projects::RepositoriesController < Projects::ApplicationController
Loading
@@ -11,8 +11,7 @@ class Projects::RepositoriesController < Projects::ApplicationController
end end
   
def archive def archive
headers.store(*Gitlab::Workhorse.send_git_archive(@project, params[:ref], params[:format])) send_git_archive @repository, ref: params[:ref], format: 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!
Loading
Loading
# Helpers to send Git blobs, diffs or archives through Workhorse.
# Workhorse will also serve files when using `send_file`.
module WorkhorseHelper
# Send a Git blob through Workhorse
def send_git_blob(repository, blob)
headers.store(*Gitlab::Workhorse.send_git_blob(repository, blob))
headers['Content-Disposition'] = 'inline'
headers['Content-Type'] = safe_content_type(blob)
head :ok # 'render nothing: true' messes up the Content-Type
end
# Send a Git diff through Workhorse
def send_git_diff(repository, diff_refs)
headers.store(*Gitlab::Workhorse.send_git_diff(repository, diff_refs))
headers['Content-Disposition'] = 'inline'
head :ok
end
# Archive a Git repository and send it through Workhorse
def send_git_archive(repository, ref:, format:)
headers.store(*Gitlab::Workhorse.send_git_archive(repository, ref: ref, format: format))
head :ok
end
end
Loading
@@ -408,5 +408,15 @@ module API
Loading
@@ -408,5 +408,15 @@ module API
error!(errors[:access_level], 422) if errors[:access_level].any? error!(errors[:access_level], 422) if errors[:access_level].any?
not_found!(errors) not_found!(errors)
end end
def send_git_blob(repository, blob)
env['api.format'] = :txt
content_type 'text/plain'
header(*Gitlab::Workhorse.send_git_blob(repository, blob))
end
def send_git_archive(repository, ref:, format:)
header(*Gitlab::Workhorse.send_git_archive(repository, ref: ref, format: format))
end
end end
end end
Loading
@@ -56,8 +56,7 @@ module API
Loading
@@ -56,8 +56,7 @@ module API
blob = Gitlab::Git::Blob.find(repo, commit.id, params[:filepath]) blob = Gitlab::Git::Blob.find(repo, commit.id, params[:filepath])
not_found! "File" unless blob not_found! "File" unless blob
   
content_type 'text/plain' send_git_blob repo, blob
header(*Gitlab::Workhorse.send_git_blob(repo, blob))
end end
   
# Get a raw blob contents by blob sha # Get a raw blob contents by blob sha
Loading
@@ -80,10 +79,7 @@ module API
Loading
@@ -80,10 +79,7 @@ module API
   
not_found! 'Blob' unless blob not_found! 'Blob' unless blob
   
env['api.format'] = :txt send_git_blob repo, blob
content_type blob.mime_type
header(*Gitlab::Workhorse.send_git_blob(repo, blob))
end end
   
# Get a an archive of the repository # Get a an archive of the repository
Loading
@@ -98,7 +94,7 @@ module API
Loading
@@ -98,7 +94,7 @@ module API
authorize! :download_code, user_project authorize! :download_code, user_project
   
begin begin
header(*Gitlab::Workhorse.send_git_archive(user_project, params[:sha], params[:format])) send_git_archive user_project.repository, ref: params[:sha], format: params[:format]
rescue rescue
not_found!('File') not_found!('File')
end end
Loading
Loading
Loading
@@ -21,27 +21,29 @@ module Gitlab
Loading
@@ -21,27 +21,29 @@ module Gitlab
   
[ [
SEND_DATA_HEADER, SEND_DATA_HEADER,
"git-blob:#{encode(params)}", "git-blob:#{encode(params)}"
] ]
end end
   
def send_git_archive(project, ref, format) def send_git_archive(repository, ref:, format:)
format ||= 'tar.gz' format ||= 'tar.gz'
format.downcase! format.downcase!
params = project.repository.archive_metadata(ref, Gitlab.config.gitlab.repository_downloads_path, format) params = repository.archive_metadata(ref, Gitlab.config.gitlab.repository_downloads_path, format)
raise "Repository or ref not found" if params.empty? raise "Repository or ref not found" if params.empty?
   
[ [
SEND_DATA_HEADER, SEND_DATA_HEADER,
"git-archive:#{encode(params)}", "git-archive:#{encode(params)}"
] ]
end end
   
def send_git_diff(repository, from, to) def send_git_diff(repository, diff_refs)
from, to = diff_refs
params = { params = {
'RepoPath' => repository.path_to_repo, 'RepoPath' => repository.path_to_repo,
'ShaFrom' => from, 'ShaFrom' => from.sha,
'ShaTo' => to 'ShaTo' => to.sha
} }
   
[ [
Loading
Loading
Loading
@@ -91,7 +91,7 @@ describe Projects::MergeRequestsController do
Loading
@@ -91,7 +91,7 @@ describe Projects::MergeRequestsController do
id: merge_request.iid, id: merge_request.iid,
format: :diff) format: :diff)
   
expect(response.headers['Gitlab-Workhorse-Send-Data']).to start_with("git-diff:") expect(response.headers[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with("git-diff:")
end end
end end
   
Loading
Loading
Loading
@@ -17,6 +17,7 @@ describe Projects::RawController do
Loading
@@ -17,6 +17,7 @@ describe Projects::RawController do
expect(response.header['Content-Type']).to eq('text/plain; charset=utf-8') expect(response.header['Content-Type']).to eq('text/plain; charset=utf-8')
expect(response.header['Content-Disposition']). expect(response.header['Content-Disposition']).
to eq("inline") to eq("inline")
expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with("git-blob:")
end end
end end
   
Loading
@@ -31,6 +32,7 @@ describe Projects::RawController do
Loading
@@ -31,6 +32,7 @@ describe Projects::RawController do
   
expect(response.status).to eq(200) expect(response.status).to eq(200)
expect(response.header['Content-Type']).to eq('image/jpeg') expect(response.header['Content-Type']).to eq('image/jpeg')
expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with("git-blob:")
end end
end end
   
Loading
Loading
Loading
@@ -20,10 +20,11 @@ describe Projects::RepositoriesController do
Loading
@@ -20,10 +20,11 @@ describe Projects::RepositoriesController do
project.team << [user, :developer] project.team << [user, :developer]
sign_in(user) sign_in(user)
end end
it "uses Gitlab::Workhorse" do
expect(Gitlab::Workhorse).to receive(:send_git_archive).with(project, "master", "zip")
   
it "uses Gitlab::Workhorse" do
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"
expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with("git-archive:")
end end
   
context "when the service raises an error" do context "when the service raises an error" do
Loading
Loading
Loading
@@ -11,7 +11,7 @@ describe Gitlab::Workhorse, lib: true do
Loading
@@ -11,7 +11,7 @@ describe Gitlab::Workhorse, lib: true do
end end
   
it "raises an error" do it "raises an error" do
expect { subject.send_git_archive(project, "master", "zip") }.to raise_error(RuntimeError) expect { subject.send_git_archive(project.repository, ref: "master", format: "zip") }.to raise_error(RuntimeError)
end end
end end
end end
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment