Commit 08994f3f authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge remote-tracking branch 'origin/merge_button'

Conflicts:
	app/assets/javascripts/merge_requests.js
	db/schema.rb
parents 9af14e4b 3a6694b5
var MergeRequest = { var MergeRequest = {
diffs_loaded: false, diffs_loaded: false,
commits_loaded: false, commits_loaded: false,
opts: false,
init: init:
function() { function(opts) {
this.opts = opts;
if($(".automerge_widget").length){
$.get(opts.url_to_automerge_check, function(data){
$(".automerge_widget").hide();
$(".automerge_widget." + data.state).show();
}, "json");
}
$(".nav-tabs a").live("click", function() { $(".nav-tabs a").live("click", function() {
$(".nav-tabs a").parent().removeClass("active"); $(".nav-tabs a").parent().removeClass("active");
$(this).parent().addClass("active"); $(this).parent().addClass("active");
...@@ -44,5 +54,11 @@ var MergeRequest = { ...@@ -44,5 +54,11 @@ var MergeRequest = {
function() { function() {
$(".first_mr_commits").remove(); $(".first_mr_commits").remove();
$(".all_mr_commits").removeClass("hide"); $(".all_mr_commits").removeClass("hide");
},
already_cannot_be_merged:
function(){
$(".automerge_widget").hide();
$(".automerge_widget.already_cannot_be_merged").show();
} }
} }
...@@ -2,7 +2,7 @@ class MergeRequestsController < ApplicationController ...@@ -2,7 +2,7 @@ class MergeRequestsController < ApplicationController
before_filter :authenticate_user! before_filter :authenticate_user!
before_filter :project before_filter :project
before_filter :module_enabled before_filter :module_enabled
before_filter :merge_request, :only => [:edit, :update, :destroy, :show, :commits, :diffs] before_filter :merge_request, :only => [:edit, :update, :destroy, :show, :commits, :diffs, :automerge, :automerge_check]
layout "project" layout "project"
# Authorize # Authorize
...@@ -89,6 +89,7 @@ class MergeRequestsController < ApplicationController ...@@ -89,6 +89,7 @@ class MergeRequestsController < ApplicationController
respond_to do |format| respond_to do |format|
if @merge_request.update_attributes(params[:merge_request].merge(:author_id_of_changes => current_user.id)) if @merge_request.update_attributes(params[:merge_request].merge(:author_id_of_changes => current_user.id))
@merge_request.reload_code @merge_request.reload_code
@merge_request.mark_as_unchecked
format.html { redirect_to [@project, @merge_request], notice: 'Merge request was successfully updated.' } format.html { redirect_to [@project, @merge_request], notice: 'Merge request was successfully updated.' }
format.json { head :ok } format.json { head :ok }
else else
...@@ -98,6 +99,23 @@ class MergeRequestsController < ApplicationController ...@@ -98,6 +99,23 @@ class MergeRequestsController < ApplicationController
end end
end end
def automerge_check
if @merge_request.unchecked?
@merge_request.check_if_can_be_merged
end
render :json => {:state => @merge_request.human_state}
end
def automerge
return access_denied! unless can?(current_user, :accept_mr, @project)
if @merge_request.open? && @merge_request.can_be_merged?
@merge_request.automerge!(current_user)
@status = true
else
@status = false
end
end
def destroy def destroy
@merge_request.destroy @merge_request.destroy
......
...@@ -48,6 +48,7 @@ class Ability ...@@ -48,6 +48,7 @@ class Ability
:admin_team_member, :admin_team_member,
:admin_merge_request, :admin_merge_request,
:admin_note, :admin_note,
:accept_mr,
:admin_wiki :admin_wiki
] if project.master_access_for?(user) || project.owner == user ] if project.master_access_for?(user) || project.owner == user
......
require File.join(Rails.root, "app/models/commit") require File.join(Rails.root, "app/models/commit")
class MergeRequest < ActiveRecord::Base class MergeRequest < ActiveRecord::Base
UNCHECKED = 1
CAN_BE_MERGED = 2
CANNOT_BE_MERGED = 3
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"
...@@ -45,6 +49,15 @@ class MergeRequest < ActiveRecord::Base ...@@ -45,6 +49,15 @@ class MergeRequest < ActiveRecord::Base
where("source_branch like :branch or target_branch like :branch", :branch => branch_name) where("source_branch like :branch or target_branch like :branch", :branch => branch_name)
end end
def human_state
states = {
CAN_BE_MERGED => "can_be_merged",
CANNOT_BE_MERGED => "cannot_be_merged",
UNCHECKED => "unchecked"
}
states[self.state]
end
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"
...@@ -56,6 +69,27 @@ class MergeRequest < ActiveRecord::Base ...@@ -56,6 +69,27 @@ class MergeRequest < ActiveRecord::Base
self.reloaded_diffs self.reloaded_diffs
end end
def unchecked?
state == UNCHECKED
end
def mark_as_unchecked
self.update_attributes(:state => UNCHECKED)
end
def can_be_merged?
state == CAN_BE_MERGED
end
def check_if_can_be_merged
self.state = if GitlabMerge.new(self, self.author).can_be_merged?
CAN_BE_MERGED
else
CANNOT_BE_MERGED
end
self.save
end
def new? def new?
today? && created_at == updated_at today? && created_at == updated_at
end end
...@@ -118,6 +152,10 @@ class MergeRequest < ActiveRecord::Base ...@@ -118,6 +152,10 @@ class MergeRequest < ActiveRecord::Base
save save
end end
def mark_as_unmergable
self.update_attributes :state => CANNOT_BE_MERGED
end
def reloaded_commits def reloaded_commits
if open? && unmerged_commits.any? if open? && unmerged_commits.any?
self.st_commits = unmerged_commits self.st_commits = unmerged_commits
...@@ -144,6 +182,16 @@ class MergeRequest < ActiveRecord::Base ...@@ -144,6 +182,16 @@ class MergeRequest < ActiveRecord::Base
:author_id => user_id :author_id => user_id
) )
end end
def automerge!(current_user)
if GitlabMerge.new(self, current_user).merge
self.merge!(current_user.id)
true
end
rescue
self.mark_as_unmergable
false
end
end end
# == Schema Information # == Schema Information
# #
......
...@@ -18,7 +18,7 @@ module Project::HooksTrait ...@@ -18,7 +18,7 @@ module Project::HooksTrait
# Update code for merge requests # Update code for merge requests
mrs = self.merge_requests.opened.find_all_by_branch(branch_name).all mrs = self.merge_requests.opened.find_all_by_branch(branch_name).all
mrs.each { |merge_request| merge_request.reload_code } mrs.each { |merge_request| merge_request.reload_code; merge_request.mark_as_unchecked }
# Close merge requests # Close merge requests
mrs = self.merge_requests.opened.where(:target_branch => branch_name).all mrs = self.merge_requests.opened.where(:target_branch => branch_name).all
......
-if @status
:plain
location.reload();
-else
:plain
MergeRequest.already_cannot_be_merged()
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
%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.open? - if @merge_request.open?
= link_to "Show how to merge", "#", :class => "how_to_merge_link btn small padded", :title => "How To Merge"
= link_to 'Close', project_merge_request_path(@project, @merge_request, :merge_request => {:closed => true }, :status_only => true), :method => :put, :class => "btn small padded", :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 small padded", :title => "Close merge request"
= link_to edit_project_merge_request_path(@project, @merge_request), :class => "btn small padded" do = link_to edit_project_merge_request_path(@project, @merge_request), :class => "btn small padded" do
Edit Edit
...@@ -53,6 +52,34 @@ ...@@ -53,6 +52,34 @@
Closed by #{@merge_request.closed_event.author_name} Closed by #{@merge_request.closed_event.author_name}
%small #{time_ago_in_words(@merge_request.closed_event.created_at)} ago. %small #{time_ago_in_words(@merge_request.closed_event.created_at)} ago.
- if @merge_request.open? && @commits.any? && can?(current_user, :accept_mr, @project)
.automerge_widget.can_be_merged{:style => "display:none"}
.ui-box.padded
%p
You can accept this request automatically. If you still want to do it manually - #{link_to "click here", "#", :class => "how_to_merge_link vlink", :title => "How To Merge"} for instructions
= link_to "Accept Merge Request", automerge_project_merge_request_path(@project, @merge_request), :class => "btn small info accept_merge_request", :remote => true
&nbsp;
.automerge_widget.cannot_be_merged{:style => "display:none"}
.alert-message
%p
%strong This request cant be merged with GitLab. You should do it manually &nbsp;
= link_to "Show how to merge", "#", :class => "how_to_merge_link btn small padded", :title => "How To Merge"
.automerge_widget.unchecked
.alert-message
%p
%strong Checking for ability to automatically merge…
.automerge_widget.already_cannot_be_merged{:style => "display:none"}
.alert-message
%p
%strong This merge request already can not be merged
= render "merge_requests/commits" = render "merge_requests/commits"
- unless @commits.empty? - unless @commits.empty?
...@@ -72,7 +99,13 @@ ...@@ -72,7 +99,13 @@
:javascript :javascript
$(function(){ $(function(){
MergeRequest.init(); MergeRequest.init({
url_to_automerge_check: "#{automerge_check_project_merge_request_path(@project, @merge_request)}",
});
$(".accept_merge_request").live("ajax:beforeSend", function() {
$(this).replaceWith('#{image_tag "ajax_loader.gif"}');
})
}) })
= render "notes/per_line_form" = render "notes/per_line_form"
......
...@@ -100,6 +100,8 @@ Gitlab::Application.routes.draw do ...@@ -100,6 +100,8 @@ Gitlab::Application.routes.draw do
resources :merge_requests do resources :merge_requests do
member do member do
get :diffs get :diffs
get :automerge
get :automerge_check
end end
collection do collection do
......
class AddAutomergeToMergeRequest < ActiveRecord::Migration
def change
add_column :merge_requests, :state, :integer, :null => false, :default => 1
end
end
...@@ -11,8 +11,7 @@ ...@@ -11,8 +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 => 20120413135904) do ActiveRecord::Schema.define(:version => 20120329170745) do
create_table "events", :force => true do |t| create_table "events", :force => true do |t|
t.string "target_type" t.string "target_type"
t.integer "target_id" t.integer "target_id"
...@@ -65,6 +64,7 @@ ActiveRecord::Schema.define(:version => 20120413135904) do ...@@ -65,6 +64,7 @@ ActiveRecord::Schema.define(:version => 20120413135904) do
t.text "st_commits", :limit => 2147483647 t.text "st_commits", :limit => 2147483647
t.text "st_diffs", :limit => 2147483647 t.text "st_diffs", :limit => 2147483647
t.boolean "merged", :default => false, :null => false t.boolean "merged", :default => false, :null => false
t.boolean "auto_merge", :default => true, :null => false
end end
add_index "merge_requests", ["project_id"], :name => "index_merge_requests_on_project_id" add_index "merge_requests", ["project_id"], :name => "index_merge_requests_on_project_id"
......
class GitlabMerge
attr_accessor :project, :merge_path, :merge_request, :user
def initialize(merge_request, user)
self.user = user
self.merge_request = merge_request
self.project = merge_request.project
self.merge_path = File.join(Rails.root, "tmp", "merge_repo", project.path, merge_request.id.to_s)
FileUtils.rm_rf(merge_path)
FileUtils.mkdir_p merge_path
end
def can_be_merged?
pull do |repo, output|
!(output =~ /Automatic merge failed/)
end
end
def merge
pull do |repo, output|
if output =~ /Automatic merge failed/
false
else
repo.git.push({}, "origin", merge_request.target_branch)
true
end
end
end
def pull
File.open(File.join(Rails.root, "tmp", "merge_repo", "#{project.path}.lock"), "w+") do |f|
f.flock(File::LOCK_EX)
self.project.repo.git.clone({:branch => merge_request.target_branch}, project.url_to_repo, merge_path)
unless File.exist?(self.merge_path)
raise "Gitlab user do not have access to repo. You should run: rake gitlab_enable_automerge"
end
Dir.chdir(merge_path) do
merge_repo = Grit::Repo.new('.')
merge_repo.git.sh "git config user.name \"#{user.name}\""
merge_repo.git.sh "git config user.email \"#{user.email}\""
output = merge_repo.git.pull({}, "--no-ff", "origin", merge_request.source_branch)
yield(merge_repo, output)
end
end
end
end
...@@ -123,5 +123,34 @@ module Gitlabhq ...@@ -123,5 +123,34 @@ module Gitlabhq
repo repo
end end
def admin_all_repo
ga_repo = ::Gitolite::GitoliteAdmin.new(File.join(@local_dir,'gitolite'))
conf = ga_repo.config
owner_name = ""
# Read gitolite-admin user
#
begin
repo = conf.get_repo("gitolite-admin")
owner_name = repo.permissions[0]["RW+"][""][0]
raise StandardError if owner_name.blank?
rescue => ex
puts "Cant determine gitolite-admin owner".red
raise StandardError
end
# @ALL repos premission for gitolite owner
repo_name = "@all"
repo = if conf.has_repo?(repo_name)
conf.get_repo(repo_name)
else
::Gitolite::Config::Repo.new(repo_name)
end
repo.add_permission("RW+", "", owner_name)
conf.add_repo(repo, true)
ga_repo.save
end
end end
end end
desc "Give gitlab user full access to every repo"
task :gitlab_enable_automerge => :environment do
Gitlabhq::GitHost.system.new.configure do |git|
git.admin_all_repo
end
puts "Done!".green
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment