Commit 7cc25205410efc6b20b11d94ab2cbc1a322ff816
1 parent
b512fbc0
Exists in
spb-stable
and in
3 other branches
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}
Showing
6 changed files
with
44 additions
and
8 deletions
Show diff stats
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, "routing" do | @@ -130,6 +130,14 @@ describe Projects::RepositoriesController, "routing" 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 |