Commit 7cc25205 authored by Jason Hollingsworth's avatar Jason Hollingsworth

Add support for various archive formats.

Used mime-types gem instead of hardcoding content types.
Allow multiple extensions in archive route (.tar.gz, .tar.bz2).
Change content disposition from infile(?) to attachment for api.
Fixed api would return “archive” instead of {project}-{hash}.{ext}
parent b512fbc0
...@@ -16,7 +16,7 @@ class Projects::RepositoriesController < Projects::ApplicationController ...@@ -16,7 +16,7 @@ class Projects::RepositoriesController < Projects::ApplicationController
storage_path = Rails.root.join("tmp", "repositories") storage_path = Rails.root.join("tmp", "repositories")
file_path = @repository.archive_repo(params[:ref], storage_path) file_path = @repository.archive_repo(params[:ref], storage_path, params[:format].downcase)
if file_path if file_path
# Send file to user # Send file to user
......
...@@ -217,7 +217,7 @@ Gitlab::Application.routes.draw do ...@@ -217,7 +217,7 @@ Gitlab::Application.routes.draw do
resource :repository, only: [:show] do resource :repository, only: [:show] do
member do member do
get "stats" get "stats"
get "archive" get "archive", constraints: { format: Gitlab::Regex.archive_formats_regex }
end end
end end
......
require 'mime/types'
module API module API
# Projects API # Projects API
class Repositories < Grape::API class Repositories < Grape::API
...@@ -206,18 +208,20 @@ module API ...@@ -206,18 +208,20 @@ module API
# sha (optional) - the commit sha to download defaults to the tip of the default branch # sha (optional) - the commit sha to download defaults to the tip of the default branch
# Example Request: # Example Request:
# GET /projects/:id/repository/archive # GET /projects/:id/repository/archive
get ":id/repository/archive" do get ":id/repository/archive", requirements: { format: Gitlab::Regex.archive_formats_regex } do
authorize! :download_code, user_project authorize! :download_code, user_project
repo = user_project.repository repo = user_project.repository
ref = params[:sha] ref = params[:sha]
format = params[:format]
storage_path = Rails.root.join("tmp", "repositories") storage_path = Rails.root.join("tmp", "repositories")
file_path = repo.archive_repo(ref, storage_path) file_path = repo.archive_repo(ref, storage_path, format)
if file_path && File.exists?(file_path) if file_path && File.exists?(file_path)
data = File.open(file_path, 'rb').read data = File.open(file_path, 'rb').read
header "Content-Disposition:", " infile; filename=\"#{File.basename(file_path)}\"" header["Content-Disposition"] = "attachment; filename=\"#{File.basename(file_path)}\""
content_type 'application/x-gzip'
content_type MIME::Types.type_for(file_path).first.content_type
env['api.format'] = :binary env['api.format'] = :binary
......
...@@ -18,6 +18,11 @@ module Gitlab ...@@ -18,6 +18,11 @@ module Gitlab
default_regex default_regex
end end
def archive_formats_regex
#|zip|tar| tar.gz | tar.bz2 |
/(zip|tar|tar\.gz|tgz|gz|tar\.bz2|tbz|tbz2|tb2|bz2)/
end
def git_reference_regex def git_reference_regex
# Valid git ref regex, see: # Valid git ref regex, see:
# https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html # https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html
......
require 'spec_helper' require 'spec_helper'
require 'mime/types'
describe API::API do describe API::API do
include ApiHelpers include ApiHelpers
...@@ -232,11 +233,29 @@ describe API::API do ...@@ -232,11 +233,29 @@ describe API::API do
end end
end end
describe "GET /projects/:id/repository/archive/:sha" do describe "GET /projects/:id/repository/archive(.:format)?:sha" do
it "should get the archive" do it "should get the archive" do
get api("/projects/#{project.id}/repository/archive", user) get api("/projects/#{project.id}/repository/archive", user)
repo_name = project.repository.name.gsub("\.git", "")
response.status.should == 200 response.status.should == 200
response.content_type.should == 'application/x-gzip' response.headers['Content-Disposition'].should =~ /filename\=\"#{repo_name}\-[^\.]+\.tar.gz\"/
response.content_type.should == MIME::Types.type_for('file.tar.gz').first.content_type
end
it "should get the archive.zip" do
get api("/projects/#{project.id}/repository/archive.zip", user)
repo_name = project.repository.name.gsub("\.git", "")
response.status.should == 200
response.headers['Content-Disposition'].should =~ /filename\=\"#{repo_name}\-[^\.]+\.zip\"/
response.content_type.should == MIME::Types.type_for('file.zip').first.content_type
end
it "should get the archive.tar.bz2" do
get api("/projects/#{project.id}/repository/archive.tar.bz2", user)
repo_name = project.repository.name.gsub("\.git", "")
response.status.should == 200
response.headers['Content-Disposition'].should =~ /filename\=\"#{repo_name}\-[^\.]+\.tar.bz2\"/
response.content_type.should == MIME::Types.type_for('file.tar.bz2').first.content_type
end end
it "should return 404 for invalid sha" do it "should return 404 for invalid sha" do
......
...@@ -130,6 +130,14 @@ describe Projects::RepositoriesController, "routing" do ...@@ -130,6 +130,14 @@ describe Projects::RepositoriesController, "routing" do
get("/gitlab/gitlabhq/repository/archive").should route_to('projects/repositories#archive', project_id: 'gitlab/gitlabhq') get("/gitlab/gitlabhq/repository/archive").should route_to('projects/repositories#archive', project_id: 'gitlab/gitlabhq')
end end
it "to #archive format:zip" do
get("/gitlab/gitlabhq/repository/archive.zip").should route_to('projects/repositories#archive', project_id: 'gitlab/gitlabhq', format: 'zip')
end
it "to #archive format:tar.bz2" do
get("/gitlab/gitlabhq/repository/archive.tar.bz2").should route_to('projects/repositories#archive', project_id: 'gitlab/gitlabhq', format: 'tar.bz2')
end
it "to #show" do it "to #show" do
get("/gitlab/gitlabhq/repository").should route_to('projects/repositories#show', project_id: 'gitlab/gitlabhq') get("/gitlab/gitlabhq/repository").should route_to('projects/repositories#show', project_id: 'gitlab/gitlabhq')
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