Commit 7cc25205410efc6b20b11d94ab2cbc1a322ff816

Authored by Jason Hollingsworth
1 parent b512fbc0

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}
app/controllers/projects/repositories_controller.rb
@@ -16,7 +16,7 @@ class Projects::RepositoriesController < Projects::ApplicationController @@ -16,7 +16,7 @@ class Projects::RepositoriesController < Projects::ApplicationController
16 16
17 storage_path = Rails.root.join("tmp", "repositories") 17 storage_path = Rails.root.join("tmp", "repositories")
18 18
19 - file_path = @repository.archive_repo(params[:ref], storage_path) 19 + file_path = @repository.archive_repo(params[:ref], storage_path, params[:format].downcase)
20 20
21 if file_path 21 if file_path
22 # Send file to user 22 # Send file to user
config/routes.rb
@@ -217,7 +217,7 @@ Gitlab::Application.routes.draw do @@ -217,7 +217,7 @@ Gitlab::Application.routes.draw do
217 resource :repository, only: [:show] do 217 resource :repository, only: [:show] do
218 member do 218 member do
219 get "stats" 219 get "stats"
220 - get "archive" 220 + get "archive", constraints: { format: Gitlab::Regex.archive_formats_regex }
221 end 221 end
222 end 222 end
223 223
lib/api/repositories.rb
  1 +require 'mime/types'
  2 +
1 module API 3 module API
2 # Projects API 4 # Projects API
3 class Repositories < Grape::API 5 class Repositories < Grape::API
@@ -206,18 +208,20 @@ module API @@ -206,18 +208,20 @@ module API
206 # sha (optional) - the commit sha to download defaults to the tip of the default branch 208 # sha (optional) - the commit sha to download defaults to the tip of the default branch
207 # Example Request: 209 # Example Request:
208 # GET /projects/:id/repository/archive 210 # GET /projects/:id/repository/archive
209 - get ":id/repository/archive" do 211 + get ":id/repository/archive", requirements: { format: Gitlab::Regex.archive_formats_regex } do
210 authorize! :download_code, user_project 212 authorize! :download_code, user_project
211 repo = user_project.repository 213 repo = user_project.repository
212 ref = params[:sha] 214 ref = params[:sha]
  215 + format = params[:format]
213 storage_path = Rails.root.join("tmp", "repositories") 216 storage_path = Rails.root.join("tmp", "repositories")
214 217
215 - file_path = repo.archive_repo(ref, storage_path) 218 + file_path = repo.archive_repo(ref, storage_path, format)
216 if file_path && File.exists?(file_path) 219 if file_path && File.exists?(file_path)
217 data = File.open(file_path, 'rb').read 220 data = File.open(file_path, 'rb').read
218 221
219 - header "Content-Disposition:", " infile; filename=\"#{File.basename(file_path)}\""  
220 - content_type 'application/x-gzip' 222 + header["Content-Disposition"] = "attachment; filename=\"#{File.basename(file_path)}\""
  223 +
  224 + content_type MIME::Types.type_for(file_path).first.content_type
221 225
222 env['api.format'] = :binary 226 env['api.format'] = :binary
223 227
lib/gitlab/regex.rb
@@ -17,6 +17,11 @@ module Gitlab @@ -17,6 +17,11 @@ module Gitlab
17 def path_regex 17 def path_regex
18 default_regex 18 default_regex
19 end 19 end
  20 +
  21 + def archive_formats_regex
  22 + #|zip|tar| tar.gz | tar.bz2 |
  23 + /(zip|tar|tar\.gz|tgz|gz|tar\.bz2|tbz|tbz2|tb2|bz2)/
  24 + end
20 25
21 def git_reference_regex 26 def git_reference_regex
22 # Valid git ref regex, see: 27 # Valid git ref regex, see:
spec/requests/api/repositories_spec.rb
1 require 'spec_helper' 1 require 'spec_helper'
  2 +require 'mime/types'
2 3
3 describe API::API do 4 describe API::API do
4 include ApiHelpers 5 include ApiHelpers
@@ -232,11 +233,29 @@ describe API::API do @@ -232,11 +233,29 @@ describe API::API do
232 end 233 end
233 end 234 end
234 235
235 - describe "GET /projects/:id/repository/archive/:sha" do 236 + describe "GET /projects/:id/repository/archive(.:format)?:sha" do
236 it "should get the archive" do 237 it "should get the archive" do
237 get api("/projects/#{project.id}/repository/archive", user) 238 get api("/projects/#{project.id}/repository/archive", user)
  239 + repo_name = project.repository.name.gsub("\.git", "")
238 response.status.should == 200 240 response.status.should == 200
239 - response.content_type.should == 'application/x-gzip' 241 + response.headers['Content-Disposition'].should =~ /filename\=\"#{repo_name}\-[^\.]+\.tar.gz\"/
  242 + response.content_type.should == MIME::Types.type_for('file.tar.gz').first.content_type
  243 + end
  244 +
  245 + it "should get the archive.zip" do
  246 + get api("/projects/#{project.id}/repository/archive.zip", user)
  247 + repo_name = project.repository.name.gsub("\.git", "")
  248 + response.status.should == 200
  249 + response.headers['Content-Disposition'].should =~ /filename\=\"#{repo_name}\-[^\.]+\.zip\"/
  250 + response.content_type.should == MIME::Types.type_for('file.zip').first.content_type
  251 + end
  252 +
  253 + it "should get the archive.tar.bz2" do
  254 + get api("/projects/#{project.id}/repository/archive.tar.bz2", user)
  255 + repo_name = project.repository.name.gsub("\.git", "")
  256 + response.status.should == 200
  257 + response.headers['Content-Disposition'].should =~ /filename\=\"#{repo_name}\-[^\.]+\.tar.bz2\"/
  258 + response.content_type.should == MIME::Types.type_for('file.tar.bz2').first.content_type
240 end 259 end
241 260
242 it "should return 404 for invalid sha" do 261 it "should return 404 for invalid sha" do
spec/routing/project_routing_spec.rb
@@ -130,6 +130,14 @@ describe Projects::RepositoriesController, &quot;routing&quot; do @@ -130,6 +130,14 @@ describe Projects::RepositoriesController, &quot;routing&quot; do
130 get("/gitlab/gitlabhq/repository/archive").should route_to('projects/repositories#archive', project_id: 'gitlab/gitlabhq') 130 get("/gitlab/gitlabhq/repository/archive").should route_to('projects/repositories#archive', project_id: 'gitlab/gitlabhq')
131 end 131 end
132 132
  133 + it "to #archive format:zip" do
  134 + get("/gitlab/gitlabhq/repository/archive.zip").should route_to('projects/repositories#archive', project_id: 'gitlab/gitlabhq', format: 'zip')
  135 + end
  136 +
  137 + it "to #archive format:tar.bz2" do
  138 + get("/gitlab/gitlabhq/repository/archive.tar.bz2").should route_to('projects/repositories#archive', project_id: 'gitlab/gitlabhq', format: 'tar.bz2')
  139 + end
  140 +
133 it "to #show" do 141 it "to #show" do
134 get("/gitlab/gitlabhq/repository").should route_to('projects/repositories#show', project_id: 'gitlab/gitlabhq') 142 get("/gitlab/gitlabhq/repository").should route_to('projects/repositories#show', project_id: 'gitlab/gitlabhq')
135 end 143 end