Skip to content
Snippets Groups Projects
Commit 5a3f23f3 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets
Browse files

Persist Merge Request diff. Auto merge request close on push

parent 27e36998
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -41,13 +41,12 @@ class MergeRequestsController < ApplicationController
 
@note = @project.notes.new(:noteable => @merge_request)
 
@commits = @project.repo.
commits_between(@merge_request.target_branch, @merge_request.source_branch).
map {|c| Commit.new(c)}.
sort_by(&:created_at).
reverse
# Get commits from repository
# or from cache if already merged
@commits = @merge_request.commits
 
render_full_content
# Close MR if nothing to merge
#@merge_request.mark_as_merged! if @merge_request.probably_merged?
 
respond_to do |format|
format.html
Loading
Loading
@@ -76,6 +75,8 @@ class MergeRequestsController < ApplicationController
 
respond_to do |format|
if @merge_request.save
@merge_request.reloaded_commits
@merge_request.reloaded_diffs
format.html { redirect_to [@project, @merge_request], notice: 'Merge request was successfully created.' }
format.json { render json: @merge_request, status: :created, location: @merge_request }
else
Loading
Loading
Loading
Loading
@@ -7,6 +7,7 @@ class Event < ActiveRecord::Base
Reopened = 4
Pushed = 5
Commented = 6
Merged = 7
 
belongs_to :project
belongs_to :target, :polymorphic => true
Loading
Loading
require File.join(Rails.root, "app/models/commit")
class MergeRequest < ActiveRecord::Base
belongs_to :project
belongs_to :author, :class_name => "User"
belongs_to :assignee, :class_name => "User"
has_many :notes, :as => :noteable, :dependent => :destroy
 
serialize :st_commits
serialize :st_diffs
attr_protected :author, :author_id, :project, :project_id
attr_accessor :author_id_of_changes
 
Loading
Loading
@@ -32,7 +37,6 @@ class MergeRequest < ActiveRecord::Base
scope :closed, where(:closed => true)
scope :assigned, lambda { |u| where(:assignee_id => u.id)}
 
def validate_branches
if target_branch == source_branch
errors.add :base, "You can not use same branch for source and target branches"
Loading
Loading
@@ -44,18 +48,65 @@ class MergeRequest < ActiveRecord::Base
end
 
def diffs
st_diffs || []
end
def reloaded_diffs
if open? && unmerged_diffs.any?
self.st_diffs = unmerged_diffs
save
end
diffs
end
def unmerged_diffs
commits = project.repo.commits_between(target_branch, source_branch).map {|c| Commit.new(c)}
diffs = project.repo.diff(commits.first.prev_commit.id, commits.last.id) rescue []
end
 
def last_commit
project.commit(source_branch)
commits.first
end
 
# Return the number of +1 comments (upvotes)
def upvotes
notes.select(&:upvote?).size
end
def commits
st_commits || []
end
def probably_merged?
unmerged_commits.empty? &&
commits.any? && open?
end
def open?
!closed
end
def mark_as_merged!
self.merged = true
self.closed = true
save
end
def reloaded_commits
if open? && unmerged_commits.any?
self.st_commits = unmerged_commits
save
end
commits
end
def unmerged_commits
self.project.repo.
commits_between(self.target_branch, self.source_branch).
map {|c| Commit.new(c)}.
sort_by(&:created_at).
reverse
end
end
# == Schema Information
#
Loading
Loading
Loading
Loading
@@ -73,6 +73,40 @@ class Project < ActiveRecord::Base
)
end
 
def update_merge_requests(oldrev, newrev, ref, author_key_id)
return true unless ref =~ /heads/
branch_name = ref.gsub("refs/heads/", "")
key = Key.find_by_identifier(author_key_id)
user = key.user
c_ids = self.commits_between(oldrev, newrev).map(&:id)
# update commits & diffs for existing MR
mrs = self.merge_requests.opened.where(:source_branch => branch_name).all
mrs.each do |merge_request|
merge_request.reloaded_commits
merge_request.reloaded_diffs
end
# Close merge requests
mrs = self.merge_requests.opened.where(:target_branch => branch_name).all
mrs.each do |merge_request|
next unless merge_request.last_commit
# Mark as merged & create event if merged
if c_ids.include?(merge_request.last_commit.id)
merge_request.mark_as_merged!
Event.create(
:project => self,
:action => Event::Merged,
:data => {:merge_request_id => merge_request.id},
:author_id => user.id
)
end
end
true
end
def execute_web_hooks(oldrev, newrev, ref, author_key_id)
ref_parts = ref.split('/')
 
Loading
Loading
Loading
Loading
@@ -2,7 +2,9 @@
.ui-box
%h5 Commits
.merge-request-commits
%ul.unstyled= render @commits
%ul.unstyled
- @commits.each do |commit|
= render "commits/commit", :commit => commit
 
- else
%h5
Loading
Loading
Loading
Loading
@@ -11,12 +11,10 @@
 
%span.right
- if can?(current_user, :modify_merge_request, @merge_request)
- if @merge_request.closed
= link_to 'Reopen', project_merge_request_path(@project, @merge_request, :merge_request => {:closed => false }, :status_only => true), :method => :put, :class => "btn"
- else
- if @merge_request.open?
= 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"
= link_to edit_project_merge_request_path(@project, @merge_request), :class => "btn" do
Edit
= link_to edit_project_merge_request_path(@project, @merge_request), :class => "btn" do
Edit
 
- if @merge_request.upvotes > 0
= link_to "#notes", :class => "btn success" do
Loading
Loading
Loading
Loading
@@ -8,7 +8,13 @@ class PostReceive
# Ignore push from non-gitlab users
return false unless Key.find_by_identifier(author_key_id)
 
# Create push event
project.observe_push(oldrev, newrev, ref, author_key_id)
# Close merged MR
project.update_merge_requests(oldrev, newrev, ref, author_key_id)
# Execute web hooks
project.execute_web_hooks(oldrev, newrev, ref, author_key_id)
end
end
class AddCommitsDiffStoreToMergeRequest < ActiveRecord::Migration
def change
add_column :merge_requests, :st_commits, :text, :null => true
add_column :merge_requests, :st_diffs, :text, :null => true
end
end
class AddMergedToMergeRequest < ActiveRecord::Migration
def change
add_column :merge_requests, :merged, :true, :null => false, :default => false
end
end
Loading
Loading
@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
 
ActiveRecord::Schema.define(:version => 20120307095918) do
ActiveRecord::Schema.define(:version => 20120315132931) do
 
create_table "events", :force => true do |t|
t.string "target_type"
Loading
Loading
@@ -50,19 +50,8 @@ ActiveRecord::Schema.define(:version => 20120307095918) do
t.integer "project_id"
end
 
create_table "merge_requests", :force => true do |t|
t.string "target_branch", :null => false
t.string "source_branch", :null => false
t.integer "project_id", :null => false
t.integer "author_id"
t.integer "assignee_id"
t.string "title"
t.boolean "closed", :default => false, :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "merge_requests", ["project_id"], :name => "index_merge_requests_on_project_id"
# Could not dump table "merge_requests" because of following StandardError
# Unknown type 'true' for column 'merged'
 
create_table "notes", :force => true do |t|
t.text "note"
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment