Commit 35d0de8f367e949c3bab50506916ca87eeb5d5ab

Authored by Steven Verbeek
2 parents 2a7cd2f1 cadf12c6

merging upstream changes

Showing 49 changed files with 511 additions and 168 deletions   Show diff stats
app/assets/javascripts/application.js
@@ -11,6 +11,7 @@ @@ -11,6 +11,7 @@
11 //= require jquery.tagify 11 //= require jquery.tagify
12 //= require jquery.cookie 12 //= require jquery.cookie
13 //= require jquery.endless-scroll 13 //= require jquery.endless-scroll
  14 +//= require jquery.highlight
14 //= require bootstrap-modal 15 //= require bootstrap-modal
15 //= require modernizr 16 //= require modernizr
16 //= require chosen 17 //= require chosen
app/assets/javascripts/merge_requests.js
@@ -11,7 +11,7 @@ var MergeRequest = { @@ -11,7 +11,7 @@ var MergeRequest = {
11 11
12 $(".tabs a.merge-notes-tab").live("click", function(e) { 12 $(".tabs a.merge-notes-tab").live("click", function(e) {
13 $(".merge-request-diffs").hide(); 13 $(".merge-request-diffs").hide();
14 - $(".merge-request-notes").show(); 14 + $(".merge_request_notes").show();
15 e.preventDefault(); 15 e.preventDefault();
16 }); 16 });
17 17
@@ -19,7 +19,7 @@ var MergeRequest = { @@ -19,7 +19,7 @@ var MergeRequest = {
19 if(!MergeRequest.diffs_loaded) { 19 if(!MergeRequest.diffs_loaded) {
20 MergeRequest.loadDiff(); 20 MergeRequest.loadDiff();
21 } 21 }
22 - $(".merge-request-notes").hide(); 22 + $(".merge_request_notes").hide();
23 $(".merge-request-diffs").show(); 23 $(".merge-request-diffs").show();
24 e.preventDefault(); 24 e.preventDefault();
25 }); 25 });
@@ -33,7 +33,7 @@ var MergeRequest = { @@ -33,7 +33,7 @@ var MergeRequest = {
33 url: $(".merge-diffs-tab").attr("data-url"), 33 url: $(".merge-diffs-tab").attr("data-url"),
34 complete: function(){ 34 complete: function(){
35 MergeRequest.diffs_loaded = true; 35 MergeRequest.diffs_loaded = true;
36 - $(".merge-request-notes").hide(); 36 + $(".merge_request_notes").hide();
37 $(".dashboard-loader").hide()}, 37 $(".dashboard-loader").hide()},
38 dataType: "script"}); 38 dataType: "script"});
39 } 39 }
app/assets/stylesheets/common.scss
@@ -3,7 +3,7 @@ a { @@ -3,7 +3,7 @@ a {
3 color: $link_color; 3 color: $link_color;
4 &:hover { 4 &:hover {
5 text-decoration:none; 5 text-decoration:none;
6 - color: $style_color; 6 + color: $blue_link;
7 } 7 }
8 8
9 &.btn { 9 &.btn {
@@ -11,6 +11,18 @@ a { @@ -11,6 +11,18 @@ a {
11 } 11 }
12 } 12 }
13 13
  14 +.btn {
  15 + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f1f1f1), color-stop(25%, #f1f1f1), to(#e6e6e6));
  16 + background-image: -webkit-linear-gradient(#f1f1f1, #f1f1f1 25%, #e6e6e6);
  17 + background-image: -moz-linear-gradient(top, #f1f1f1, #f1f1f1 25%, #e6e6e6);
  18 + background-image: -ms-linear-gradient(#f1f1f1, #f1f1f1 25%, #e6e6e6);
  19 + background-image: -o-linear-gradient(#f1f1f1, #f1f1f1 25%, #e6e6e6);
  20 + background-image: linear-gradient(#f1f1f1, #f1f1f1 25%, #e6e6e6);
  21 +
  22 + &:hover {
  23 + }
  24 +}
  25 +
14 a:focus { 26 a:focus {
15 outline: none; 27 outline: none;
16 } 28 }
@@ -29,6 +41,29 @@ a:focus { @@ -29,6 +41,29 @@ a:focus {
29 41
30 .label { 42 .label {
31 background-color: #474D57; 43 background-color: #474D57;
  44 +
  45 + &.pushed {
  46 + background-color: $link_color;
  47 + }
  48 +}
  49 +
  50 +.pretty_label {
  51 + @include round-borders-all(4px);
  52 + padding:2px 4px;
  53 + background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.076, #fefefe), to(#F6F7F8));
  54 + background-image: -webkit-linear-gradient(#fefefe 7.6%, #F6F7F8);
  55 + background-image: -moz-linear-gradient(#fefefe 7.6%, #F6F7F8);
  56 + background-image: -o-linear-gradient(#fefefe 7.6%, #F6F7F8);
  57 + color: #777;
  58 + border: 1px solid #DEDFE1;
  59 +
  60 + &.branch {
  61 + border:none;
  62 + font-size:13px;
  63 + background: #474D57;
  64 + color:#fff;
  65 + font-family: monospace;
  66 + }
32 } 67 }
33 68
34 .tabs > li > a, .pills > li > a { 69 .tabs > li > a, .pills > li > a {
@@ -807,12 +842,19 @@ p.time { @@ -807,12 +842,19 @@ p.time {
807 width:840px; 842 width:840px;
808 margin:auto; 843 margin:auto;
809 844
810 - .wll {  
811 - padding:5px;  
812 - margin-top:5px; 845 + .dash_project_item {
  846 + margin-bottom:10px;
813 border:none; 847 border:none;
814 &:hover { 848 &:hover {
815 background:none; 849 background:none;
  850 +
  851 + h4 {
  852 + color:#2FA0BB;
  853 + .arrow {
  854 + background:#2FA0BB;
  855 + color:#fff;
  856 + }
  857 + }
816 } 858 }
817 859
818 h4 { 860 h4 {
@@ -887,7 +929,7 @@ p.time { @@ -887,7 +929,7 @@ p.time {
887 } 929 }
888 a:last-child h4 { border:none; } 930 a:last-child h4 { border:none; }
889 931
890 - a.active { 932 + a:hover {
891 h4 { 933 h4 {
892 color:#111; 934 color:#111;
893 border-right:4px solid $styled_border_color; 935 border-right:4px solid $styled_border_color;
@@ -974,3 +1016,32 @@ p.time { @@ -974,3 +1016,32 @@ p.time {
974 } 1016 }
975 } 1017 }
976 } 1018 }
  1019 +
  1020 +.highlight_word {
  1021 + background:#EEDC94;
  1022 +}
  1023 +
  1024 +.status_info {
  1025 + font-size:14px;
  1026 + padding:5px 15px;
  1027 + line-height:24px;
  1028 + width:60px;
  1029 + text-align:center;
  1030 + float:left;
  1031 + margin-right:20px;
  1032 +}
  1033 +
  1034 +.merge_request_status_holder {
  1035 + margin-bottom:20px;
  1036 +}
  1037 +
  1038 +.arrow{
  1039 + float: right;
  1040 + background: #E3E5EA;
  1041 + padding: 10px;
  1042 + border-radius: 5px;
  1043 + text-shadow: none;
  1044 + color: #999;
  1045 + line-height: 16px;
  1046 + font-weight:bold;
  1047 +}
app/assets/stylesheets/main.scss
@@ -15,7 +15,7 @@ $app_padding:20px; @@ -15,7 +15,7 @@ $app_padding:20px;
15 $bg_color: #FFF; 15 $bg_color: #FFF;
16 $styled_border_color: #2FA0BB; 16 $styled_border_color: #2FA0BB;
17 $color: "#4BB8D2"; 17 $color: "#4BB8D2";
18 -$blue_link: "#2fa0bb"; 18 +$blue_link: #2fa0bb;
19 19
20 20
21 /** Style colors **/ 21 /** Style colors **/
app/assets/stylesheets/ui_basic.scss
@@ -17,7 +17,7 @@ @@ -17,7 +17,7 @@
17 color: $link_color; 17 color: $link_color;
18 &:hover { 18 &:hover {
19 text-decoration:none; 19 text-decoration:none;
20 - color: $style_color; 20 + color: $blue_link;
21 } 21 }
22 } 22 }
23 23
app/controllers/dashboard_controller.rb
@@ -18,7 +18,7 @@ class DashboardController < ApplicationController @@ -18,7 +18,7 @@ class DashboardController < ApplicationController
18 # Get authored or assigned open merge requests 18 # Get authored or assigned open merge requests
19 def merge_requests 19 def merge_requests
20 @projects = current_user.projects.all 20 @projects = current_user.projects.all
21 - @merge_requests = MergeRequest.where("author_id = :id or assignee_id = :id", :id => current_user.id).opened.order("created_at DESC").limit(40) 21 + @merge_requests = current_user.cared_merge_requests.order("created_at DESC").limit(40)
22 end 22 end
23 23
24 # Get only assigned issues 24 # Get only assigned issues
app/controllers/merge_requests_controller.rb
@@ -41,13 +41,9 @@ class MergeRequestsController < ApplicationController @@ -41,13 +41,9 @@ class MergeRequestsController < ApplicationController
41 41
42 @note = @project.notes.new(:noteable => @merge_request) 42 @note = @project.notes.new(:noteable => @merge_request)
43 43
44 - @commits = @project.repo.  
45 - commits_between(@merge_request.target_branch, @merge_request.source_branch).  
46 - map {|c| Commit.new(c)}.  
47 - sort_by(&:created_at).  
48 - reverse  
49 -  
50 - render_full_content 44 + # Get commits from repository
  45 + # or from cache if already merged
  46 + @commits = @merge_request.commits
51 47
52 respond_to do |format| 48 respond_to do |format|
53 format.html 49 format.html
@@ -76,6 +72,7 @@ class MergeRequestsController < ApplicationController @@ -76,6 +72,7 @@ class MergeRequestsController < ApplicationController
76 72
77 respond_to do |format| 73 respond_to do |format|
78 if @merge_request.save 74 if @merge_request.save
  75 + @merge_request.reload_code
79 format.html { redirect_to [@project, @merge_request], notice: 'Merge request was successfully created.' } 76 format.html { redirect_to [@project, @merge_request], notice: 'Merge request was successfully created.' }
80 format.json { render json: @merge_request, status: :created, location: @merge_request } 77 format.json { render json: @merge_request, status: :created, location: @merge_request }
81 else 78 else
@@ -88,6 +85,7 @@ class MergeRequestsController < ApplicationController @@ -88,6 +85,7 @@ class MergeRequestsController < ApplicationController
88 def update 85 def update
89 respond_to do |format| 86 respond_to do |format|
90 if @merge_request.update_attributes(params[:merge_request].merge(:author_id_of_changes => current_user.id)) 87 if @merge_request.update_attributes(params[:merge_request].merge(:author_id_of_changes => current_user.id))
  88 + @merge_request.reload_code
91 format.html { redirect_to [@project, @merge_request], notice: 'Merge request was successfully updated.' } 89 format.html { redirect_to [@project, @merge_request], notice: 'Merge request was successfully updated.' }
92 format.json { head :ok } 90 format.json { head :ok }
93 else 91 else
app/controllers/projects_controller.rb
@@ -13,6 +13,7 @@ class ProjectsController < ApplicationController @@ -13,6 +13,7 @@ class ProjectsController < ApplicationController
13 def index 13 def index
14 @projects = current_user.projects 14 @projects = current_user.projects
15 @projects = @projects.select(&:last_activity_date).sort_by(&:last_activity_date).reverse 15 @projects = @projects.select(&:last_activity_date).sort_by(&:last_activity_date).reverse
  16 + @events = Event.where(:project_id => @projects.map(&:id)).recent.limit(40)
16 end 17 end
17 18
18 def new 19 def new
@@ -78,7 +79,6 @@ class ProjectsController < ApplicationController @@ -78,7 +79,6 @@ class ProjectsController < ApplicationController
78 render "projects/empty" 79 render "projects/empty"
79 end 80 end
80 end 81 end
81 - format.js  
82 end 82 end
83 end 83 end
84 84
app/controllers/search_controller.rb 0 → 100644
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +class SearchController < ApplicationController
  2 + def show
  3 + query = params[:search]
  4 + if query.blank?
  5 + @projects = []
  6 + @merge_requests = []
  7 + else
  8 + @projects = Project.search(query).limit(10)
  9 + @merge_requests = MergeRequest.search(query).limit(10)
  10 + end
  11 + end
  12 +end
app/models/event.rb
@@ -7,6 +7,7 @@ class Event &lt; ActiveRecord::Base @@ -7,6 +7,7 @@ class Event &lt; ActiveRecord::Base
7 Reopened = 4 7 Reopened = 4
8 Pushed = 5 8 Pushed = 5
9 Commented = 6 9 Commented = 6
  10 + Merged = 7
10 11
11 belongs_to :project 12 belongs_to :project
12 belongs_to :target, :polymorphic => true 13 belongs_to :target, :polymorphic => true
app/models/merge_request.rb
  1 +require File.join(Rails.root, "app/models/commit")
  2 +
1 class MergeRequest < ActiveRecord::Base 3 class MergeRequest < ActiveRecord::Base
2 belongs_to :project 4 belongs_to :project
3 belongs_to :author, :class_name => "User" 5 belongs_to :author, :class_name => "User"
4 belongs_to :assignee, :class_name => "User" 6 belongs_to :assignee, :class_name => "User"
5 has_many :notes, :as => :noteable, :dependent => :destroy 7 has_many :notes, :as => :noteable, :dependent => :destroy
6 8
  9 + serialize :st_commits
  10 + serialize :st_diffs
  11 +
7 attr_protected :author, :author_id, :project, :project_id 12 attr_protected :author, :author_id, :project, :project_id
8 attr_accessor :author_id_of_changes 13 attr_accessor :author_id_of_changes
9 14
@@ -32,6 +37,13 @@ class MergeRequest &lt; ActiveRecord::Base @@ -32,6 +37,13 @@ class MergeRequest &lt; ActiveRecord::Base
32 scope :closed, where(:closed => true) 37 scope :closed, where(:closed => true)
33 scope :assigned, lambda { |u| where(:assignee_id => u.id)} 38 scope :assigned, lambda { |u| where(:assignee_id => u.id)}
34 39
  40 + def self.search query
  41 + where("title like :query", :query => "%#{query}%")
  42 + end
  43 +
  44 + def self.find_all_by_branch(branch_name)
  45 + where("source_branch like :branch or target_branch like :branch", :branch => branch_name)
  46 + end
35 47
36 def validate_branches 48 def validate_branches
37 if target_branch == source_branch 49 if target_branch == source_branch
@@ -39,23 +51,99 @@ class MergeRequest &lt; ActiveRecord::Base @@ -39,23 +51,99 @@ class MergeRequest &lt; ActiveRecord::Base
39 end 51 end
40 end 52 end
41 53
  54 + def reload_code
  55 + self.reloaded_commits
  56 + self.reloaded_diffs
  57 + end
  58 +
42 def new? 59 def new?
43 today? && created_at == updated_at 60 today? && created_at == updated_at
44 end 61 end
45 62
46 def diffs 63 def diffs
  64 + st_diffs || []
  65 + end
  66 +
  67 + def reloaded_diffs
  68 + if open? && unmerged_diffs.any?
  69 + self.st_diffs = unmerged_diffs
  70 + save
  71 + end
  72 + diffs
  73 + end
  74 +
  75 + def unmerged_diffs
47 commits = project.repo.commits_between(target_branch, source_branch).map {|c| Commit.new(c)} 76 commits = project.repo.commits_between(target_branch, source_branch).map {|c| Commit.new(c)}
48 diffs = project.repo.diff(commits.first.prev_commit.id, commits.last.id) rescue [] 77 diffs = project.repo.diff(commits.first.prev_commit.id, commits.last.id) rescue []
49 end 78 end
50 79
51 def last_commit 80 def last_commit
52 - project.commit(source_branch) 81 + commits.first
  82 + end
  83 +
  84 + def merged?
  85 + merged && merge_event
  86 + end
  87 +
  88 + def merge_event
  89 + self.project.events.where(:target_id => self.id, :target_type => "MergeRequest", :action => Event::Merged).last
  90 + end
  91 +
  92 + def closed_event
  93 + self.project.events.where(:target_id => self.id, :target_type => "MergeRequest", :action => Event::Closed).last
53 end 94 end
54 95
  96 +
55 # Return the number of +1 comments (upvotes) 97 # Return the number of +1 comments (upvotes)
56 def upvotes 98 def upvotes
57 notes.select(&:upvote?).size 99 notes.select(&:upvote?).size
58 end 100 end
  101 +
  102 + def commits
  103 + st_commits || []
  104 + end
  105 +
  106 + def probably_merged?
  107 + unmerged_commits.empty? &&
  108 + commits.any? && open?
  109 + end
  110 +
  111 + def open?
  112 + !closed
  113 + end
  114 +
  115 + def mark_as_merged!
  116 + self.merged = true
  117 + self.closed = true
  118 + save
  119 + end
  120 +
  121 + def reloaded_commits
  122 + if open? && unmerged_commits.any?
  123 + self.st_commits = unmerged_commits
  124 + save
  125 + end
  126 + commits
  127 + end
  128 +
  129 + def unmerged_commits
  130 + self.project.repo.
  131 + commits_between(self.target_branch, self.source_branch).
  132 + map {|c| Commit.new(c)}.
  133 + sort_by(&:created_at).
  134 + reverse
  135 + end
  136 +
  137 + def merge!(user_id)
  138 + self.mark_as_merged!
  139 + Event.create(
  140 + :project => self.project,
  141 + :action => Event::Merged,
  142 + :target_id => self.id,
  143 + :target_type => "MergeRequest",
  144 + :author_id => user_id
  145 + )
  146 + end
59 end 147 end
60 # == Schema Information 148 # == Schema Information
61 # 149 #
app/models/project.rb
@@ -54,6 +54,10 @@ class Project &lt; ActiveRecord::Base @@ -54,6 +54,10 @@ class Project &lt; ActiveRecord::Base
54 UsersProject.access_roles 54 UsersProject.access_roles
55 end 55 end
56 56
  57 + def self.search query
  58 + where("name like :query or code like :query or path like :query", :query => "%#{query}%")
  59 + end
  60 +
57 def to_param 61 def to_param
58 code 62 code
59 end 63 end
@@ -73,6 +77,24 @@ class Project &lt; ActiveRecord::Base @@ -73,6 +77,24 @@ class Project &lt; ActiveRecord::Base
73 ) 77 )
74 end 78 end
75 79
  80 + def update_merge_requests(oldrev, newrev, ref, author_key_id)
  81 + return true unless ref =~ /heads/
  82 + branch_name = ref.gsub("refs/heads/", "")
  83 + user = Key.find_by_identifier(author_key_id).user
  84 + c_ids = self.commits_between(oldrev, newrev).map(&:id)
  85 +
  86 + # Update code for merge requests
  87 + mrs = self.merge_requests.opened.find_all_by_branch(branch_name).all
  88 + mrs.each { |merge_request| merge_request.reload_code }
  89 +
  90 + # Close merge requests
  91 + mrs = self.merge_requests.opened.where(:target_branch => branch_name).all
  92 + mrs = mrs.select(&:last_commit).select { |mr| c_ids.include?(mr.last_commit.id) }
  93 + mrs.each { |merge_request| merge_request.merge!(user.id) }
  94 +
  95 + true
  96 + end
  97 +
76 def execute_web_hooks(oldrev, newrev, ref, author_key_id) 98 def execute_web_hooks(oldrev, newrev, ref, author_key_id)
77 ref_parts = ref.split('/') 99 ref_parts = ref.split('/')
78 100
app/models/user.rb
@@ -86,6 +86,10 @@ class User &lt; ActiveRecord::Base @@ -86,6 +86,10 @@ class User &lt; ActiveRecord::Base
86 ) 86 )
87 end 87 end
88 end 88 end
  89 +
  90 + def cared_merge_requests
  91 + MergeRequest.where("author_id = :id or assignee_id = :id", :id => self.id).opened
  92 + end
89 end 93 end
90 # == Schema Information 94 # == Schema Information
91 # 95 #
app/views/commits/show.html.haml
@@ -12,8 +12,8 @@ @@ -12,8 +12,8 @@
12 = @commit.committer_name 12 = @commit.committer_name
13 %small= @commit.committed_date.stamp("Aug 21, 2011 9:23pm") 13 %small= @commit.committed_date.stamp("Aug 21, 2011 9:23pm")
14 14
15 -%hr  
16 -%pre.commit_message 15 +%br
  16 +%pre.commit_message.prettyprint
17 = commit_msg_with_link_to_issues(@project, @commit.safe_message) 17 = commit_msg_with_link_to_issues(@project, @commit.safe_message)
18 .clear 18 .clear
19 %br 19 %br
app/views/dashboard/_events_feed.html.haml
@@ -1,2 +0,0 @@ @@ -1,2 +0,0 @@
1 -= render @events  
2 -  
app/views/dashboard/_issues_feed.html.haml
@@ -3,8 +3,10 @@ @@ -3,8 +3,10 @@
3 = link_to [issue.project, issue] do 3 = link_to [issue.project, issue] do
4 %p 4 %p
5 %strong 5 %strong
6 - %span.label= issue.project.name 6 + %span.pretty_label= issue.project.name
7 &ndash; 7 &ndash;
8 Issue # 8 Issue #
9 = issue.id 9 = issue.id
10 = truncate issue.title, :length => 50 10 = truncate issue.title, :length => 50
  11 + %span.right.cgray
  12 + = issue.updated_at.stamp("Aug 21, 2011")
app/views/dashboard/_merge_requests_feed.html.haml
@@ -3,8 +3,9 @@ @@ -3,8 +3,9 @@
3 = link_to [merge_request.project, merge_request] do 3 = link_to [merge_request.project, merge_request] do
4 %p 4 %p
5 %strong 5 %strong
6 - %span.label= merge_request.project.name 6 + %span.pretty_label= merge_request.project.name
7 &ndash; 7 &ndash;
8 - Merge Request #  
9 - = merge_request.id 8 + Merge Request ##{merge_request.id}
10 = truncate merge_request.title, :length => 50 9 = truncate merge_request.title, :length => 50
  10 + %span.right.cgray
  11 + = merge_request.updated_at.stamp("Aug 21, 2011")
app/views/dashboard/_projects_feed.html.haml
1 -- @active_projects.first(5).each do |project|  
2 - .wll 1 +- projects.first(5).each do |project|
  2 + %div.dash_project_item
3 = link_to project do 3 = link_to project do
4 %h4 4 %h4
5 %span.ico.project 5 %span.ico.project
@@ -7,3 +7,5 @@ @@ -7,3 +7,5 @@
7 %small 7 %small
8 last activity at 8 last activity at
9 = project.last_activity_date.stamp("Aug 25, 2011") 9 = project.last_activity_date.stamp("Aug 25, 2011")
  10 + %span.right.arrow
  11 + &rarr;
app/views/dashboard/index.html.haml
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 .row 20 .row
21 .dashboard_block 21 .dashboard_block
22 .row 22 .row
23 - .span10= render "dashboard/projects_feed" 23 + .span10= render "dashboard/projects_feed", :projects => @active_projects
24 .span4.right 24 .span4.right
25 - if current_user.can_create_project? 25 - if current_user.can_create_project?
26 .alert-message.block-message.warning 26 .alert-message.block-message.warning
@@ -65,4 +65,4 @@ @@ -65,4 +65,4 @@
65 65
66 %hr 66 %hr
67 .row 67 .row
68 - .dashboard_block= render "dashboard/events_feed" 68 + .dashboard_block= render @events
app/views/events/_event_changed_issue.html.haml
1 = image_tag gravatar_icon(event.author_email), :class => "avatar" 1 = image_tag gravatar_icon(event.author_email), :class => "avatar"
2 %strong #{event.author_name} 2 %strong #{event.author_name}
3 -- if event.closed?  
4 - closed  
5 -- else  
6 - reopened  
7 -issue 3 +%span.label.important
  4 + - if event.closed?
  5 + closed
  6 + - else
  7 + reopened
  8 +&nbsp;issue
8 = link_to project_issue_path(event.project, event.issue) do 9 = link_to project_issue_path(event.project, event.issue) do
9 %strong= truncate event.issue_title 10 %strong= truncate event.issue_title
10 at 11 at
app/views/events/_event_changed_merge_request.html.haml
1 = image_tag gravatar_icon(event.author_email), :class => "avatar" 1 = image_tag gravatar_icon(event.author_email), :class => "avatar"
2 %strong #{event.author_name} 2 %strong #{event.author_name}
3 -- if event.closed?  
4 - closed  
5 -- else  
6 - reopened  
7 -merge request 3 +%span.label.important
  4 + - if event.closed?
  5 + closed
  6 + - else
  7 + reopened
  8 +&nbsp;merge request
8 = link_to project_merge_request_path(event.project, event.merge_request) do 9 = link_to project_merge_request_path(event.project, event.merge_request) do
9 %strong= truncate event.merge_request_title 10 %strong= truncate event.merge_request_title
10 at 11 at
@@ -12,7 +13,6 @@ at @@ -12,7 +13,6 @@ at
12 %span.cgray 13 %span.cgray
13 = time_ago_in_words(event.created_at) 14 = time_ago_in_words(event.created_at)
14 ago. 15 ago.
15 -%br  
16 %span.label= event.merge_request.source_branch 16 %span.label= event.merge_request.source_branch
17 &rarr; 17 &rarr;
18 %span.label= event.merge_request.target_branch 18 %span.label= event.merge_request.target_branch
app/views/events/_event_new_issue.html.haml
1 = image_tag gravatar_icon(event.author_email), :class => "avatar" 1 = image_tag gravatar_icon(event.author_email), :class => "avatar"
2 %strong #{event.author_name} 2 %strong #{event.author_name}
3 -created new issue 3 +%span.label.success created
  4 +&nbsp;new issue
4 = link_to project_issue_path(event.project, event.issue) do 5 = link_to project_issue_path(event.project, event.issue) do
5 %strong= truncate event.issue_title 6 %strong= truncate event.issue_title
6 at 7 at
app/views/events/_event_new_merge_request.html.haml
1 = image_tag gravatar_icon(event.author_email), :class => "avatar" 1 = image_tag gravatar_icon(event.author_email), :class => "avatar"
2 %strong #{event.author_name} 2 %strong #{event.author_name}
3 -requested merge 3 +%span.label.success requested
  4 +&nbsp;merge
4 = link_to project_merge_request_path(event.project, event.merge_request) do 5 = link_to project_merge_request_path(event.project, event.merge_request) do
5 %strong= truncate event.merge_request_title 6 %strong= truncate event.merge_request_title
6 at 7 at
@@ -8,7 +9,6 @@ at @@ -8,7 +9,6 @@ at
8 %span.cgray 9 %span.cgray
9 = time_ago_in_words(event.created_at) 10 = time_ago_in_words(event.created_at)
10 ago. 11 ago.
11 -%br  
12 %span.label= event.merge_request.source_branch 12 %span.label= event.merge_request.source_branch
13 &rarr; 13 &rarr;
14 %span.label= event.merge_request.target_branch 14 %span.label= event.merge_request.target_branch
app/views/events/_event_push.html.haml
1 - if event.new_branch? || event.new_tag? 1 - if event.new_branch? || event.new_tag?
2 = image_tag gravatar_icon(event.author_email), :class => "avatar" 2 = image_tag gravatar_icon(event.author_email), :class => "avatar"
3 %strong #{event.author_name} 3 %strong #{event.author_name}
4 - pushed new 4 + %span.label.pushed pushed
  5 + &nbsp;new
5 - if event.new_tag? 6 - if event.new_tag?
6 tag 7 tag
7 = link_to project_commits_path(event.project, :ref => event.tag_name) do 8 = link_to project_commits_path(event.project, :ref => event.tag_name) do
@@ -18,7 +19,8 @@ @@ -18,7 +19,8 @@
18 - else 19 - else
19 = image_tag gravatar_icon(event.author_email), :class => "avatar" 20 = image_tag gravatar_icon(event.author_email), :class => "avatar"
20 %strong #{event.author_name} 21 %strong #{event.author_name}
21 - pushed to 22 + %span.label.pushed pushed
  23 + &nbsp;to
22 = link_to project_commits_path(event.project, :ref => event.branch_name) do 24 = link_to project_commits_path(event.project, :ref => event.branch_name) do
23 %strong= event.branch_name 25 %strong= event.branch_name
24 at 26 at
@@ -30,10 +32,10 @@ @@ -30,10 +32,10 @@
30 = link_to compare_project_commits_path(event.project, :from => event.commits.first.prev_commit_id, :to => event.commits.last.id) do 32 = link_to compare_project_commits_path(event.project, :from => event.commits.first.prev_commit_id, :to => event.commits.last.id) do
31 Compare #{event.commits.first.commit.id[0..8]}...#{event.commits.last.id[0..8]} 33 Compare #{event.commits.first.commit.id[0..8]}...#{event.commits.last.id[0..8]}
32 - @project = event.project 34 - @project = event.project
33 - %ul.unstyled  
34 - - if event.commits.size > 4  
35 - = render event.commits[0..2]  
36 - %li ... and #{event.commits.size - 3} more commits 35 + %ul.unstyled.event_commits
  36 + - if event.commits.size > 3
  37 + = render event.commits[0...2]
  38 + %li ... and #{event.commits.size - 2} more commits
37 - else 39 - else
38 = render event.commits 40 = render event.commits
39 41
app/views/layouts/_app_menu.html.haml
1 %nav.main_menu 1 %nav.main_menu
2 = render "layouts/const_menu_links" 2 = render "layouts/const_menu_links"
3 = link_to "Projects", projects_path, :class => "#{"current" if current_page?(projects_path)}" 3 = link_to "Projects", projects_path, :class => "#{"current" if current_page?(projects_path)}"
4 - = link_to "Issues", dashboard_issues_path, :class => "#{"current" if current_page?(dashboard_issues_path)}", :id => "issues_slide"  
5 - = link_to "Requests", dashboard_merge_requests_path, :class => "#{"current" if current_page?(dashboard_merge_requests_path)}", :id => "merge_requests_slide" 4 + = link_to dashboard_issues_path, :class => "#{"current" if current_page?(dashboard_issues_path)}", :id => "issues_slide" do
  5 + Issues
  6 + %span.count= current_user.assigned_issues.opened.count
  7 + = link_to dashboard_merge_requests_path, :class => "#{"current" if current_page?(dashboard_merge_requests_path)}", :id => "merge_requests_slide" do
  8 + Requests
  9 + %span.count= current_user.cared_merge_requests.count
  10 + = link_to "Search", search_path, :class => "#{"current" if current_page?(search_path)}"
6 = link_to "Help", help_path, :class => "#{"current" if controller.controller_name == "help"}" 11 = link_to "Help", help_path, :class => "#{"current" if controller.controller_name == "help"}"
app/views/layouts/_head_panel.html.haml
@@ -7,7 +7,9 @@ @@ -7,7 +7,9 @@
7 %h1 7 %h1
8 GITLAB 8 GITLAB
9 %h1.project_name= title 9 %h1.project_name= title
10 - .search= text_field_tag "search", nil, :placeholder => "Search", :class => "search-input" 10 + .search
  11 + = form_tag search_path, :method => :get do |f|
  12 + = text_field_tag "search", nil, :placeholder => "Search", :class => "search-input"
11 - if current_user.is_admin? 13 - if current_user.is_admin?
12 = link_to admin_projects_path, :class => "admin_link", :title => "Admin area" do 14 = link_to admin_projects_path, :class => "admin_link", :title => "Admin area" do
13 = image_tag "admin.PNG", :width => 16 15 = image_tag "admin.PNG", :width => 16
app/views/merge_requests/_commits.html.haml
@@ -2,7 +2,9 @@ @@ -2,7 +2,9 @@
2 .ui-box 2 .ui-box
3 %h5 Commits 3 %h5 Commits
4 .merge-request-commits 4 .merge-request-commits
5 - %ul.unstyled= render @commits 5 + %ul.unstyled
  6 + - @commits.each do |commit|
  7 + = render "commits/commit", :commit => commit
6 8
7 - else 9 - else
8 %h5 10 %h5
app/views/merge_requests/_how_to_merge.html.haml
@@ -15,7 +15,7 @@ @@ -15,7 +15,7 @@
15 :javascript 15 :javascript
16 $(function(){ 16 $(function(){
17 var modal = $('#modal_merge_info').modal({modal: true}); 17 var modal = $('#modal_merge_info').modal({modal: true});
18 - $('.info_link').bind("click", function(){ 18 + $('.how_to_merge_link').bind("click", function(){
19 modal.show(); 19 modal.show();
20 }); 20 });
21 $('.modal-header .close').bind("click", function(){ 21 $('.modal-header .close').bind("click", function(){
app/views/merge_requests/_merge_request.html.haml
@@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
6 = time_ago_in_words(merge_request.created_at) 6 = time_ago_in_words(merge_request.created_at)
7 ago 7 ago
8 - if merge_request.notes.any? 8 - if merge_request.notes.any?
9 - %span.label= pluralize merge_request.notes.count, 'note' 9 + %span.pretty_label= pluralize merge_request.notes.count, 'note'
10 - if merge_request.upvotes > 0 10 - if merge_request.upvotes > 0
11 %span.label.success= "+#{merge_request.upvotes}" 11 %span.label.success= "+#{merge_request.upvotes}"
12 .right 12 .right
app/views/merge_requests/show.html.haml
1 %h3 1 %h3
2 = "Merge Request ##{@merge_request.id}:" 2 = "Merge Request ##{@merge_request.id}:"
3 &nbsp; 3 &nbsp;
4 - %span.label= @merge_request.source_branch 4 + %span.pretty_label.branch= @merge_request.source_branch
5 &rarr; 5 &rarr;
6 - %span.label= @merge_request.target_branch 6 + %span.pretty_label.branch= @merge_request.target_branch
7 7
8 %small 8 %small
9 created at 9 created at
@@ -11,12 +11,10 @@ @@ -11,12 +11,10 @@
11 11
12 %span.right 12 %span.right
13 - if can?(current_user, :modify_merge_request, @merge_request) 13 - if can?(current_user, :modify_merge_request, @merge_request)
14 - - if @merge_request.closed  
15 - = link_to 'Reopen', project_merge_request_path(@project, @merge_request, :merge_request => {:closed => false }, :status_only => true), :method => :put, :class => "btn"  
16 - - else 14 + - if @merge_request.open?
17 = link_to 'Close', project_merge_request_path(@project, @merge_request, :merge_request => {:closed => true }, :status_only => true), :method => :put, :class => "btn", :title => "Close merge request" 15 = link_to 'Close', project_merge_request_path(@project, @merge_request, :merge_request => {:closed => true }, :status_only => true), :method => :put, :class => "btn", :title => "Close merge request"
18 - = link_to edit_project_merge_request_path(@project, @merge_request), :class => "btn" do  
19 - Edit 16 + = link_to edit_project_merge_request_path(@project, @merge_request), :class => "btn" do
  17 + Edit
20 18
21 %br 19 %br
22 - if @merge_request.upvotes > 0 20 - if @merge_request.upvotes > 0
@@ -28,17 +26,27 @@ @@ -28,17 +26,27 @@
28 26
29 27
30 %hr 28 %hr
31 -- if @merge_request.closed  
32 - .alert-message.error Closed  
33 -- else  
34 - .alert-message.success  
35 - = link_to "#", :class => "info_link", :title => "How To Merge" do  
36 - = image_tag "Info-UI.PNG"  
37 - Open 29 +.merge_request_status_holder
  30 + - if @merge_request.closed
  31 + %h5
  32 + .alert-message.error.status_info Closed
  33 + - if @merge_request.merged?
  34 + %span
  35 + Merged by #{@merge_request.merge_event.author_name}
  36 + %small #{time_ago_in_words(@merge_request.merge_event.created_at)} ago.
  37 + - elsif @merge_request.closed_event
  38 + %span
  39 + Closed by #{@merge_request.closed_event.author_name}
  40 + %small #{time_ago_in_words(@merge_request.closed_event.created_at)} ago.
  41 + %br
  42 + - else
  43 + %h5
  44 + .alert-message.success.status_info Open
  45 + = link_to "How to merge", "#", :class => "vlink how_to_merge_link", :title => "How To Merge"
38 46
39 = render "merge_requests/how_to_merge" 47 = render "merge_requests/how_to_merge"
40 48
41 -%div.well 49 +%div.well.prettyprint
42 %div 50 %div
43 %cite.cgray Created by 51 %cite.cgray Created by
44 = image_tag gravatar_icon(@merge_request.author_email), :width => 16, :class => "lil_av" 52 = image_tag gravatar_icon(@merge_request.author_email), :width => 16, :class => "lil_av"
app/views/profile/password.html.haml
1 -%h3 Password  
2 -%hr  
3 -= form_for @user, :url => profile_password_path, :method => :put do |f|  
4 - .data  
5 - .alert-message.block-message.warning  
6 - %p After successfull password update you will be redirected to login page where you should login with new password  
7 - -if @user.errors.any?  
8 - .alert-message.block-message.error  
9 - %ul  
10 - - @user.errors.full_messages.each do |msg|  
11 - %li= msg 1 +.row
  2 + .span8
  3 + %h3 Password
  4 + %hr
  5 + = form_for @user, :url => profile_password_path, :method => :put do |f|
  6 + .data
  7 + .alert-message.block-message.warning
  8 + %p After successfull password update you will be redirected to login page where you should login with new password
  9 + -if @user.errors.any?
  10 + .alert-message.block-message.error
  11 + %ul
  12 + - @user.errors.full_messages.each do |msg|
  13 + %li= msg
  14 +
  15 + .clearfix
  16 + = f.label :password
  17 + .input= f.password_field :password
  18 + .clearfix
  19 + = f.label :password_confirmation
  20 + .input= f.password_field :password_confirmation
  21 + .actions
  22 + = f.submit 'Save', :class => "btn"
12 23
13 - .clearfix  
14 - = f.label :password  
15 - .input= f.password_field :password  
16 - .clearfix  
17 - = f.label :password_confirmation  
18 - .input= f.password_field :password_confirmation  
19 - .actions  
20 - = f.submit 'Save', :class => "btn"  
21 -  
22 -%h3  
23 - Private token  
24 - %span.cred.right  
25 - keep it in secret!  
26 -%hr  
27 -= form_for @user, :url => profile_reset_private_token_path, :method => :put do |f|  
28 - .data  
29 - %p Private token used to access application resources without authentication.  
30 - %p For example its required to access commits feed. 24 + .span7.right
  25 + %h3
  26 + Private token
  27 + %span.cred.right
  28 + keep it in secret!
31 %hr 29 %hr
32 - %p.cgray  
33 - - if current_user.private_token  
34 - = text_field_tag "token", current_user.private_token  
35 - - else  
36 - You don`t have one yet. Click generate to fix it.  
37 - .actions  
38 - - if current_user.private_token  
39 - = f.submit 'Reset', :confirm => "Are you sure?", :class => "btn"  
40 - - else  
41 - = f.submit 'Generate', :class => "btn" 30 + = form_for @user, :url => profile_reset_private_token_path, :method => :put do |f|
  31 + .data
  32 + .alert-message.block-message.warning
  33 + %p Private token used to access application resources without authentication.
  34 + %hr
  35 + %p * required for rss feed
  36 + %p.cgray
  37 + - if current_user.private_token
  38 + = text_field_tag "token", current_user.private_token
  39 + - else
  40 + You don`t have one yet. Click generate to fix it.
  41 + .actions
  42 + - if current_user.private_token
  43 + = f.submit 'Reset', :confirm => "Are you sure?", :class => "btn"
  44 + - else
  45 + = f.submit 'Generate', :class => "btn"
42 46
app/views/projects/_show.html.haml
1 -%h4.title 1 +%h5.title
2 = @project.name 2 = @project.name
3 %br 3 %br
4 %div 4 %div
app/views/projects/empty.html.haml
@@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
6 %li Visit profile &rarr; keys and add public key of every machine you want to use for work with gitlabhq. 6 %li Visit profile &rarr; keys and add public key of every machine you want to use for work with gitlabhq.
7 7
8 .alert-message.block-message.error 8 .alert-message.block-message.error
9 - %ul.alert_holder 9 + %ul.unstyled.alert_holder
10 %li You should push repository to proceed. 10 %li You should push repository to proceed.
11 %li After push you will be able to browse code, commits etc. 11 %li After push you will be able to browse code, commits etc.
12 12
app/views/projects/index.html.haml
1 - if @projects.any? 1 - if @projects.any?
2 .row 2 .row
3 - .span4 3 + .span11
  4 + = render @events
  5 + .span5.right
4 %div.leftbar.ui-box 6 %div.leftbar.ui-box
5 %h5 7 %h5
6 Projects 8 Projects
  9 + %small
  10 + (#{@projects.count})
7 - if current_user.can_create_project? 11 - if current_user.can_create_project?
8 %span.right 12 %span.right
9 = link_to new_project_path, :class => "btn very_small info" do 13 = link_to new_project_path, :class => "btn very_small info" do
10 New Project 14 New Project
11 .content_list 15 .content_list
12 - @projects.each do |project| 16 - @projects.each do |project|
13 - = link_to project_path(project), :remote => true, :class => dom_class(project) do 17 + = link_to project_path(project), :class => dom_class(project) do
14 %h4 18 %h4
15 %span.ico.project 19 %span.ico.project
16 - = truncate(project.name, :length => 22)  
17 - .span12.right  
18 - .show_holder.ui-box.padded  
19 - .loading 20 + = truncate(project.name, :length => 25)
  21 + %span.right
  22 + &rarr;
20 23
21 - else 24 - else
22 %h3 Nothing here 25 %h3 Nothing here
@@ -31,20 +34,3 @@ @@ -31,20 +34,3 @@
31 New Project » 34 New Project »
32 - else 35 - else
33 If you will be added to project - it will be displayed here 36 If you will be added to project - it will be displayed here
34 -  
35 -  
36 -:javascript  
37 - $(function(){  
38 - $("a.project").live("ajax:before", function() {  
39 - $(".show_holder").html("<div class='loading'>");  
40 - $('a.project').removeClass("active");  
41 - $(this).addClass("active");  
42 - });  
43 - $('a.project:first-child').trigger("click");  
44 - });  
45 -  
46 -- if @projects.count == @limit  
47 - :javascript  
48 - $(function(){  
49 - Pager.init(#{@limit});  
50 - });  
app/views/projects/show.html.haml
@@ -21,9 +21,13 @@ @@ -21,9 +21,13 @@
21 = text_field_tag :project_clone, @project.url_to_repo, :class => "xlarge one_click_select git_clone_url" 21 = text_field_tag :project_clone, @project.url_to_repo, :class => "xlarge one_click_select git_clone_url"
22 22
23 - if @project.description.present? 23 - if @project.description.present?
24 - = markdown @project.description 24 + .prettyprint= markdown @project.description
25 - unless @events.blank? 25 - unless @events.blank?
26 - %h5.cgray Recent Activity 26 + %br
  27 + %h5.cgray
  28 + %span.ico.activities
  29 + Recent Activity
  30 + %hr
27 .content_list= render @events 31 .content_list= render @events
28 32
29 33
app/views/projects/show.js.haml
@@ -1,7 +0,0 @@ @@ -1,7 +0,0 @@
1 -- if @project.repo_exists? && @project.has_commits?  
2 - :plain  
3 - $(".show_holder").html("#{escape_javascript(render(:partial => 'projects/show'))}");  
4 -- else  
5 - :plain  
6 - $(".show_holder").html("#{escape_javascript(render(:template => 'projects/empty'))}");  
7 -  
app/views/search/_result.html.haml 0 → 100644
No preview for this file type
app/views/search/show.html.haml 0 → 100644
@@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
  1 += form_tag search_path, :method => :get do |f|
  2 + .padded
  3 + = label_tag :search, "Looking for"
  4 + .input
  5 + = text_field_tag :search, params[:search],:placeholder => "issue 143", :class => "xxlarge"
  6 + = submit_tag 'Search', :class => "btn primary"
  7 +- if params[:search].present?
  8 + %br
  9 + %h3 Search results
  10 + %hr
  11 + .search_results
  12 + - if @projects.empty? && @merge_requests.empty?
  13 + %h3
  14 + %small Nothing here
  15 + - else
  16 + - if @projects.any?
  17 + - @projects.each do |project|
  18 + = link_to project do
  19 + %h4
  20 + %span.ico.project
  21 + = project.name
  22 + %small
  23 + last activity at
  24 + = project.last_activity_date.stamp("Aug 25, 2011")
  25 + - if @merge_requests.any?
  26 + - @merge_requests.each do |merge_request|
  27 + = link_to [merge_request.project, merge_request] do
  28 + %h5
  29 + Merge Request #
  30 + = merge_request.id
  31 + &ndash;
  32 + = truncate merge_request.title, :length => 50
  33 + %small
  34 + updated at
  35 + = merge_request.updated_at.stamp("Aug 25, 2011")
  36 + %strong
  37 + %span.label= merge_request.project.name
  38 + :javascript
  39 + $(function() {
  40 + $(".search_results").highlight("#{params[:search]}");
  41 + })
app/workers/post_receive.rb
@@ -8,7 +8,13 @@ class PostReceive @@ -8,7 +8,13 @@ class PostReceive
8 # Ignore push from non-gitlab users 8 # Ignore push from non-gitlab users
9 return false unless Key.find_by_identifier(author_key_id) 9 return false unless Key.find_by_identifier(author_key_id)
10 10
  11 + # Create push event
11 project.observe_push(oldrev, newrev, ref, author_key_id) 12 project.observe_push(oldrev, newrev, ref, author_key_id)
  13 +
  14 + # Close merged MR
  15 + project.update_merge_requests(oldrev, newrev, ref, author_key_id)
  16 +
  17 + # Execute web hooks
12 project.execute_web_hooks(oldrev, newrev, ref, author_key_id) 18 project.execute_web_hooks(oldrev, newrev, ref, author_key_id)
13 end 19 end
14 end 20 end
config/routes.rb
1 Gitlab::Application.routes.draw do 1 Gitlab::Application.routes.draw do
2 - 2 + get 'search' => "search#show"
3 3
4 # Optionally, enable Resque here 4 # Optionally, enable Resque here
5 require 'resque/server' 5 require 'resque/server'
@@ -40,6 +40,7 @@ Gitlab::Application.routes.draw do @@ -40,6 +40,7 @@ Gitlab::Application.routes.draw do
40 get "dashboard", :to => "dashboard#index" 40 get "dashboard", :to => "dashboard#index"
41 get "dashboard/issues", :to => "dashboard#issues" 41 get "dashboard/issues", :to => "dashboard#issues"
42 get "dashboard/merge_requests", :to => "dashboard#merge_requests" 42 get "dashboard/merge_requests", :to => "dashboard#merge_requests"
  43 + get "dashboard/activities", :to => "dashboard#activities"
43 44
44 #get "profile/:id", :to => "profile#show" 45 #get "profile/:id", :to => "profile#show"
45 46
db/migrate/20120315111711_add_commits_diff_store_to_merge_request.rb 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +class AddCommitsDiffStoreToMergeRequest < ActiveRecord::Migration
  2 + def change
  3 + add_column :merge_requests, :st_commits, :text, :null => true
  4 + add_column :merge_requests, :st_diffs, :text, :null => true
  5 + end
  6 +end
db/migrate/20120315132931_add_merged_to_merge_request.rb 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +class AddMergedToMergeRequest < ActiveRecord::Migration
  2 + def change
  3 + add_column :merge_requests, :merged, :boolean, :null => false, :default => false
  4 + end
  5 +end
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 # 11 #
12 # It's strongly recommended to check this file into your version control system. 12 # It's strongly recommended to check this file into your version control system.
13 13
14 -ActiveRecord::Schema.define(:version => 20120307095918) do 14 +ActiveRecord::Schema.define(:version => 20120315132931) do
15 15
16 create_table "events", :force => true do |t| 16 create_table "events", :force => true do |t|
17 t.string "target_type" 17 t.string "target_type"
@@ -61,6 +61,9 @@ ActiveRecord::Schema.define(:version =&gt; 20120307095918) do @@ -61,6 +61,9 @@ ActiveRecord::Schema.define(:version =&gt; 20120307095918) do
61 t.boolean "closed", :default => false, :null => false 61 t.boolean "closed", :default => false, :null => false
62 t.datetime "created_at", :null => false 62 t.datetime "created_at", :null => false
63 t.datetime "updated_at", :null => false 63 t.datetime "updated_at", :null => false
  64 + t.text "st_commits"
  65 + t.text "st_diffs"
  66 + t.boolean "merged", :default => false, :null => false
64 end 67 end
65 68
66 add_index "merge_requests", ["project_id"], :name => "index_merge_requests_on_project_id" 69 add_index "merge_requests", ["project_id"], :name => "index_merge_requests_on_project_id"
doc/installation.md
@@ -209,7 +209,7 @@ Application can be started with next command: @@ -209,7 +209,7 @@ Application can be started with next command:
209 209
210 cd /home/gitlab/gitlab 210 cd /home/gitlab/gitlab
211 sudo -u gitlab cp config/unicorn.rb.orig config/unicorn.rb 211 sudo -u gitlab cp config/unicorn.rb.orig config/unicorn.rb
212 - sudo -u gitlab unicorn_rails -c config/unicorn.rb -E production -D 212 + sudo -u gitlab bundle exec unicorn_rails -c config/unicorn.rb -E production -D
213 213
214 Edit /etc/nginx/nginx.conf. Add next code to **http** section: 214 Edit /etc/nginx/nginx.conf. Add next code to **http** section:
215 215
@@ -256,33 +256,38 @@ Create init script in /etc/init.d/gitlab: @@ -256,33 +256,38 @@ Create init script in /etc/init.d/gitlab:
256 NAME=unicorn 256 NAME=unicorn
257 DESC="Gitlab service" 257 DESC="Gitlab service"
258 PID=/home/gitlab/gitlab/tmp/pids/unicorn.pid 258 PID=/home/gitlab/gitlab/tmp/pids/unicorn.pid
  259 + RESQUE_PID=/home/gitlab/gitlab/tmp/pids/resque_worker.pid
259 260
260 case "$1" in 261 case "$1" in
261 start) 262 start)
262 CD_TO_APP_DIR="cd /home/gitlab/gitlab" 263 CD_TO_APP_DIR="cd /home/gitlab/gitlab"
263 START_DAEMON_PROCESS="bundle exec unicorn_rails $DAEMON_OPTS" 264 START_DAEMON_PROCESS="bundle exec unicorn_rails $DAEMON_OPTS"
  265 + START_RESQUE_PROCESS="./resque.sh"
264 266
265 echo -n "Starting $DESC: " 267 echo -n "Starting $DESC: "
266 if [ `whoami` = root ]; then 268 if [ `whoami` = root ]; then
267 - sudo -u gitlab sh -c "$CD_TO_APP_DIR > /dev/null 2>&1 && $START_DAEMON_PROCESS" 269 + sudo -u gitlab sh -c "$CD_TO_APP_DIR > /dev/null 2>&1 && $START_DAEMON_PROCESS && $START_RESQUE_PROCESS"
268 else 270 else
269 - $CD_TO_APP_DIR > /dev/null 2>&1 && $START_DAEMON_PROCESS 271 + $CD_TO_APP_DIR > /dev/null 2>&1 && $START_DAEMON_PROCESS && $START_RESQUE_PROCESS
270 fi 272 fi
271 echo "$NAME." 273 echo "$NAME."
272 ;; 274 ;;
273 stop) 275 stop)
274 echo -n "Stopping $DESC: " 276 echo -n "Stopping $DESC: "
275 kill -QUIT `cat $PID` 277 kill -QUIT `cat $PID`
  278 + kill -QUIT `cat $RESQUE_PID`
276 echo "$NAME." 279 echo "$NAME."
277 ;; 280 ;;
278 restart) 281 restart)
279 echo -n "Restarting $DESC: " 282 echo -n "Restarting $DESC: "
280 kill -USR2 `cat $PID` 283 kill -USR2 `cat $PID`
  284 + kill -USR2 `cat $RESQUE_PID`
281 echo "$NAME." 285 echo "$NAME."
282 ;; 286 ;;
283 reload) 287 reload)
284 echo -n "Reloading $DESC configuration: " 288 echo -n "Reloading $DESC configuration: "
285 kill -HUP `cat $PID` 289 kill -HUP `cat $PID`
  290 + kill -HUP `cat $RESQUE_PID`
286 echo "$NAME." 291 echo "$NAME."
287 ;; 292 ;;
288 *) 293 *)
1 mkdir tmp/pids 1 mkdir tmp/pids
2 -nohup bundle exec rake environment resque:work QUEUE=* RAILS_ENV=production PIDFILE=tmp/pids/resque_worker_QUEUE.pid & >> log/resque_worker_QUEUE.log 2>&1 2 +nohup bundle exec rake environment resque:work QUEUE=* RAILS_ENV=production PIDFILE=tmp/pids/resque_worker.pid & >> log/resque_worker.log 2>&1
spec/models/project_spec.rb
@@ -160,6 +160,34 @@ describe Project do @@ -160,6 +160,34 @@ describe Project do
160 end 160 end
161 end 161 end
162 end 162 end
  163 +
  164 + describe :update_merge_requests do
  165 + let(:project) { Factory :project }
  166 +
  167 + before do
  168 + @merge_request = Factory :merge_request,
  169 + :project => project,
  170 + :merged => false,
  171 + :closed => false
  172 + @key = Factory :key, :user_id => project.owner.id
  173 + end
  174 +
  175 + it "should close merge request if last commit from source branch was pushed to target branch" do
  176 + @merge_request.reloaded_commits
  177 + @merge_request.last_commit.id.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a"
  178 + project.update_merge_requests("8716fc78f3c65bbf7bcf7b574febd583bc5d2812", "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a", "refs/heads/stable", @key.identifier)
  179 + @merge_request.reload
  180 + @merge_request.merged.should be_true
  181 + @merge_request.closed.should be_true
  182 + end
  183 +
  184 + it "should update merge request commits with new one if pushed to source branch" do
  185 + @merge_request.last_commit.should == nil
  186 + project.update_merge_requests("8716fc78f3c65bbf7bcf7b574febd583bc5d2812", "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a", "refs/heads/master", @key.identifier)
  187 + @merge_request.reload
  188 + @merge_request.last_commit.id.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a"
  189 + end
  190 + end
163 end 191 end
164 # == Schema Information 192 # == Schema Information
165 # 193 #
spec/requests/dashboard_spec.rb
1 require 'spec_helper' 1 require 'spec_helper'
2 -__END__  
3 -# Disabled for now  
4 describe "Dashboard" do 2 describe "Dashboard" do
5 before do 3 before do
6 @project = Factory :project 4 @project = Factory :project
@@ -22,19 +20,7 @@ describe &quot;Dashboard&quot; do @@ -22,19 +20,7 @@ describe &quot;Dashboard&quot; do
22 end 20 end
23 21
24 it "should have projects panel" do 22 it "should have projects panel" do
25 - within ".project-list" do  
26 - page.should have_content(@project.name)  
27 - end 23 + page.should have_content(@project.name)
28 end 24 end
29 -  
30 - # Temporary disabled cause of travis  
31 - # TODO: fix or rewrite  
32 - #it "should have news feed" do  
33 - #within "#news-feed" do  
34 - #page.should have_content("commit")  
35 - #page.should have_content(@project.commit.author.name)  
36 - #page.should have_content(@project.commit.safe_message)  
37 - #end  
38 - #end  
39 end 25 end
40 end 26 end
spec/requests/merge_requests_spec.rb
@@ -42,7 +42,7 @@ describe &quot;MergeRequests&quot; do @@ -42,7 +42,7 @@ describe &quot;MergeRequests&quot; do
42 42
43 it { should have_content(@merge_request.title[0..10]) } 43 it { should have_content(@merge_request.title[0..10]) }
44 it "Show page should inform user that merge request closed" do 44 it "Show page should inform user that merge request closed" do
45 - page.should have_content "Reopen" 45 + page.should have_content "Closed"
46 end 46 end
47 end 47 end
48 end 48 end
vendor/assets/javascripts/jquery.highlight.js 0 → 100644
@@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
  1 +/*
  2 +
  3 +highlight v3
  4 +
  5 +Highlights arbitrary terms.
  6 +
  7 +<http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html>
  8 +
  9 +MIT license.
  10 +
  11 +Johann Burkard
  12 +<http://johannburkard.de>
  13 +<mailto:jb@eaio.com>
  14 +
  15 +*/
  16 +
  17 +jQuery.fn.highlight = function(pat) {
  18 + function innerHighlight(node, pat) {
  19 + var skip = 0;
  20 + if (node.nodeType == 3) {
  21 + var pos = node.data.toUpperCase().indexOf(pat);
  22 + if (pos >= 0) {
  23 + var spannode = document.createElement('span');
  24 + spannode.className = 'highlight_word';
  25 + var middlebit = node.splitText(pos);
  26 + var endbit = middlebit.splitText(pat.length);
  27 + var middleclone = middlebit.cloneNode(true);
  28 + spannode.appendChild(middleclone);
  29 + middlebit.parentNode.replaceChild(spannode, middlebit);
  30 + skip = 1;
  31 + }
  32 + }
  33 + else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
  34 + for (var i = 0; i < node.childNodes.length; ++i) {
  35 + i += innerHighlight(node.childNodes[i], pat);
  36 + }
  37 + }
  38 + return skip;
  39 + }
  40 + return this.each(function() {
  41 + innerHighlight(this, pat.toUpperCase());
  42 + });
  43 +};
  44 +
  45 +jQuery.fn.removeHighlight = function() {
  46 + return this.find("span.highlight").each(function() {
  47 + this.parentNode.firstChild.nodeName;
  48 + with (this.parentNode) {
  49 + replaceChild(this.firstChild, this);
  50 + normalize();
  51 + }
  52 + }).end();
  53 +};