Merge remote-tracking branch 'origin/merge_button'
Conflicts: app/assets/javascripts/merge_requests.js db/schema.rb
This commit is contained in:
commit
08994f3f60
13 changed files with 223 additions and 7 deletions
|
@ -1,9 +1,19 @@
|
||||||
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 = {
|
||||||
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
|
||||||
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
|
||||||
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
|
||||||
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
|
||||||
: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
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
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
|
||||||
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
|
||||||
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
|
||||||
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
|
||||||
: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
|
||||||
|
|
||||||
# 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
|
||||||
|
|
7
app/views/merge_requests/automerge.js.haml
Normal file
7
app/views/merge_requests/automerge.js.haml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
-if @status
|
||||||
|
:plain
|
||||||
|
location.reload();
|
||||||
|
-else
|
||||||
|
:plain
|
||||||
|
MergeRequest.already_cannot_be_merged()
|
||||||
|
|
|
@ -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 @@
|
||||||
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
|
||||||
|
|
||||||
|
|
||||||
|
.automerge_widget.cannot_be_merged{:style => "display:none"}
|
||||||
|
.alert-message
|
||||||
|
%p
|
||||||
|
%strong This request cant be merged with GitLab. You should do it manually
|
||||||
|
= 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 @@
|
||||||
|
|
||||||
: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
|
||||||
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
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
class AddAutomergeToMergeRequest < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_column :merge_requests, :state, :integer, :null => false, :default => 1
|
||||||
|
end
|
||||||
|
end
|
|
@ -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
|
||||||
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"
|
||||||
|
|
48
lib/gitlab_merge.rb
Normal file
48
lib/gitlab_merge.rb
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
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
|
||||||
|
|
||||||
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
|
||||||
|
|
9
lib/tasks/gitlab_enable_automerge.rake
Normal file
9
lib/tasks/gitlab_enable_automerge.rake
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
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
|
Loading…
Add table
Reference in a new issue