|
- # encoding: utf-8
- # 如果你对改模块任何功能不清楚,请不要随便改
- # @Hjqreturn
- class PullRequestsController < ApplicationController
- before_filter :authorize_logged
- before_filter :find_project_and_repository
- before_filter :connect_gitlab, :only => [:index, :show, :create, :accept_pull_request, :pull_request_commits, :pull_request_changes, :new, :update_pull_request, :pull_request_comments, :create_pull_request_comment, :compare_pull_request]
- before_filter :member_allowed, :only => [:new, :create, :create_pull_request_comment]
- before_filter :manager_allowed, :only => [:accept_pull_request]
-
- layout "base_projects"
- include PullRequestsHelper
- include ApplicationHelper
-
- require 'ostruct'
-
- # 返回json格式
- def index
- # project_menu_type 为了控制base顶部导航
- @project_menu_type = 6
- # 不符合pullrequest条件的给出提示
- @allow_to_pull_request = allow_pull_request(@project) > 0
-
- type = params[:type]
- merge_requests = @g.merge_requests(@project.gpid)
- merge_requests_count = merge_requests.count
- case type
- when nil, "1"
- @requests = merge_requests.select{|request| request.state == "opened" || request.state == "reopened"}
- # 更新统计数字
- project_score = @project.project_score.update_column(:pull_request_num, merge_requests_count)
- when "2"
- @requests = merge_requests.select{|request| request.state == "merged"}
- when "3"
- @requests = merge_requests.select{|request| request.state == "closed"}
- end
- @requests_opened_count = @requests.count
- @requests_merged_count = merge_requests.select{|request| request.state == "merged"}.count
- @requests_closed_count = merge_requests.select{|request| request.state == "closed"}.count
-
- @limit = 20
- @is_remote = true
- @count = type_count(type, @requests_opened_count, @requests_merged_count, @requests_closed_count)
- @pages = Paginator.new @count, @limit, params['page'] || 1
- @offset ||= @pages.offset
- @requests = paginateHelper @requests, 20
- respond_to do |format|
- format.html
- format.js
- end
- end
-
- # 主要取源项目和目标项目分支及标识(用户名/版本库名)
- # @tip 为空的时候表明发送的pr请求有改动,为1的时候源分支和目标分支没有改动,则不能成功创建
- def new
- # project_menu_type 为了控制base顶部导航
- @project_menu_type = 6
- @tip = params[:show_tip]
- identifier = get_rep_identifier_by_project @project
- @source_project_name = "#{get_user_name(@project.user_id)}/#{identifier}"
- @source_rev = @g.branches(@project.gpid).map{|b| b.name}
-
- # 获取forked源项目信息
- if @project.forked_from_project_id
- @forked_project = Project.find(@project.forked_from_project_id)
- identifier = get_rep_identifier_by_project @forked_project
- @forked_project_name = "#{get_user_name(@forked_project.user_id)}/#{identifier}"
- @forked_rev = @g.branches(@forked_project.gpid).map{|b| b.name}
- end
- end
-
- # Creates a merge request.
- # If the operation is successful, 200 and the newly created merge request is returned. If an error occurs, an error number and a message explaining the reason is returned.
- #
- # @example
- # Gitlab.create_merge_request(5, 'New merge request',
- # :source_branch => 'source_branch', :target_branch => 'target_branch')
- # Gitlab.create_merge_request(5, 'New merge request',
- # :source_branch => 'source_branch', :target_branch => 'target_branch', :assignee_id => 42)
- #
- # @param [Integer] project The ID of a project.
- # @param [String] title The title of a merge request.
- # @param [Hash] options A customizable set of options.
- # @option options [String] :source_branch (required) The source branch name.
- # @option options [String] :target_branch (required) The target branch name.
- # @option options [Integer] :assignee_id (optional) The ID of a user to assign merge request.
- # @return [Gitlab::ObjectifiedHash] Information about created merge request.
- def create
- title = params[:title]
- description = params[:description]
- source_branch = params[:source_branch]
- target_branch = params[:target_branch]
- target_project_id = params[:target_project_id]
- begin
- # 如果分支有改动
- if compare_pull_request(source_branch, target_project_id, target_branch)
- # 如果传送了目标项目ID即向fork源项目发送请求
- # if params[:forked_project_id] && params[:source_project] == "forked_project_name"
- if !params[:target_project_id].blank? && params[:target_project_id].to_i != @project.id
- target_project_id = params[:forked_project_id].to_i
- request = @g.create_merge_request(@project.gpid, title, User.current.gid, :description => description, :source_branch => source_branch, :target_branch => target_branch, :target_project_id => target_project_id)
- @fork_project_name = Project.find(params[:target_project_id]).try(:name)
- @fork_pr_message = true if @fork_project_name
- # 向管理员发送消息
- send_message_to_manager(params[:target_project_id].to_i, request.id, 1)
- PullRequest.create(:pull_request_id => request.id, :user_id => User.current.id, :status => 1, :project_id => target_project_id, :title => title)
- else
- @project_member = Member.where(:project_id => @project.id)
- request = @g.create_merge_request(@project.gpid, title, User.current.gid, :description => description, :source_branch => source_branch, :target_branch => target_branch)
- # 发送消息
- send_message_to_manager(@project.id, request.id, 1)
- # 创建Trustie数据
- PullRequest.create(:pull_request_id => request.id, :user_id => User.current.id, :status => 1, :project_id => @project.id, :title => title)
- respond_to do |format|
- format.js{redirect_to project_pull_request_path(request.id, :project_id => @project.id)}
- end
- end
- else
- tip = 1
- respond_to do |format|
- format.js{redirect_to new_project_pull_request_path(:show_tip => tip)}
- end
- end
- rescue Gitlab::Error::Forbidden => e
- @message = l(:label_pull_request_forbidden)
- rescue Gitlab::Error::Conflict => e
- @message = l(:label_pull_request_conflic)
- rescue Gitlab::Error::NotFound => e
- @message = l(:label_pull_request_notfound)
- rescue Exception => e
- puts e
- end
- end
-
- # Compare branch for MR
- # 判断源分支和目标分支是否有改动
- # status 为true 表示有改动; false:便是没有改动
- def compare_pull_request source_branch, target_project, target_branch
- user_name_source = @project.owner.try(:login)
- identifier = @repository.identifier.downcase
- git_source_tree = '--git-dir=/home/git/repositories/' + user_name_source + '/' + identifier + '.git'
- if target_project
- forked_source_project = Project.find(target_project)
- user_name_target = forked_source_project.owner.try(:login)
- git_target_tree = '--git-dir=/home/git/repositories/' + user_name_target + '/' + identifier + '.git'
- git_sourse_commit_id = @g.get_branch_commit_id(@project.gpid, git_source_tree, source_branch)
- git_target_commit_id = @g.get_branch_commit_id(forked_source_project.gpid, git_target_tree, target_branch)
- else
- git_sourse_commit_id = @g.get_branch_commit_id(@project.gpid, git_source_tree, source_branch)
- git_target_commit_id = @g.get_branch_commit_id(@project.gpid, git_source_tree, target_branch)
- end
- status = (git_sourse_commit_id.try(:commit_id) == git_target_commit_id.try(:commit_id) ? false : true)
- end
-
- # @project_menu_type 为了控制base顶部导航
- # merge_when_succeeds
- def show
- # compare_pull_request source_project, source_branch, target_project, target_branch
- # compare_pull_request
- # 如何从个人主页点击进入,则将该消息设为“已读”
- ForgeMessage.where(:forge_message_id => params[:id], :forge_message_type => "PullRequest", :user_id => User.current.id, :viewed => false).update_all(:viewed => true)
-
- @project_menu_type = 6
- @type = params[:type]
- @request = @g.merge_request(@project.gpid, params[:id])
- @commits = @g.merge_request_commits(@project.gpid, params[:id].to_i)
- @commits_count = @commits.count
- # @commits_day = @commits.chunk
- @changes = @g.merge_request_changes(@project.gpid, params[:id]).try(:changes)
- @changes_count = @changes.count
- @comments = @g.merge_request_comments(@project.gpid, params[:id]).reverse
- @comments_count = @comments.count
-
- @limit = 10
- @is_remote = true
- @count = @comments_count
- @pages = Paginator.new @count, @limit, params['page'] || 1
- @offset ||= @pages.offset
- @comments = paginateHelper @comments, 10
- end
-
- # Accept a merge request.
- # If merge success you get 200 OK.
- # Accept a merge request.
- #
- # @example
- # Gitlab.accept_pull_rquest(5, 1)
- #
- # @param [Integer] project The ID of a project.
- # @param [Integer] id The ID of a merge request.
- # @return [Gitlab::ObjectifiedHash]
- def accept_pull_request
- begin
- @status = @g.accept_merge_rquest(@project.gpid, params[:id], User.current.gid)
- user = User.find_by_login(@status.author.try(:username))
- # 更新管理员的pullrequest消息
- update_pullrequest_message(params[:id].to_i, @project.id, "PullRequest", 2)
- # 接受后,给用户发消息
- if ForgeMessage.where(:forge_message_id => params[:id].to_i, :project_id => @project.id, :forge_message_type => "PullRequest", :user_id => user.id).count == 0
- send_message_to_author(@project.id, @status.author.try(:username), params[:id], 2)
- end
- respond_to do |format|
- format.js{redirect_to project_pull_request_path(@status.id, :project_id => @project.id)}
- end
- rescue Gitlab::Error::Forbidden => e
- @message = l(:label_pull_request_forbidden)
- rescue Gitlab::Error::DataNotAccepted => e
- @message = l(:label_pull_request_datanotaccepted)
- rescue Gitlab::Error::NotFound => e
- @message = l(:label_pull_request_notfound)
- rescue Exception => e
- puts e
- end
- end
-
- # Updates a merge request.
- #
- # @example
- # Gitlab.update_merge_request(5, 42, :title => 'New title')
- #
- # @param [Integer] project The ID of a project.
- # @param [Integer] id The ID of a merge request.
- # @param [Hash] options A customizable set of options.
- # @option options [String] :title The title of a merge request.
- # @option options [String] :source_branch The source branch name.
- # @option options [String] :target_branch The target branch name.
- # @option options [Integer] :assignee_id The ID of a user to assign merge request.
- # @option options [String] :state_event New state (close|reopen|merge).
- # @return [Gitlab::ObjectifiedHash] Information about updated merge request.
- def update_pull_request
- begin
- request = @g.update_merge_request(@project.gpid, params[:id], User.current.gid, :state_event => params[:state])
- user = User.find_by_login(request.author.try(:username))
- status = params[:state] == "close" ? 4 : 3
- #send_message_to_manager(@project.id, params[:id], status)
- update_pullrequest_message(request.id, @project.id, "PullRequest", status)
- # 给作者发送消息,如何已经发送了消息,则不发
- if is_project_manager?(User.current.id, @project.id) && ForgeMessage.where(:forge_message_id => request.id, :project_id => @project.id, :forge_message_type => "PullRequest", :user_id => user.id).count == 0
- send_message_to_author(@project.id, user.login, request.id, status)
- end
- respond_to do |format|
- format.html{redirect_to project_pull_request_path(params[:id], :project_id => @project.id)}
- end
- rescue Exception => e
- @message = e.message
- end
- end
-
- # Creates a merge request.
- #
- # @example
- # Gitlab.create_merge_request(5, 'New merge request',
- # :source_branch => 'source_branch', :target_branch => 'target_branch')
- # Gitlab.create_merge_request(5, 'New merge request',
- # :source_branch => 'source_branch', :target_branch => 'target_branch', :assignee_id => 42)
- def create_pull_request_comment
- content = params[:pull_request_comment]
- begin
- @comments = @g.create_merge_request_comment(@project.gpid, params[:id], content, User.current.gid)
- respond_to do |format|
- format.js{redirect_to project_pull_request_path(params[:id], :project_id => @project.id)}
- end
- rescue Exception => e
- @message = e.message
- end
- end
-
- # Gets the comments on a merge request.
- #
- # @example
- # Gitlab.merge_request_comments(5, 1)
- def pull_request_comments
- begin
- @comments = @g.merge_request_comments(@project.gpid, params[:id]).reverse
- @comments_count = @comments.count
-
- @limit = 10
- @is_remote = true
- @count = @comments_count
- @pages = Paginator.new @count, @limit, params['page'] || 1
- @offset ||= @pages.offset
- @comments = paginateHelper @comments, 10
- rescue Exception => e
- @message = e.message
- end
- end
-
- # Get a list of merge request commits.
- # Parameters:
- # id (required) - The ID of a project
- # merge_request_id (required) - The ID of MR
- def pull_request_commits
- begin
- @type = params[:type]
- @commits = @g.merge_request_commits(@project.gpid, params[:id])
- @commits_count = @commits.count
-
- @limit = 10
- @is_remote = true
- @count = @commits_count
- @pages = Paginator.new @count, @limit, params['page'] || 1
- @offset ||= @pages.offset
- @commits = paginateHelper @commits, 10
- rescue Exception => e
- @message = e.message
- end
- end
-
- # Shows information about the merge request including its files and changes. With GitLab 8.2 the return fields upvotes and downvotes are deprecated and always return 0.
- # Parameters:
- # id (required) - The ID of a project
- # merge_request_id (required) - The ID of MR
- def pull_request_changes
- @type = params[:type]
- @changes = @g.merge_request_changes(@project.gpid, params[:id]).try(:changes)
-
-
-
-
- @changes_count = @changes.count
- @limit = 10
- @is_remote = true
- @count = @changes_count
- @pages = Paginator.new @count, @limit, params['page'] || 1
- @offset ||= @pages.offset
- @changes = paginateHelper @changes, 10
-
- end
-
- private
- # post 相关操作权限控制
- # 项目管理员可操作
- def manager_allowed
- unless is_project_manager?(User.current.id, @project.id)
- return render_403
- end
- end
-
- # 项目成员可操作
- def member_allowed
- unless User.current.member_of?(@project)
- return render_403
- end
- end
-
- def send_message user_id, project_id, pull_request_id
- ForgeMessage.create(:user_id => user_id, :project_id => project_id,
- :forge_message_id => pull_request_id, :forge_message_type => "PullRequest", :viewed => true)
- end
-
- def send_message_to_manager project_id, pull_request_id, status
- project = Project.find(project_id)
- project.members.each do |member|
- if is_project_manager?(member.user_id, project_id) && User.current.id != member.user_id
- add_message(member.user_id, project_id, pull_request_id, status)
- end
- end
- end
-
- def send_message_to_author(project_id, user_login, request_id, status)
- user = get_user_by_login_and(user_login)
- if user.id != User.current.id
- add_message(user.id, project_id, request_id, status)
- end
- end
-
- def add_message(user_id, project_id, pull_request_id, status)
- ForgeMessage.create(:user_id => user_id,
- :project_id => project_id,
- :forge_message_id => pull_request_id,
- :forge_message_type => "PullRequest",
- :viewed => false,
- :status => status,
- :operate_user_id => User.current.id,
- )
- end
-
- def update_pullrequest_message forge_message_id, project_id, forge_message_type, status
- # 更新这条pullrequest消息所有相关的信息
- ForgeMessage.where(:forge_message_id => forge_message_id, :project_id => project_id, :forge_message_type => forge_message_type).update_all(:status => status, :operate_user_id => User.current.id, :updated_at => Time.now)
- # 更新自己的消息为已读
- ForgeMessage.where(:forge_message_id => forge_message_id, :project_id => project_id, :forge_message_type => forge_message_type, :user_id => User.current.id).update_all(:viewed => true)
- # 更新pullrequest的status字段
- PullRequest.where(:pull_request_id => forge_message_id).update_all(:status => status)
- end
-
- def authorize_logged
- if !User.current.logged?
- redirect_to signin_path
- return
- end
- end
-
- def connect_gitlab
- @g = Gitlab.client
- end
-
- def find_project_and_repository
- @project = Project.find(params[:project_id])
- render_404 if @project.gpid.blank?
- @repository = Repository.where(:project_id => @project.id, :type => "Repository::Gitlab").first
- rescue ActiveRecord::RecordNotFound
- render_404
- end
-
- end
|