Permalink
Browse files

Persist Merge Request diff. Auto merge request close on push

  • Loading branch information...
1 parent 27e3699 commit 5a3f23f395eef87bf3457e6474bac82333e71ec8 @dzaporozhets dzaporozhets committed Mar 14, 2012
@@ -41,13 +41,12 @@ def show
@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
@@ -76,6 +75,8 @@ def create
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
View
@@ -7,6 +7,7 @@ class Event < ActiveRecord::Base
Reopened = 4
Pushed = 5
Commented = 6
+ Merged = 7
belongs_to :project
belongs_to :target, :polymorphic => true
@@ -1,9 +1,14 @@
+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
@@ -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"
@@ -44,18 +48,65 @@ def new?
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
#
View
@@ -73,6 +73,40 @@ def observe_push(oldrev, newrev, ref, author_key_id)
)
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('/')
@@ -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
@@ -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
@@ -8,7 +8,13 @@ def self.perform(reponame, oldrev, newrev, ref, author_key_id)
# 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
@@ -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
@@ -0,0 +1,5 @@
+class AddMergedToMergeRequest < ActiveRecord::Migration
+ def change
+ add_column :merge_requests, :merged, :true, :null => false, :default => false
+ end
+end
View
@@ -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"
@@ -50,19 +50,8 @@
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"

0 comments on commit 5a3f23f

Please sign in to comment.