Commit f52b5724cd43dd33fa5dee56481ae43847808c91

Merge branch 'master' of git://gitorious.org/gitorious/mainline

Commit diff

app/controllers/browse_controller.rb

 
4848 end
4949 @blob = @git.tree(@commit.tree.id, ["#{params[:path].join("/")}"]).contents.first
5050 render_not_found and return unless @blob
51 unless @blob.respond_to?(:data) # it's a tree
52 redirect_to project_repository_tree_path(@project, @repository, @commit.id, params[:path])
53 end
5154 end
5255
5356 def raw
toggle raw diff

app/controllers/comments_controller.rb

 
55
66 def index
77 @comments = @repository.comments.find(:all, :include => :user)
8 @merge_request_count = @repository.merge_requests.count_open
89 @atom_auto_discovery_url = formatted_project_repository_comments_path(@project, @repository, :atom)
910 respond_to do |format|
1011 format.html { }
toggle raw diff

app/controllers/merge_requests_controller.rb

 
1class MergeRequestsController < ApplicationController
2 before_filter :login_required, :except => [:index, :show]
3 before_filter :find_project
4 before_filter :find_repository
5 before_filter :find_merge_request, :except => [:index, :show, :new, :create]
6 before_filter :assert_merge_request_ownership, :except => [:index, :show, :new, :create, :resolve]
7 before_filter :assert_merge_request_resolvable, :only => [:resolve]
8
9 def index
10 @merge_requests = @repository.merge_requests
11 @comment_count = @repository.comments.count
12 #@proposed_merge_requests = @repository.proposed_merge_requests
13 end
14
15 def show
16 @merge_request = @repository.merge_requests.find(params[:id])
17 @commits = @merge_request.target_repository.git.commit_deltas_from(@merge_request.source_repository.git)
18 end
19
20 def new
21 @merge_request = @repository.proposed_merge_requests.new(:user => current_user)
22 @repositories = @project.repositories.find(:all, :conditions => ["id != ?", @repository.id])
23 end
24
25 def create
26 @merge_request = @repository.proposed_merge_requests.new(params[:merge_request])
27 @merge_request.user = current_user
28 if @merge_request.save
29 flash[:success] = "Your sent a merge request to #{@merge_request.target_repository.name}"
30 redirect_to project_repository_path(@project, @repository) and return
31 else
32 @repositories = @project.repositories.find(:all, :conditions => ["id != ?", @repository.id])
33 render :action => "new"
34 end
35 end
36
37 def resolve
38 # TODO: put to change status
39 @merge_request.status = params[:merge_request][:status]
40 if @merge_request.save
41 flash[:notice] = "The merge request was marked as #{@merge_request.status_string}"
42 end
43 redirect_to [@project, @repository, @merge_request]
44 end
45
46 def edit
47 @repositories = @project.repositories.find(:all, :conditions => ["id != ?", @repository.id])
48 end
49
50 def update
51 @merge_request.attributes = params[:merge_request]
52 if @merge_request.save
53 flash[:success] = "Merge request was updated"
54 redirect_to [@project, @repository, @merge_request]
55 else
56 @repositories = @project.repositories.find(:all, :conditions => ["id != ?", @repository.id])
57 render :action => "edit"
58 end
59 end
60
61 def destroy
62 @merge_request.destroy
63 flash[:success] = "Merge request was retracted"
64 redirect_to project_repository_path(@project, @repository)
65 end
66
67 protected
68 def find_repository
69 @repository = @project.repositories.find_by_name!(params[:repository_id])
70 end
71
72 def find_merge_request
73 @merge_request = @repository.merge_requests.find(params[:id])
74 end
75
76 def assert_merge_request_resolvable
77 unless @merge_request.resolvable_by?(current_user)
78 respond_to do |format|
79 flash[:error] = "You're not permitted to resolve this merge request"
80 format.html { redirect_to([@project, @repository, @merge_request]) }
81 format.xml { render :text => "You're not permitted to resolve this merge request", :status => :forbidden }
82 end
83 return
84 end
85 end
86
87 def assert_merge_request_ownership
88 if @merge_request.user != current_user
89 respond_to do |format|
90 flash[:error] = "You're not the owner of this merge request"
91 format.html { redirect_to([@project, @repository]) }
92 format.xml { render :text => "You're not the owner of this merge request", :status => :forbidden }
93 end
94 return
95 end
96 end
97
98end
toggle raw diff

