Persist Merge Request diff. Auto merge request close on push
This commit is contained in:
parent
27e3699814
commit
5a3f23f395
10 changed files with 121 additions and 28 deletions
|
@ -41,13 +41,12 @@ class MergeRequestsController < ApplicationController
|
||||||
|
|
||||||
@note = @project.notes.new(:noteable => @merge_request)
|
@note = @project.notes.new(:noteable => @merge_request)
|
||||||
|
|
||||||
@commits = @project.repo.
|
# Get commits from repository
|
||||||
commits_between(@merge_request.target_branch, @merge_request.source_branch).
|
# or from cache if already merged
|
||||||
map {|c| Commit.new(c)}.
|
@commits = @merge_request.commits
|
||||||
sort_by(&:created_at).
|
|
||||||
reverse
|
|
||||||
|
|
||||||
render_full_content
|
# Close MR if nothing to merge
|
||||||
|
#@merge_request.mark_as_merged! if @merge_request.probably_merged?
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html
|
format.html
|
||||||
|
@ -76,6 +75,8 @@ class MergeRequestsController < ApplicationController
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
if @merge_request.save
|
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.html { redirect_to [@project, @merge_request], notice: 'Merge request was successfully created.' }
|
||||||
format.json { render json: @merge_request, status: :created, location: @merge_request }
|
format.json { render json: @merge_request, status: :created, location: @merge_request }
|
||||||
else
|
else
|
||||||
|
|
|
@ -7,6 +7,7 @@ class Event < ActiveRecord::Base
|
||||||
Reopened = 4
|
Reopened = 4
|
||||||
Pushed = 5
|
Pushed = 5
|
||||||
Commented = 6
|
Commented = 6
|
||||||
|
Merged = 7
|
||||||
|
|
||||||
belongs_to :project
|
belongs_to :project
|
||||||
belongs_to :target, :polymorphic => true
|
belongs_to :target, :polymorphic => true
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
|
require File.join(Rails.root, "app/models/commit")
|
||||||
|
|
||||||
class MergeRequest < ActiveRecord::Base
|
class MergeRequest < ActiveRecord::Base
|
||||||
belongs_to :project
|
belongs_to :project
|
||||||
belongs_to :author, :class_name => "User"
|
belongs_to :author, :class_name => "User"
|
||||||
belongs_to :assignee, :class_name => "User"
|
belongs_to :assignee, :class_name => "User"
|
||||||
has_many :notes, :as => :noteable, :dependent => :destroy
|
has_many :notes, :as => :noteable, :dependent => :destroy
|
||||||
|
|
||||||
|
serialize :st_commits
|
||||||
|
serialize :st_diffs
|
||||||
|
|
||||||
attr_protected :author, :author_id, :project, :project_id
|
attr_protected :author, :author_id, :project, :project_id
|
||||||
attr_accessor :author_id_of_changes
|
attr_accessor :author_id_of_changes
|
||||||
|
|
||||||
|
@ -32,7 +37,6 @@ class MergeRequest < ActiveRecord::Base
|
||||||
scope :closed, where(:closed => true)
|
scope :closed, where(:closed => true)
|
||||||
scope :assigned, lambda { |u| where(:assignee_id => u.id)}
|
scope :assigned, lambda { |u| where(:assignee_id => u.id)}
|
||||||
|
|
||||||
|
|
||||||
def validate_branches
|
def validate_branches
|
||||||
if target_branch == source_branch
|
if target_branch == source_branch
|
||||||
errors.add :base, "You can not use same branch for source and target branches"
|
errors.add :base, "You can not use same branch for source and target branches"
|
||||||
|
@ -44,18 +48,65 @@ class MergeRequest < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def diffs
|
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)}
|
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 []
|
diffs = project.repo.diff(commits.first.prev_commit.id, commits.last.id) rescue []
|
||||||
end
|
end
|
||||||
|
|
||||||
def last_commit
|
def last_commit
|
||||||
project.commit(source_branch)
|
commits.first
|
||||||
end
|
end
|
||||||
|
|
||||||
# Return the number of +1 comments (upvotes)
|
# Return the number of +1 comments (upvotes)
|
||||||
def upvotes
|
def upvotes
|
||||||
notes.select(&:upvote?).size
|
notes.select(&:upvote?).size
|
||||||
end
|
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
|
end
|
||||||
# == Schema Information
|
# == Schema Information
|
||||||
#
|
#
|
||||||
|
|
|
@ -73,6 +73,40 @@ class Project < ActiveRecord::Base
|
||||||
)
|
)
|
||||||
end
|
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)
|
def execute_web_hooks(oldrev, newrev, ref, author_key_id)
|
||||||
ref_parts = ref.split('/')
|
ref_parts = ref.split('/')
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
.ui-box
|
.ui-box
|
||||||
%h5 Commits
|
%h5 Commits
|
||||||
.merge-request-commits
|
.merge-request-commits
|
||||||
%ul.unstyled= render @commits
|
%ul.unstyled
|
||||||
|
- @commits.each do |commit|
|
||||||
|
= render "commits/commit", :commit => commit
|
||||||
|
|
||||||
- else
|
- else
|
||||||
%h5
|
%h5
|
||||||
|
|
|
@ -11,9 +11,7 @@
|
||||||
|
|
||||||
%span.right
|
%span.right
|
||||||
- if can?(current_user, :modify_merge_request, @merge_request)
|
- if can?(current_user, :modify_merge_request, @merge_request)
|
||||||
- if @merge_request.closed
|
- if @merge_request.open?
|
||||||
= link_to 'Reopen', project_merge_request_path(@project, @merge_request, :merge_request => {:closed => false }, :status_only => true), :method => :put, :class => "btn"
|
|
||||||
- else
|
|
||||||
= 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 '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
|
= link_to edit_project_merge_request_path(@project, @merge_request), :class => "btn" do
|
||||||
Edit
|
Edit
|
||||||
|
|
|
@ -8,7 +8,13 @@ class PostReceive
|
||||||
# Ignore push from non-gitlab users
|
# Ignore push from non-gitlab users
|
||||||
return false unless Key.find_by_identifier(author_key_id)
|
return false unless Key.find_by_identifier(author_key_id)
|
||||||
|
|
||||||
|
# Create push event
|
||||||
project.observe_push(oldrev, newrev, ref, author_key_id)
|
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)
|
project.execute_web_hooks(oldrev, newrev, ref, author_key_id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
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
|
5
db/migrate/20120315132931_add_merged_to_merge_request.rb
Normal file
5
db/migrate/20120315132931_add_merged_to_merge_request.rb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
class AddMergedToMergeRequest < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_column :merge_requests, :merged, :true, :null => false, :default => false
|
||||||
|
end
|
||||||
|
end
|
17
db/schema.rb
17
db/schema.rb
|
@ -11,7 +11,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended to check this file into your version control system.
|
# 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|
|
create_table "events", :force => true do |t|
|
||||||
t.string "target_type"
|
t.string "target_type"
|
||||||
|
@ -50,19 +50,8 @@ ActiveRecord::Schema.define(:version => 20120307095918) do
|
||||||
t.integer "project_id"
|
t.integer "project_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "merge_requests", :force => true do |t|
|
# Could not dump table "merge_requests" because of following StandardError
|
||||||
t.string "target_branch", :null => false
|
# Unknown type 'true' for column 'merged'
|
||||||
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"
|
|
||||||
|
|
||||||
create_table "notes", :force => true do |t|
|
create_table "notes", :force => true do |t|
|
||||||
t.text "note"
|
t.text "note"
|
||||||
|
|
Loading…
Reference in a new issue