Authorization for trees controller
[gitorious:mainline.git] / app / controllers / trees_controller.rb
1 # encoding: utf-8
2 #--
3 #   Copyright (C) 2012 Gitorious AS
4 #   Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
5 #   Copyright (C) 2009 Fabio Akita <fabio.akita@gmail.com>
6 #   Copyright (C) 2008 Tor Arne Vestbø <tavestbo@trolltech.com>
7 #   Copyright (C) 2008 Johan Sørensen <johan@johansorensen.com>
8 #
9 #   This program is free software: you can redistribute it and/or modify
10 #   it under the terms of the GNU Affero General Public License as published by
11 #   the Free Software Foundation, either version 3 of the License, or
12 #   (at your option) any later version.
13 #
14 #   This program is distributed in the hope that it will be useful,
15 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
16 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 #   GNU Affero General Public License for more details.
18 #
19 #   You should have received a copy of the GNU Affero General Public License
20 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 #++
22
23 class TreesController < ApplicationController
24   include Gitorious::Messaging::Publisher
25   before_filter :find_project_and_repository
26   before_filter :check_repository_for_commits
27   renders_in_site_specific_context :except => [:archive]
28
29   def index
30     redirect_to repo_owner_path(@repository, :project_repository_tree_path,
31                   @project, @repository, branch_with_tree(@repository.head_candidate_name, []))
32   end
33
34   def show
35     @git = @repository.git
36     @ref, @path = branch_and_path(params[:branch_and_path], @git)
37     unless @commit = @git.commit(@ref)
38       handle_missing_tree_sha and return
39     end
40     if stale_conditional?(Digest::SHA1.hexdigest(@commit.id + params[:branch_and_path].join),
41                           @commit.committed_date.utc)
42       head = @git.get_head(@ref) || Grit::Head.new(@commit.id_abbrev, @commit)
43       @root = Breadcrumb::Folder.new({:paths => @path, :head => head,
44                                       :repository => @repository})
45       path = @path.blank? ? [] : ["#{@path.join("/")}/"] # FIXME: meh, this sux
46       @tree = @git.tree(@commit.tree.id, path)
47       expires_in 30.seconds
48     end
49   end
50
51   def archive
52     @git = @repository.git
53     # FIXME: update route when we've fixed rails bug #1939
54     @ref = desplat_path(params[:branch])
55     ext = params[:archive_format]
56     unless @commit = @git.commit(@ref)
57       handle_missing_tree_sha and return
58     end
59
60     if !@commit
61       flash[:error] = I18n.t "trees_controller.archive_error"
62       redirect_to project_repository_path(@project, @repository) and return
63     end
64
65     user_path = "#{@repository.project_or_owner.to_param}-#{@repository.to_param}-#{@ref}.#{ext}"
66     disk_path = "#{@repository.hashed_path.gsub(/\//,'-')}-#{@commit.id}.#{ext}"
67     if File.exist?(File.join(GitoriousConfig["archive_cache_dir"], disk_path))
68       respond_to do |format|
69         format.html {
70           set_xsendfile_headers(disk_path, user_path)
71           head(:ok) and return
72         }
73         format.js {
74           render :partial => "archive_ready"
75         }
76       end
77     else
78       # enqueue the creation of the tarball, and send an accepted response
79       if !File.exist?(File.join(GitoriousConfig["archive_work_dir"], disk_path))
80         publish_archive_message(@repository, disk_path, @commit)
81       end
82
83       respond_to do |format|
84         format.html {
85           # FIXME: This doesn't fly with wget/curl/etc type clients
86           render :text => "The archive is currently being generated, try again later",
87             :status => :accepted, :content_type => "text/plain" and return
88         }
89         format.js {
90           render :partial => "archive_generating"
91         }
92       end
93     end
94   end
95
96   protected
97     def set_xsendfile_headers(real_path, user_path, content_type = "application/x-gzip")
98       response.headers["X-Sendfile"] = File.join(GitoriousConfig["archive_cache_dir"], real_path)
99       response.headers["Content-Type"] = content_type
100       user_path = user_path.gsub("/", "_").gsub('"', '\"')
101       response.headers["Content-Disposition"] = "Content-Disposition: attachment; filename=\"#{user_path}\""
102     end
103
104     def publish_archive_message(repo, disk_path, commit)
105       publish("/queue/GitoriousRepositoryArchiving", {
106         :full_repository_path => repo.full_repository_path,
107         :output_path => File.join(GitoriousConfig["archive_cache_dir"], disk_path),
108         :work_path => File.join(GitoriousConfig["archive_work_dir"], disk_path),
109         :commit_sha => commit.id,
110         :name => (repo.project.slug + "-" + repo.name),
111         :format => "tar.gz",
112       })
113     end
114
115     def handle_missing_tree_sha
116       flash[:error] = "No such tree SHA1 was found"
117       redirect_to project_repository_tree_path(@project, @repository,
118                       branch_with_tree("HEAD", @path || []))
119     end
120 end