app/controllers/repositories_controller.rb

 
1212 def show
1313 @repository = @project.repositories.find_by_name!(params[:id])
1414 @comment_count = @repository.comments.count
15 @merge_request_count = @repository.merge_requests.count_open
1516 if @repository.has_commits?
1617 @commits = @repository.git.commits(@repository.head_candidate.name, 10)
1718 else
toggle raw diff

app/helpers/application_helper.rb

 
88
99 def linked_tag_list_as_sentence(tags)
1010 tags.map do |tag|
11 link_to(h(tag.name), { :action => :category, :id => tag.name })
11 link_to(h(tag.name), { :controller => "projects", :action => "category", :id => tag.name })
1212 end.to_sentence
1313 end
1414
toggle raw diff

app/helpers/merge_requests_helper.rb

 
1module MergeRequestsHelper
2end
toggle raw diff

app/models/mailer.rb

 
2121 @body[:url] = "http://gitorious.org/p/#{repository.project.slug}/repos/#{repository.name}"
2222 end
2323
24 def merge_request_notification(merge_request)
25 setup_email(merge_request.target_repository.user)
26 @subject += %Q{#{merge_request.source_repository.user.login} has requested a merge in #{merge_request.target_repository.project.title}}
27 @body[:merge_request] = merge_request
28 @body[:project] = merge_request.target_repository.project
29 url = "http://gitorious.org/p/#{merge_request.target_repository.project.slug}"
30 url << "/repos/#{merge_request.target_repository.name}"
31 url << "/merge_requests/#{merge_request.id}"
32 @body[:url] = url
33 end
34
2435 protected
2536 def setup_email(user)
2637 @recipients = "#{user.email}"
toggle raw diff

app/models/merge_request.rb

 
1class MergeRequest < ActiveRecord::Base
2 belongs_to :user
3 belongs_to :source_repository, :class_name => 'Repository'
4 belongs_to :target_repository, :class_name => 'Repository'
5
6 attr_protected :user, :status
7
8 STATUS_OPEN = 0
9 STATUS_MERGED = 1
10 STATUS_REJECTED = 2
11
12 validates_presence_of :user, :source_repository, :target_repository
13 attr_protected :user_id
14
15 def self.statuses
16 { "Open" => STATUS_OPEN, "Merged" => STATUS_MERGED, "Rejected" => STATUS_REJECTED }
17 end
18
19 def self.count_open
20 count(:all, :conditions => {:status => STATUS_OPEN})
21 end
22
23 def status_string
24 self.class.statuses.invert[status].downcase
25 end
26
27 def open?
28 status == STATUS_OPEN
29 end
30
31 def merged?
32 status == STATUS_MERGED
33 end
34
35 def rejected?
36 status == STATUS_REJECTED
37 end
38
39 def resolvable_by?(candidate)
40 candidate == target_repository.user
41 end
42end
toggle raw diff

app/models/merge_request_observer.rb

 
1class MergeRequestObserver < ActiveRecord::Observer
2
3 def after_create(record)
4 Mailer.deliver_merge_request_notification(record)
5 end
6
7end
toggle raw diff

app/models/repository.rb

 
55 has_many :committerships, :dependent => :destroy
66 has_many :committers, :through => :committerships, :source => :user
77 has_many :comments, :dependent => :destroy
8 has_many :merge_requests, :foreign_key => 'target_repository_id', :order => "status, id desc"
9 has_many :proposed_merge_requests, :foreign_key => 'source_repository_id',
10 :class_name => 'MergeRequest', :order => "id desc"
811
912 validates_presence_of :user_id, :project_id, :name
1013 validates_format_of :name, :with => /^[a-z0-9_\-]+$/i,
toggle raw diff

app/views/comments/index.html.erb

 
1515<ul class="tab_menu">
1616 <li><%= link_to "Recent commits", project_repository_path(@project, @repository) -%></li>
1717 <li class="selected">Comments (<%= @comments.size -%>)</li>
18 <li><%= link_to "merge requests(#{@merge_request_count})",
19 project_repository_merge_requests_path(@project, @repository) -%></li>
1820</ul>
1921
2022<%= render :partial => @comments -%>
toggle raw diff

app/views/mailer/merge_request_notification.rhtml

 
1Hello <%= @merge_request.target_repository.user.login -%>,
2
3<%= @merge_request.source_repository.user.login -%> has requested that you merge <%= @merge_request.source_repository.name -%> with <%= @merge_request.target_repository.name -%> in the <%= @project.title -%> project.
4
5You can review the request and its commits here:
6<%= @url %>
7
8Thank you
9
10http://gitorious.org
toggle raw diff

app/views/merge_requests/_form.html.erb

 
1<p>
2 <%= form.label :target_repository_id -%><br />
3 <small class="hint">The one you wish this repository should be merged with</small><br />
4 <%= form.select :target_repository_id, @repositories.map{|r| [r.name, r.id] } -%>
5</p>
6<p>
7 <%= form.label :proposal -%><br />
8 <small class="hint">A short summary of your changes</small><br />
9 <%= form.text_area :proposal, :class => "text medium" -%>
10</p>
toggle raw diff

app/views/merge_requests/_merge_request.html.erb

 
1<% no_link ||= false -%>
2
3<div class="merge_request_summary <%= merge_request.status_string -%>">
4 <p class="status">[<span><%= merge_request.status_string -%></span>]</p>
5 <h5>
6 <%= link_to h(merge_request.source_repository.name), [@project, merge_request.source_repository] -%>
7 has requested a merge with <%= link_to h(merge_request.target_repository.name), [@project, merge_request.target_repository] -%>:
8 </h5>
9 <div class="proposal"><%= sanitize(simple_format(merge_request.proposal)) -%></div>
10 <p class="byline">
11 <%= link_to(h(merge_request.user.login), merge_request.user) -%> |
12 <%= merge_request.created_at.to_s(:short) -%>
13 <% unless no_link -%>
14 | <strong><%= link_to "Review merge request &#x2192;", [@project, @repository, merge_request] -%></strong>
15 <% end -%>
16 </p>
17</div>
toggle raw diff

app/views/merge_requests/index.html.erb

 
1<% @page_title = "Merge requests in #{h(@repository.name)}" -%>
2<h1>
3 Merge requests in <%=h @repository.name -%>
4</h1>
5
6<%= render :partial => "repositories/infobox" -%>
7
8<p class="hint">
9 A "merge request" is a notification from one repository to another that
10 would like their changes to be merged upstream.
11</p>
12
13<ul class="tab_menu">
14 <li><%= link_to "Recent commits", project_repository_path(@project, @repository) -%></li>
15 <li><%= link_to "comments (#{@comment_count})",
16 project_repository_comments_path(@project, @repository) -%></li>
17 <li class="selected">merge requests(<%= @merge_requests.select{|mr| mr.open? }.size -%>)</li>
18</ul>
19
20<% if @merge_requests.blank? -%>
21 <p>
22 <em>No merge requests yet</em><br />
23 </p>
24<% else -%>
25 <%= render :partial => @merge_requests -%>
26<% end -%>
toggle raw diff

app/views/merge_requests/new.html.erb

 
1<h1>Create a merge request</h1>
2
3<%= error_messages_for :merge_request -%>
4
5<% form_for [@project, @repository, @merge_request] do |f| -%>
6 <%= render :partial => "form", :locals => {:form => f} -%>
7
8 <%= f.submit "Create merge request" -%>
9<% end -%>
toggle raw diff

app/views/merge_requests/show.html.erb

 
1<h1>
2 Reviewing merge request "<%=h @merge_request.source_repository.name -%>" &#x2192;
3 "<%= @merge_request.target_repository.name -%>"
4</h1>
5
6<%= render :partial => @merge_request, :locals => { :no_link => true } -%>
7
8<% if @merge_request.resolvable_by?(current_user) -%>
9 <% form_for @merge_request,
10 :url => resolve_project_repository_merge_request_path(@project,
11 @repository, @merge_request) do |f| -%>
12 <p>
13 <%= f.label :status -%><br />
14 <%= f.select :status, MergeRequest.statuses.sort_by{|k,v| v } -%><br />
15 <%= f.submit "Update merge request" -%></p>
16 <% end -%>
17
18 <% if @merge_request.open? -%>
19 <p>The simplest way to merge in these changes is to simply pull them in with the following command:</p>
20 <pre>git pull <%= @merge_request.source_repository.clone_url -%></pre>
21 <% end -%>
22<% end -%>
23
24<% if @merge_request.open? -%>
25<h2>Commits that would be merged:</h2>
26
27<ul class="shortlog">
28 <% @commits.each do |commit| -%>
29 <li><a href=""><%= link_to h(commit.id_abbrev),
30 project_repository_commit_path(@project, @merge_request.source_repository, commit.id) -%></a>
31 by <strong><%=h commit.committer.name -%></strong> <%=h time_ago_in_words(commit.committed_date) -%> ago
32 <div class="commit_message"><%= simple_format(h(commit.message)) -%></div></li>
33 <% end -%>
34</ul>
35<% end -%>
toggle raw diff

app/views/projects/index.atom.builder

 
88 entry.title(project.title)
99 entry.content(project.description)
1010 entry.author do |author|
11 author.name("Gitorious")
11 author.name(project.user.login)
1212 end
1313 end
1414 end
toggle raw diff

app/views/repositories/_infobox.html.erb

 
77 <% end -%>
88 <li><strong>Created:</strong> <%= @repository.created_at.to_s(:short) -%></li>
99 <li>
10 <strong>Clone url:</strong> <code><%=h @repository.clone_url -%></code>
10 <strong>Public clone url:</strong> <code><%=h @repository.clone_url -%></code>
1111 <small><%= link_to_function "More info…", "$('detailed_clone_info').toggle()" -%></small>
1212 <div id="detailed_clone_info" class="info_hint" style="display:none">
1313 You can clone this repository with the following command:<br />
14 <% if logged_in? && current_user.can_write_to?(@repository) -%>
15 <code>git clone <%= @repository.push_url -%></code>
16 <% else -%>
17 <code>git clone <%= @repository.clone_url -%></code>
18 <% end -%>
14 <code>git clone <%= @repository.clone_url -%></code>
1915 </div>
2016 </li>
2117 <li>
1919 <small><%= link_to_function "More info…", "$('detailed_http_clone_info').toggle()" -%></small>
2020 <div id="detailed_http_clone_info" class="info_hint" style="display:none">
2121 You can clone this repository with the following command:<br />
22 <code>git clone <%= @repository.http_clone_url -%></code>
22 <code>git clone <%= @repository.http_clone_url -%></code><br />
23 <small>(note that cloning over HTTP is slightly slower, but useful
24 if you're behind a firewall)</small>
2325 </div>
2426 </li>
2527 <% if logged_in? && current_user.can_write_to?(@repository) -%>
2929 <strong>Push url:</strong> <code><%=h @repository.push_url -%></code>
3030 <small><%= link_to_function "More info…", "$('detailed_push_info').toggle()" -%></small>
3131 <div id="detailed_push_info" class="info_hint" style="display:none">
32You can run "<code>git push git@gitorious.org:tumbline/mainline.git</code>", or
33you can setup a remote by doing the following:
32 You can run "<code>git push <%= @repository.push_url %></code>", or
33 you can setup a remote by doing the following:
3434<pre>
3535git remote add origin <%= @repository.push_url %>
3636# to push the master branch to the origin remote we added above:
toggle raw diff

app/views/repositories/show.html.erb

 
99
1010 <ul class="tab_menu">
1111 <li class="selected">Recent commits</li>
12 <li><%= link_to "comments (#{@comment_count})", project_repository_comments_path(@project, @repository) -%></li>
12 <li><%= link_to "comments (#{@comment_count})",
13 project_repository_comments_path(@project, @repository) -%></li>
14 <li><%= link_to "merge requests(#{@merge_request_count})",
15 project_repository_merge_requests_path(@project, @repository) -%></li>
1316 </ul>
1417
1518 <h2>Recent commits</h2>
3636<% content_for :sidebar do -%>
3737 <ul class="links">
3838 <% if @repository.ready? -%>
39 <li><%= link_to "Clone this repository", new_project_repository_path(@project, @repository) -%></li>
39 <li><%= link_to "Clone repository", new_project_repository_path(@project, @repository) -%></li>
4040 <% end -%>
4141 <% if @repository.user == current_user -%>
42 <li><%= link_to "Request merge", new_project_repository_merge_request_path(@project, @repository) -%></li>
4243 <li><%= link_to "Add committer",
4344 { :controller => "committers", :action => "new", :project_id => @project,
4445 :repository_id => @repository } -%></li>
toggle raw diff

config/environment.rb

 
4545 # config.active_record.schema_format = :sql
4646
4747 # Activate observers that should always be running
48 config.active_record.observers = [:user_observer, :repository_observer]
48 config.active_record.observers = [
49 :user_observer,
50 :repository_observer,
51 :merge_request_observer
52 ]
4953
5054 # Make Active Record use UTC-base instead of local time
5155 config.active_record.default_timezone = :utc
toggle raw diff

config/routes.rb

 
3838 }, :path_name => "repos") do |repo|
3939 repo.resources :committers, :name_prefix => nil, :collection => {:auto_complete_for_user_login => :post}
4040 repo.resources :comments
41 repo.resources :merge_requests, :member => { :resolve => :put }
4142 repo.commit_comment "comments/commit/:sha", :controller => "comments",
4243 :action => "commit", :conditions => { :method => :get }
4344
toggle raw diff

db/migrate/021_create_merge_requests.rb

 
1class CreateMergeRequests < ActiveRecord::Migration
2 def self.up
3 create_table :merge_requests do |t|
4 t.integer :user_id
5 t.integer :source_repository_id
6 t.integer :target_repository_id
7 t.text :proposal
8 t.string :sha_snapshot
9 t.integer :status, :default => 0
10 t.timestamps
11 end
12 add_index :merge_requests, :user_id
13 add_index :merge_requests, :source_repository_id
14 add_index :merge_requests, :target_repository_id
15 add_index :merge_requests, :status
16 end
17
18 def self.down
19 drop_table :merge_requests
20 end
21end
toggle raw diff

db/schema.rb

 
99#
1010# It's strongly recommended to check this file into your version control system.
1111
12ActiveRecord::Schema.define(:version => 20) do
12ActiveRecord::Schema.define(:version => 21) do
1313
1414 create_table "comments", :force => true do |t|
1515 t.integer "user_id", :null => false
3737 add_index "committerships", ["repository_id"], :name => "index_permissions_on_repository_id"
3838 add_index "committerships", ["user_id"], :name => "index_permissions_on_user_id"
3939
40 create_table "merge_requests", :force => true do |t|
41 t.integer "user_id"
42 t.integer "source_repository_id"
43 t.integer "target_repository_id"
44 t.text "proposal"
45 t.string "sha_snapshot"
46 t.integer "status", :default => 0
47 t.datetime "created_at"
48 t.datetime "updated_at"
49 end
50
51 add_index "merge_requests", ["user_id"], :name => "index_merge_requests_on_user_id"
52 add_index "merge_requests", ["source_repository_id"], :name => "index_merge_requests_on_source_repository_id"
53 add_index "merge_requests", ["target_repository_id"], :name => "index_merge_requests_on_target_repository_id"
54 add_index "merge_requests", ["status"], :name => "index_merge_requests_on_status"
55
4056 create_table "projects", :force => true do |t|
4157 t.string "title"
4258 t.text "description"
toggle raw diff

public/404.html

 
55
66<head>
77 <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
8 <title>We're sorry, but something went wrong (500)</title>
8 <title>Page not found (404)</title>
99 <link href="/stylesheets/base.css?1199397346" media="screen" rel="stylesheet" type="text/css" />
1010 <style type="text/css">; }
1111 div.dialog {
1818 }
1919 </style>
2020</head>
21
2221<body>
22 <div id="header">
23 <h1 id="logo">
24 <a href="/"><img alt="Logo-white" src="/images/logo-white.png" /></a>
25 </h1>
26 <ul id="menu">