Merge remote-tracking branch 'official/master' into saltation
[gitorious:taladars-gitorious-saltation.git] / app / controllers / commits_controller.rb
1 # encoding: utf-8
2 #--
3 #   Copyright (C) 2011 Gitorious AS
4 #   Copyright (C) 2010 Marko Peltola <marko@markopeltola.com>
5 #   Copyright (C) 2010 Tero Hänninen <tero.j.hanninen@jyu.fi>
6 #   Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
7 #   Copyright (C) 2008 Johan Sørensen <johan@johansorensen.com>
8 #   Copyright (C) 2008 David A. Cuadrado <krawek@gmail.com>
9 #   Copyright (C) 2008 Tor Arne Vestbø <tavestbo@trolltech.com>
10 #
11 #   This program is free software: you can redistribute it and/or modify
12 #   it under the terms of the GNU Affero General Public License as published by
13 #   the Free Software Foundation, either version 3 of the License, or
14 #   (at your option) any later version.
15 #
16 #   This program is distributed in the hope that it will be useful,
17 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
18 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 #   GNU Affero General Public License for more details.
20 #
21 #   You should have received a copy of the GNU Affero General Public License
22 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 #++
24
25 class CommitsController < ApplicationController
26   before_filter :find_project_and_repository
27   before_filter :require_view_right_to_repository
28   before_filter :check_repository_for_commits
29   skip_before_filter :public_and_logged_in, :only => [:diffs]
30   skip_before_filter :require_current_eula, :only => [:diffs]
31   skip_after_filter :mark_flash_status, :only => [:diffs]
32   renders_in_site_specific_context
33
34   def index
35     if params[:branch].blank?
36       redirect_to_ref(@repository.head_candidate.name) and return
37     end
38
39     @git = @repository.git
40     @ref, @path = branch_and_path(params[:branch], @git)
41
42     head = get_head(@ref)
43     return handle_unknown_ref if head.nil?
44
45     if stale_conditional?(head.commit.id, head.commit.committed_date.utc)
46       @root = Breadcrumb::Branch.new(head, @repository)
47       @commits = @repository.cached_paginated_commits(@ref, params[:page])
48       @atom_auto_discovery_url = project_repository_formatted_commits_feed_path(@project, @repository, params[:branch], :atom)
49       respond_to do |format|
50         format.html
51       end
52     end
53   end
54
55   def show
56     @diffs = []
57     @diffmode = params[:diffmode] == "sidebyside" ? "sidebyside" : "inline"
58     @git = @repository.git
59     @diffs_url = project_repository_commit_diffs_url(:project_id => params[:project_id],
60                                                      :repository_id => params[:repository_id],
61                                                      :id => params[:id])
62     @comments_url = project_repository_commit_comments_url(:project_id => params[:project_id],
63                                                            :repository_id => params[:repository_id],
64                                                            :id => params[:id])
65
66     unless @commit = @git.commit(params[:id])
67       handle_missing_sha and return
68     end
69
70     respond_to do |format|
71       format.html
72
73       format.diff do
74         render(:text => commit_diffs.map { |d| d.diff }.join("\n"),
75                :content_type => "text/plain")
76       end
77
78       format.patch do
79         render :text => @commit.to_patch, :content_type => "text/plain"
80       end
81     end
82   end
83
84   def comments
85     @comments = @repository.comments.find_all_by_sha1(params[:id], :include => :user)
86     last_modified = @comments.size > 0 ? @comments.last.created_at.utc : Time.at(0)
87
88     if stale_conditional?([params[:id], @comments.size], last_modified)
89       @comment_count = @comments.length
90       render :layout => !request.xhr?
91     end
92   end
93
94   def diffs
95     @comments = []
96     @diffmode = params[:diffmode] == "sidebyside" ? "sidebyside" : "inline"
97     @git = @repository.git
98
99     unless @commit = @git.commit(params[:id])
100       handle_missing_sha and return
101     end
102
103     @root = Breadcrumb::Commit.new(:repository => @repository, :id => @commit.id_abbrev)
104     @diffs = commit_diffs
105     @committer_user = User.find_by_email_with_aliases(@commit.committer.email)
106     @author_user = User.find_by_email_with_aliases(@commit.author.email)
107     headers["Cache-Control"] = "public, max-age=315360000"
108
109     render :layout => !request.xhr?
110   end
111
112   def feed
113     @git = @repository.git
114     @ref = desplat_path(params[:branch])
115     @commits = @repository.git.commits(@ref, 1)
116     return if @commits.empty?
117     expires_in 30.minutes
118     if stale?(:etag => @commits.first.id, :last_modified => @commits.first.committed_date.utc)
119       @commits += @repository.git.commits(@ref, 49, 1)
120       respond_to do |format|
121         format.atom
122       end
123     end
124   end
125   
126   protected
127     def handle_missing_sha
128       flash[:error] = "No such SHA1 was found"
129       redirect_to repo_owner_path(@repository, :project_repository_commits_path, @project, 
130                       @repository)
131     end
132     
133     def redirect_to_ref(ref)
134       redirect_to repo_owner_path(@repository, :project_repository_commits_in_ref_path, 
135                       @project, @repository, ref)
136     end
137
138     def commit_diffs
139       @commit.parents.empty? ? [] : @commit.diffs
140     end
141
142     def get_head(ref)
143       if h = @git.get_head(ref)
144         return h
145       end
146
147       begin
148         if commit = @git.commit(@ref)
149           return Grit::Head.new(commit.id_abbrev, commit)
150         end
151       rescue Errno::EISDIR => err
152       end
153
154       nil
155     end
156
157     def handle_unknown_ref
158       flash[:error] = "\"#{CGI.escapeHTML(@ref)}\" was not a valid ref, trying #{CGI.escapeHTML(@git.head.name)} instead"
159       redirect_to_ref(@git.head.name)
160     end
161 end