Commit 8c930210231c6383bb5c40fbf3b69a3676b3a5e0

Merge commit 'johan/master'

* commit 'johan/master': (70 commits)
updated todo
FIXED: order events desc
color code various events just a tiny bit
Smaller more matching feed icon
html escape commits in events
Made the user feed a member action, since usernames can contain dots
output less from rebuild_events
Updated TODO
commits-by-author graph should use gitorious username (if found)
Disabling readme rendering until we decided on the specifics
Fixed event display of commit message. TODO updated
atom feed for /events.
simple_format for event body
Fixed formatted user path, Make (more) visible the atom feed for activities
Sanitize the README content
Added method to link file path to blob
Render README for repositories
fix submenu positioning in webkit
Simplify rounded corners css, and add webkit support
Print less from *-receive hooks
...

Commit diff

TODO.txt

 
1events:
2* need to create user-less events even we don't find matching users, otherwise it gets weird whenever there's commits from non-registered gitorious users (or users commit from another email).
3- maybe save name+email in events table in that case, so we can hook them up to a user later if needed.
4
5new-ui:
6* mandatory project descriptions, at least a sentence or two
7* tweak fonts-sizes and line-heights
8* Clone stats graph on repositories#index
9* popular & active projects on frontpage
10* make the top-header smaller (move gitorious logo to footer?)
11
112(in no particular order)
213
314two from Yurii:
1717
1818* tree browser: deal better with funny characters: http://gitorious.org/projects/avara/repos/mainline/trees/master
1919* if you comment on a specific commit, you should get redirected back there
20* graphs should show username (if we have it) for avoiding confusion and for consistency
21** Repository#commit_graph_data_by_author should just use git-shortlog summary instead of jumping through hoops about it
2220
2321> If you do `git archive --format=tar --prefix=myproject/ HEAD | gzip >
2422> myproject.tar.gz`, when .gitattributes specifies files that have
2525> it'd be pretty nice if it did.
2626
2727* Deal gracefully with markdown errors (and/or look into using the other markdown libary instead)
28* Don't generate graphs with big "No Data", text even if there's no data
2928* Markdownify atom feed body for projects.atom
3029* Make the fact that you _can_ clone/fork any repo more visible, maybe reword it since people confuse it with local cloning
3130* Show the most recent mergerequests on users dashboard so they can track them
4040* Nicer diff stats
4141* more interesting project stats on frontpage
4242* parse git submodule data and link to project if submodule is in gitorious
43* link to users in gitorious in commmits if email match
4443* add mainline as a remote branch in clones
4544* timezone support
4645* Email source_repository owner about merge_request changes
toggle raw diff

app/controllers/comments_controller.rb

 
2929 @comment.project = @project
3030 respond_to do |format|
3131 if @comment.save
32 @project.create_event(Action::COMMENT, @comment, current_user)
3233 format.html do
3334 flash[:success] = "Your comment was added"
3435 redirect_to project_repository_comments_path(@project, @repository)
toggle raw diff

app/controllers/committers_controller.rb

 
2121
2222 respond_to do |format|
2323 if @repository.add_committer(@committer)
24 @committership = @repository.committerships.find_by_user_id(@committer.id)
25 @project.create_event(Action::ADD_COMMITTER, @committership, current_user)
2426 format.html { redirect_to([@repository.project, @repository]) }
2527 format.xml do
2628 render :xml => @committer
4040
4141 respond_to do |format|
4242 if @committership.destroy
43 @project.create_event(Action::REMOVE_COMMITTER, @repository, current_user, params[:id])
4344 flash[:success] = "User removed from repository"
4445 format.html { redirect_to [@repository.project, @repository] }
4546 format.xml { render :nothing, :status => :ok }
toggle raw diff

app/controllers/events_controller.rb

 
1class EventsController < ApplicationController
2 def index
3 @events = Event.paginate(:all, :order => "events.created_at desc",
4 :page => params[:page], :include => [:user])
5 @atom_auto_discovery_url = formatted_events_path(:atom)
6
7 respond_to do |if_format_is|
8 if_format_is.html {}
9 if_format_is.atom {}
10 end
11 end
12
13end
toggle raw diff

app/controllers/merge_requests_controller.rb

 
3131 @merge_request.user = current_user
3232 respond_to do |format|
3333 if @merge_request.save
34 @project.create_event(Action::REQUEST_MERGE, @merge_request, current_user)
3435 format.html {
3536 flash[:success] = %Q{You sent a merge request to "#{@merge_request.target_repository.name}"}
3637 redirect_to project_repository_path(@project, @repository) and return
5151 # TODO: put to change status
5252 @merge_request.status = params[:merge_request][:status]
5353 if @merge_request.save
54 @project.create_event(Action::RESOLVE_MERGE_REQUEST, @merge_request, current_user)
5455 flash[:notice] = "The merge request was marked as #{@merge_request.status_string}"
5556 end
5657 redirect_to [@project, @repository, @merge_request]
6464 def update
6565 @merge_request.attributes = params[:merge_request]
6666 if @merge_request.save
67 @project.create_event(Action::UPDATE_MERGE_REQUEST, @merge_request, current_user)
6768 flash[:success] = "Merge request was updated"
6869 redirect_to [@project, @repository, @merge_request]
6970 else
7575
7676 def destroy
7777 @merge_request.destroy
78 @project.create_event(Action::DELETE_MERGE_REQUEST, @repository, current_user)
7879 flash[:success] = "Merge request was retracted"
7980 redirect_to project_repository_path(@project, @repository)
8081 end
toggle raw diff

app/controllers/projects_controller.rb

 
3131
3232 def show
3333 @project = Project.find_by_slug!(params[:id], :include => [:repositories])
34 @repositories = @project.repositories
34 @mainline_repository = @project.mainline_repository
35 @repositories = @project.repository_clones
36 @events = @project.events.paginate(:all, :page => params[:page],
37 :order => "created_at desc", :include => [:user, :project])
38 @atom_auto_discovery_url = formatted_project_path(@project, :atom)
3539
3640 respond_to do |format|
3741 format.html
38 format.xml { render :xml => @project }
42 format.xml { render :xml => @project }
43 format.atom { }
3944 end
4045 end
4146
5151 @project = Project.new(params[:project])
5252 @project.user = current_user
5353 if @project.save
54 @project.create_event(Action::CREATE_PROJECT, @project, current_user)
5455 redirect_to projects_path
5556 else
5657 render :action => 'new'
7070 end
7171 @project.attributes = params[:project]
7272 if @project.save
73 @project.create_event(Action::UPDATE_PROJECT, @project, current_user)
7374 redirect_to project_path(@project)
7475 else
7576 render :action => 'new'
8484 def destroy
8585 @project = Project.find_by_slug!(params[:id])
8686 if @project.can_be_deleted_by?(current_user)
87 project_title = @project.title
8788 @project.destroy
89 #current_user.create_event(Action::DELETE_PROJECT, nil, project_title)
8890 else
8991 flash[:error] = "You're not the owner of this project, or the project has clones"
9092 end
toggle raw diff

app/controllers/repositories_controller.rb

 
66 session :off, :only => [:writable_by]
77
88 def index
9 redirect_to(project_path(@project))
9 @repositories = @project.repositories.find(:all, :include => [:user, :events, :project])
1010 end
1111
1212 def show
1313 @repository = @project.repositories.find_by_name!(params[:id])
14 @comment_count = @repository.comments.count
15 @merge_request_count = @repository.merge_requests.count_open
16 if @repository.has_commits?
17 @commits = @repository.paginated_commits(@repository.head_candidate.name, page=1)
18 else
19 @commits = []
20 end
14 @events = @repository.events.paginate(:all, :page => params[:page],
15 :order => "created_at desc")
2116
2217 @atom_auto_discovery_url = formatted_project_repository_path(@project, @repository, :atom)
2318 respond_to do |format|
2419 format.html
2520 format.xml { render :xml => @repository }
26 format.atom { render :template => "logs/feed.atom.builder" }
21 format.atom { }
2722 end
2823 end
2924
5656
5757 respond_to do |format|
5858 if @repository.save
59 @project.create_event(Action::CLONE_REPOSITORY, @repository, current_user, @repository_to_clone.id)
60
5961 location = project_repository_path(@project, @repository)
6062 format.html { redirect_to location }
6163 format.xml { render :xml => @repository, :status => :created, :location => location }
8686 def destroy
8787 @repository = @project.repositories.find_by_name!(params[:id])
8888 if @repository.can_be_deleted_by?(current_user)
89 repo_name = @repository.name
8990 flash[:notice] = "The repository was deleted"
9091 @repository.destroy
92 @project.create_event(Action::DELETE_REPOSITORY, @project, current_user, repo_name)
9193 else
9294 flash[:error] = "You're not the owner of this repository"
9395 end
toggle raw diff

app/controllers/site_controller.rb

 
77
88 def dashboard
99 @projects = current_user.projects
10 project_ids = @projects.map(&:id)
11 @recent_comments = Comment.find(:all, :limit => 10,
12 :conditions => ["comments.project_id in (?)", project_ids],
13 :order => "comments.created_at desc", :include => [:user, :repository])
14 @repository_clones = Repository.find(:all, :order => "created_at desc",
15 :conditions => ["project_id in (?) and mainline = ?", project_ids, false])
16
17 @repositories = current_user.repositories.find(:all, :conditions => ["mainline = ?", false])
10 @repositories = current_user.repositories.find(:all,
11 :conditions => ["mainline = ?", false])
12 event_project_ids = (@projects.map(&:id) + @repositories.map(&:project_id)).uniq
13 @events = Event.paginate(:all,
14 :page => params[:page],
15 :conditions => ["events.project_id in (?)", event_project_ids],
16 :order => "events.created_at desc",
17 :include => [:user, :project])
1818 end
1919
2020 def about
toggle raw diff

app/controllers/users_controller.rb

 
77 @user = User.find_by_login!(params[:id])
88 @projects = @user.projects.find(:all, :include => [:tags, { :repositories => :project }])
99 @repositories = @user.repositories.find(:all, :conditions => ["mainline = ?", false])
10 @events = @user.events.paginate(:all,
11 :page => params[:page],
12 :order => "events.created_at desc",
13 :include => [:user, :project])
1014
11 @commits_last_week = 0
12 @projects.map{|p| p.repositories.first }.concat(@repositories).each do |repo|
13 @commits_last_week += repo.count_commits_from_last_week_by_user(@user)
15 @commits_last_week = @user.events.count(:all,
16 :conditions => ["created_at > ? AND action = ?", 7.days.ago, Action::COMMIT])
17 @atom_auto_discovery_url = formatted_feed_user_path(@user, :atom)
18
19 respond_to do |format|
20 format.html { }
21 format.atom { redirect_to formatted_feed_user_path(@user, :atom) }
22 end
23 end
24
25 def feed
26 @user = User.find_by_login!(params[:id])
27 @events = @user.events.find(:all, :order => "events.created_at desc",
28 :include => [:user, :project], :limit => 30)
29 respond_to do |format|
30 format.html { redirect_to user_path(@user) }
31 format.atom { }
1432 end
1533 end
1634
toggle raw diff

app/helpers/application_helper.rb

 
22module ApplicationHelper
33 include TagsHelper
44
5 def feed_icon(url, alt_title = "Atom feed", size = :small)
6 link_to image_tag("feed_12.png", :class => "feed_icon"), url,
7 :alt => alt_title, :title => alt_title
8 end
9
510 def default_css_tag_sizes
611 %w(tag_size_1 tag_size_2 tag_size_3 tag_size_4)
712 end
4343 end
4444 end
4545
46 def submenu_selected_class_if_current?(section)
47 case section
48 when :overview
49 if %w[projects].include?(controller.controller_name )
50 return "selected"
51 end
52 when :repositories
53 if %w[repositories trees logs commits comitters comments merge_requests
54 blobs committers].include?(controller.controller_name )
55 return "selected"
56 end
57 end
58 end
59
4660 def link_to_with_selected(name, options = {}, html_options = nil)
4761 html_options = current_page?(options) ? {:class => "selected"} : nil
4862 link_to(name, options = {}, html_options)
120120 image_tag("graphs/#{filename}")
121121 end
122122 end
123
124 def action_and_body_for_event(event)
125 target = event.target
126 action = ""
127 body = ""
128 category = ""
129 case event.action
130 when Action::CREATE_PROJECT
131 action = "<strong>created project</strong> #{link_to h(target.title), project_path(target)}"
132 body = truncate(target.stripped_description, 100)
133 category = "project"
134 when Action::DELETE_PROJECT
135 action = "<strong>deleted project</strong> #{h(event.data)}"
136 category = "project"
137 when Action::UPDATE_PROJECT
138 action = "<strong>updated project</strong> #{link_to h(target.title), project_path(target)}"
139 category = "project"
140 when Action::CLONE_REPOSITORY
141 original_repo = Repository.find_by_id(event.data.to_i)
142 next if original_repo.nil?
143
144 project = target.project
145
146 action = "<strong>forked</strong> #{link_to h(project.title), project_path(project)}/#{link_to h(original_repo.name), project_repository_url(project, original_repo)} in #{link_to h(target.name), project_repository_url(project, target)}"
147 category = "repository"
148 when Action::DELETE_REPOSITORY
149 action = "<strong>deleted repository</strong> #{link_to h(target.title), project_path(target)}/#{event.data}"
150 category = "project"
151 when Action::COMMIT
152 project = event.project
153 action = "<strong>committed</strong> #{link_to event.data[0,8], project_repository_commit_path(project, target, event.data)} to #{link_to h(project.slug), project_path(project)}/#{link_to h(target.name), project_repository_url(project, target)}"
154 body = link_to(h(truncate(event.body, 150)), project_repository_commit_path(project, target, event.data))
155 category = "commit"
156 when Action::CREATE_BRANCH
157 project = target.project
158 if event.data == "master"
159 action = "<strong>started development</strong> of #{link_to h(project.title), project_path(project)}/#{link_to h(target.name), project_repository_url(project, target)}"
160 body = event.body
161 else
162 action = "<strong>created branch</strong> #{link_to h(event.data), project_repository_tree_path(project, target, event.data)} on #{link_to h(project.title), project_path(project)}/#{link_to h(target.name), project_repository_url(project, target)}"
163 end
164 category = "commit"
165 when Action::DELETE_BRANCH
166 project = target.project
167 action = "<strong>deleted branch</strong> #{event.data} on #{link_to h(project.title), project_path(project)}/#{link_to h(target.name), project_repository_url(project, target)}"
168 category = "commit"
169 when Action::CREATE_TAG
170 project = target.project
171 action = "<strong>tagged</strong> #{link_to h(project.title), project_path(project)}/#{link_to h(target.name), project_repository_url(project, target)}"
172 body = "#{link_to event.data, project_repository_commit_path(project, target, event.data)}<br/>#{event.body}"
173 category = "commit"
174 when Action::DELETE_TAG
175 project = target.project
176 action = "<strong>deleted tag</strong> #{event.data} on #{link_to h(project.title), project_path(project)}/#{link_to h(target.name), project_repository_url(project, target)}"
177 category = "commit"
178 when Action::ADD_COMMITTER
179 user = target.user
180 repo = target.repository
181 action = "<strong>added committer</strong> #{link_to user.login, user_path(user)} to #{link_to h(repo.project.title), project_path(repo.project)}/#{link_to h(repo.name), project_repository_url(repo.project, repo)}"
182 category = "repository"
183 when Action::REMOVE_COMMITTER
184 user = User.find_by_id(event.data.to_i)
185 next unless user
186
187 project = target.project
188 action = "<strong>removed committer</strong> #{link_to user.login, user_path(user)} from #{link_to h(project.title), project_path(project)}/#{link_to h(target.name), project_repository_url(project, target)}"
189 category = "repository"
190 when Action::COMMENT
191 project = target.project
192 repo = target.repository
193
194 action = "<strong>commented</strong> on #{link_to h(project.title), project_path(project)}/#{link_to h(repo.name), project_repository_url(project, repo)}"
195 body = truncate(h(target.body), 150)
196 category = "comment"
197 when Action::REQUEST_MERGE
198 source_repository = target.source_repository
199 project = source_repository.project
200 target_repository = target.target_repository
201
202 action = "<strong>requested merge</strong> #{link_to h(project.title), project_path(project)}/#{link_to h(source_repository.name), project_repository_url(project, source_repository)} to #{link_to h(project.title), project_path(project)}/#{link_to h(target_repository.name)}"
203 body = "#{link_to "review", [project, target_repository, target]}<br/>#{truncate(h(target.proposal), 100)}"
204 category = "merge request"
205 when Action::RESOLVE_MERGE_REQUEST
206 source_repository = target.source_repository
207 project = source_repository.project
208 target_repository = target.target_repository
209
210 action = "<strong>resolved merge request </strong>to [#{target.status_string}] from #{link_to h(project.title), project_path(project)}/#{link_to h(source_repository.name), project_repository_url(project, source_repository)}"
211 category = "merge_request"
212 when Action::UPDATE_MERGE_REQUEST
213 source_repository = target.source_repository
214 project = source_repository.project
215 target_repository = target.target_repository
216
217 action = "<strong>updated merge request</strong> from #{link_to h(project.title), project_path(project)}/#{link_to h(source_repository.name), project_repository_url(project, source_repository)}"
218 category = "merge_request"
219 when Action::DELETE_MERGE_REQUEST
220 project = target.project
221
222 action = "<strong>deleted merge request</strong> from #{link_to h(project.title), project_path(project)}/#{link_to h(target.name), project_repository_url(project, target)}"
223 category = "merge_request"
224 end
225
226 [action, body, category]
227 end
228
229 def sidebar_content?
230 !@content_for_sidebar.blank?
231 end
232
233 def render_readme(repository)
234 possibilities = []
235 repository.git.git.ls_tree({:name_only => true}, "master").each do |line|
236 possibilities << line[0, line.length-1] if line =~ /README.*/
237 end
238
239 return "" if possibilities.empty?
240 text = repository.git.git.show({}, "master:#{possibilities.first}")
241 markdown(text) rescue simple_format(sanitize(text))
242 end
243
244 def file_path(repository, filename, head = "master")
245 project_repository_blob_path(repository.project, repository, head, filename)
246 end
123247end
toggle raw diff

app/helpers/events_helper.rb

 
1module EventsHelper
2end
toggle raw diff

app/models/action.rb

 
1class Action
2 CREATE_PROJECT = 0
3 DELETE_PROJECT = 1
4 UPDATE_PROJECT = 2
5 CLONE_REPOSITORY = 3
6 DELETE_REPOSITORY = 4
7 COMMIT = 5
8 CREATE_BRANCH = 6
9 DELETE_BRANCH = 7
10 CREATE_TAG = 8
11 DELETE_TAG = 9
12 ADD_COMMITTER = 10
13 REMOVE_COMMITTER = 11
14 COMMENT = 12
15 REQUEST_MERGE = 13
16 RESOLVE_MERGE_REQUEST = 14
17 UPDATE_MERGE_REQUEST = 15
18 DELETE_MERGE_REQUEST = 16
19
20 def self.name(action_id)
21 case action_id
22 when CREATE_PROJECT
23 "create project"
24 when DELETE_PROJECT
25 "delete project"
26 when UPDATE_PROJECT
27 "update project"
28 when CLONE_REPOSITORY
29 "clone repository"
30 when DELETE_REPOSITORY
31 "delete repository"
32 when COMMIT
33 "commit"
34 when CREATE_BRANCH
35 "create branch"
36 when DELETE_BRANCH
37 "delete branch"
38 when CREATE_TAG
39 "create tag"
40 when DELETE_TAG
41 "delete tag"
42 when ADD_COMMITTER
43 "add committer"
44 when REMOVE_COMMITTER
45 "remove committer"
46 when COMMENT
47 "comment"
48 when REQUEST_MERGE
49 "request merge"
50 when RESOLVE_MERGE_REQUEST
51 "resolve merge request"
52 when UPDATE_MERGE_REQUEST
53 "update merge request"
54 when DELETE_MERGE_REQUEST
55 "delete merge request"
56 end
57 end
58end
toggle raw diff