2020-03-09 00:40:16 +08:00
class PullRequestsController < ApplicationController
2020-11-03 18:37:47 +08:00
before_action :require_login , except : [ :index , :show , :files , :commits ]
2021-08-31 18:00:54 +08:00
before_action :require_profile_completed , only : [ :create ]
2020-08-15 13:28:22 +08:00
before_action :load_repository
2022-03-07 10:53:07 +08:00
before_action :check_menu_authorize , only : [ :index , :show , :create , :update , :refuse_merge , :pr_merge ]
2020-11-03 18:37:47 +08:00
before_action :find_pull_request , except : [ :index , :new , :create , :check_can_merge , :get_branches , :create_merge_infos , :files , :commits ]
before_action :load_pull_request , only : [ :files , :commits ]
2021-10-20 09:39:21 +08:00
before_action :find_atme_receivers , only : [ :create , :update ]
2023-03-02 13:49:50 +08:00
2020-03-09 00:40:16 +08:00
include TagChosenHelper
include ApplicationHelper
def index
2023-05-30 15:10:02 +08:00
# @issues = Gitea::PullRequest::ListService.new(@user,@repository.try(:identifier)).call #通过gitea获取
issues = @project . issues . issue_pull_request . issue_index_includes . includes ( pull_request : :user )
issues = issues . where ( is_private : false ) unless current_user . present? && ( current_user . admin? || @project . member? ( current_user ) )
@all_issues = issues . distinct
@filter_issues = @all_issues
@filter_issues = @filter_issues . where ( " issues.subject LIKE ? OR issues.description LIKE ? " , " % #{ params [ :search ] } % " , " % #{ params [ :search ] } % " ) if params [ :search ] . present?
@open_issues = @filter_issues . joins ( :pull_request ) . where ( pull_requests : { status : PullRequest :: OPEN } )
@close_issues = @filter_issues . joins ( :pull_request ) . where ( pull_requests : { status : PullRequest :: CLOSED } )
@merged_issues = @filter_issues . joins ( :pull_request ) . where ( pull_requests : { status : PullRequest :: MERGED } )
2020-03-24 12:01:52 +08:00
@user_admin_or_member = current_user . present? && ( current_user . admin || @project . member? ( current_user ) )
2021-08-26 17:56:19 +08:00
@user_admin_or_developer = current_user . present? && ( current_user . admin || @project . all_developers . include? ( current_user ) )
2023-05-30 14:46:15 +08:00
2023-05-30 15:10:02 +08:00
scopes = Issues :: ListQueryService . call ( issues , params . delete_if { | k , v | v . blank? } , " PullRequest " )
@issues_size = scopes . size
@issues = paginate ( scopes )
2020-03-09 00:40:16 +08:00
end
def new
2022-04-26 17:15:59 +08:00
@all_branches = Branches :: ListService . call ( @owner , @project , params [ :branch_name ] )
2020-06-29 17:06:46 +08:00
@is_fork = @project . forked_from_project_id . present?
@projects_names = [ {
2020-11-03 18:37:47 +08:00
project_user_login : @owner . try ( :login ) ,
project_name : " #{ @owner . try ( :show_real_name ) } / #{ @repository . try ( :identifier ) } " ,
2020-08-15 13:49:36 +08:00
project_id : @project . identifier ,
id : @project . id
2020-06-29 17:06:46 +08:00
} ]
@merge_projects = @projects_names
fork_project = @project . fork_project if @is_fork
if fork_project . present?
@merge_projects . push ( {
2020-06-30 09:44:28 +08:00
project_user_login : fork_project . owner . try ( :login ) ,
2020-06-29 17:06:46 +08:00
project_name : " #{ fork_project . owner . try ( :show_real_name ) } / #{ fork_project . repository . try ( :identifier ) } " ,
2020-08-15 13:49:36 +08:00
project_id : fork_project . identifier ,
id : fork_project . id
2020-06-29 17:06:46 +08:00
} )
2020-03-09 00:40:16 +08:00
end
end
2020-06-29 17:06:46 +08:00
def get_branches
2022-04-26 17:15:59 +08:00
branch_result = Branches :: ListService . call ( @owner , @project , params [ :name ] )
2020-06-29 17:06:46 +08:00
render json : branch_result
# return json: branch_result
end
2020-03-09 00:40:16 +08:00
def create
2022-06-28 11:05:12 +08:00
if params [ :fork_project_id ] . present?
fork_project = Project . find_by ( id : params [ :fork_project_id ] )
return normal_status ( - 1 , " 您不是源项目开发者,没有权限,请联系源项目管理员. " ) unless fork_project && fork_project . operator? ( current_user )
else
return normal_status ( - 1 , " 您不是项目开发者,没有权限,请联系项目管理员. " ) unless @project . operator? ( current_user )
end
2020-12-23 15:46:06 +08:00
ActiveRecord :: Base . transaction do
2022-05-07 14:06:48 +08:00
Issues :: CreateForm . new ( { subject : params [ :title ] , description : params [ :body ] . blank? ? params [ :body ] : params [ :body ] . b } ) . validate!
2020-12-23 15:46:06 +08:00
@pull_request , @gitea_pull_request = PullRequests :: CreateService . call ( current_user , @owner , @project , params )
if @gitea_pull_request [ :status ] == :success
2023-06-15 17:45:07 +08:00
PullRequests :: SendJournalService . call ( @project , @pull_request , current_user )
2021-10-14 18:31:27 +08:00
@pull_request . bind_gitea_pull_request! ( @gitea_pull_request [ :body ] [ " number " ] , @gitea_pull_request [ :body ] [ " id " ] )
2022-07-26 16:45:53 +08:00
reviewers = User . where ( id : params [ :reviewer_ids ] )
@pull_request . reviewers = reviewers
2021-10-13 15:50:51 +08:00
SendTemplateMessageJob . perform_later ( 'PullRequestAssigned' , current_user . id , @pull_request & . id ) if Site . has_notice_menu?
SendTemplateMessageJob . perform_later ( 'ProjectPullRequest' , current_user . id , @pull_request & . id ) if Site . has_notice_menu?
2021-10-20 09:39:21 +08:00
Rails . logger . info " [ATME] maybe to at such users: #{ @atme_receivers . pluck ( :login ) } "
AtmeService . call ( current_user , @atme_receivers , @pull_request ) if @atme_receivers . size > 0
2023-03-02 13:49:50 +08:00
# author: zxh
# 调用上链API
2023-03-07 15:38:54 +08:00
push_activity_2_blockchain ( " pull_request_create " , @pull_request ) if Site . has_blockchain? && @project . use_blockchain
2023-03-02 13:49:50 +08:00
2020-12-23 15:46:06 +08:00
else
render_error ( " create pull request error: #{ @gitea_pull_request [ :status ] } " )
raise ActiveRecord :: Rollback
2020-03-09 00:40:16 +08:00
end
end
2021-11-29 10:53:59 +08:00
rescue = > e
normal_status ( - 1 , e . message )
2020-03-09 00:40:16 +08:00
end
def edit
2021-10-14 16:59:43 +08:00
@fork_project_user_name = @pull_request & . fork_project & . owner . try ( :show_real_name )
@fork_project_user = @pull_request & . fork_project & . owner . try ( :login )
@fork_project_identifier = @pull_request & . fork_project & . repository . try ( :identifier )
2020-03-09 00:40:16 +08:00
end
def update
2021-11-25 14:16:45 +08:00
return render_forbidden ( " 你没有权限操作. " ) unless @project . operator? ( current_user )
2020-03-09 00:40:16 +08:00
if params [ :title ] . nil?
normal_status ( - 1 , " 名称不能为空 " )
elsif params [ :issue_tag_ids ] . nil?
2021-09-16 18:39:19 +08:00
normal_status ( - 1 , " 标记不能为空 " )
2020-03-09 00:40:16 +08:00
else
ActiveRecord :: Base . transaction do
begin
2022-05-07 14:06:48 +08:00
Issues :: UpdateForm . new ( { subject : params [ :title ] , description : params [ :body ] . blank? ? params [ :body ] : params [ :body ] . b } ) . validate!
2020-06-12 18:22:42 +08:00
merge_params
2020-03-09 00:40:16 +08:00
2022-07-26 16:45:53 +08:00
reviewers = User . where ( id : params [ :reviewer_ids ] )
@pull_request . reviewers = reviewers
2020-06-12 18:22:42 +08:00
if @issue . update_attributes ( @issue_params )
2020-06-29 17:06:46 +08:00
if @pull_request . update_attributes ( @local_params . compact )
2021-01-12 15:45:18 +08:00
gitea_pull = Gitea :: PullRequest :: UpdateService . call ( @owner . login , @repository . identifier ,
2021-06-25 17:31:23 +08:00
@pull_request . gitea_number , @requests_params , current_user . gitea_token )
2021-01-12 15:45:18 +08:00
if gitea_pull [ :status ] === :success
2020-03-09 00:40:16 +08:00
if params [ :issue_tag_ids ] . present?
2021-11-29 10:27:41 +08:00
if params [ :issue_tag_ids ] . is_a? ( Array ) && params [ :issue_tag_ids ] . size > 1
return normal_status ( - 1 , " 最多只能创建一个标记。 " )
elsif params [ :issue_tag_ids ] . is_a? ( Array ) && params [ :issue_tag_ids ] . size == 1
@issue & . issue_tags_relates & . destroy_all
params [ :issue_tag_ids ] . each do | tag |
IssueTagsRelate . create! ( issue_id : @issue . id , issue_tag_id : tag )
end
else
return normal_status ( - 1 , " 请输入正确的标记。 " )
2023-03-02 13:49:50 +08:00
end
2020-03-09 00:40:16 +08:00
end
2023-03-02 15:55:46 +08:00
if params [ :attached_issue_ids ] . present?
if params [ :attached_issue_ids ] . is_a? ( Array ) && params [ :attached_issue_ids ] . size > 1
return normal_status ( - 1 , " 最多只能关联一个疑修。 " )
elsif params [ :attached_issue_ids ] . is_a? ( Array ) && params [ :attached_issue_ids ] . size == 1
@pull_request & . pull_attached_issues & . destroy_all
params [ :attached_issue_ids ] . each do | issue |
PullAttachedIssue . create! ( issue_id : issue , pull_request_id : @pull_request . id )
end
else
return normal_status ( - 1 , " 请输入正确的疑修。 " )
end
end
2020-03-09 00:40:16 +08:00
if params [ :status_id ] . to_i == 5
@issue . issue_times . update_all ( end_time : Time . now )
end
2021-10-20 09:39:21 +08:00
Rails . logger . info " [ATME] maybe to at such users: #{ @atme_receivers . pluck ( :login ) } "
AtmeService . call ( current_user , @atme_receivers , @pull_request ) if @atme_receivers . size > 0
2020-03-09 00:40:16 +08:00
normal_status ( 0 , " PullRequest更新成功 " )
else
normal_status ( - 1 , " PullRequest更新失败 " )
end
else
normal_status ( - 1 , " PullRequest更新失败 " )
end
end
rescue = > e
normal_status ( - 1 , e . message )
raise ActiveRecord :: Rollback
end
2021-10-13 15:50:51 +08:00
SendTemplateMessageJob . perform_later ( 'PullRequestChanged' , current_user . id , @pull_request & . id , @issue . previous_changes . slice ( :assigned_to_id , :priority_id , :fixed_version_id , :issue_tags_value ) ) if Site . has_notice_menu?
SendTemplateMessageJob . perform_later ( 'PullRequestAssigned' , current_user . id , @pull_request & . id ) if @issue . previous_changes [ :assigned_to_id ] . present? && Site . has_notice_menu?
2020-03-09 00:40:16 +08:00
end
end
end
2020-06-12 18:22:42 +08:00
def refuse_merge
2020-04-13 17:46:25 +08:00
ActiveRecord :: Base . transaction do
begin
2021-01-12 15:45:18 +08:00
colsed = PullRequests :: CloseService . call ( @owner , @repository , @pull_request , current_user )
2023-03-02 13:49:50 +08:00
# author: zxh
# 调用上链API
2023-03-07 15:38:54 +08:00
push_activity_2_blockchain ( " pull_request_refuse " , @pull_request ) if Site . has_blockchain? && @project . use_blockchain
2023-03-02 13:49:50 +08:00
if colsed === true
2021-10-15 14:36:50 +08:00
@pull_request . project_trends . create! ( user : current_user , project : @project , action_type : ProjectTrend :: CLOSE )
2022-11-11 14:13:38 +08:00
# 合并请求下issue处理为关闭
@issue & . update_attributes! ( { status_id : 5 } )
2021-10-13 15:50:51 +08:00
SendTemplateMessageJob . perform_later ( 'PullRequestClosed' , current_user . id , @pull_request . id ) if Site . has_notice_menu?
2023-03-02 13:49:50 +08:00
normal_status ( 1 , " 已拒绝 " )
2021-09-15 18:55:58 +08:00
else
normal_status ( - 1 , '合并失败' )
end
2020-04-13 17:46:25 +08:00
rescue = > e
normal_status ( - 1 , e . message )
raise ActiveRecord :: Rollback
end
end
end
2020-06-29 17:06:46 +08:00
def create_merge_infos
get_relatived
end
2020-03-09 00:40:16 +08:00
def show
2023-05-30 14:46:15 +08:00
tip_exception ( 403 , " 你没有权限访问 " ) if @project . pr_view_admin? && ! @project . manager? ( current_user )
2020-03-09 00:40:16 +08:00
@issue_user = @issue . user
@issue_assign_to = @issue . get_assign_user
2021-05-21 11:39:50 +08:00
@gitea_pull = Gitea :: PullRequest :: GetService . call ( @owner . login ,
2023-03-27 14:16:06 +08:00
@repository . identifier , @pull_request . gitea_number , @owner & . gitea_token )
2022-07-25 18:23:06 +08:00
@last_review = @pull_request . reviews . take
2020-03-09 00:40:16 +08:00
end
def pr_merge
2021-04-29 18:48:54 +08:00
return render_forbidden ( " 你没有权限操作. " ) unless @project . operator? ( current_user )
2024-03-16 16:03:31 +08:00
return normal_status ( - 1 , " 该分支存在冲突,无法自动合并. " ) unless @pull_request . conflict_files . blank?
2020-07-03 16:23:06 +08:00
2020-03-09 00:40:16 +08:00
if params [ :do ] . blank?
normal_status ( - 1 , " 请选择合并方式 " )
else
ActiveRecord :: Base . transaction do
begin
2021-07-12 12:02:34 +08:00
@gitea_pull = Gitea :: PullRequest :: GetService . call ( @owner . login , @repository . identifier , @pull_request . gitea_number , current_user & . gitea_token )
2021-01-12 15:45:18 +08:00
2021-07-12 12:02:34 +08:00
if @gitea_pull [ " merged_by " ] . present?
success_condition = true
else
result = PullRequests :: MergeService . call ( @owner , @repository , @pull_request , current_user , params )
success_condition = result . status == 200
end
if success_condition && @pull_request . merge!
2021-10-15 14:36:50 +08:00
# @pull_request.project_trend_status!
@pull_request . project_trends . create! ( user : current_user , project : @project , action_type : ProjectTrend :: MERGE )
2020-04-28 10:41:20 +08:00
@issue & . custom_journal_detail ( " merge " , " " , " 该合并请求已被合并 " , current_user & . id )
2023-03-02 13:49:50 +08:00
# author: zxh
# 调用上链API
2023-03-07 15:38:54 +08:00
push_activity_2_blockchain ( " pull_request_merge " , @pull_request ) if Site . has_blockchain? && @project . use_blockchain
2023-03-02 13:49:50 +08:00
# 查看是否fix了相关issue, 如果fix就转账
2023-03-02 15:55:46 +08:00
@pull_request . attached_issues . each do | issue |
2023-03-09 18:37:08 +08:00
next if PullAttachedIssue . exists? ( issue_id : issue . id , fixed : true )
2023-03-02 15:55:46 +08:00
token_num = issue . blockchain_token_num
token_num = token_num . nil? ? 0 : token_num
author_id = @pull_request . user_id
if token_num > 0
2023-03-09 17:03:15 +08:00
Blockchain :: FixIssue . call ( { user_id : author_id . to_s , project_id : @project . id . to_s , token_num : token_num } ) if Site . has_blockchain? && @project . use_blockchain
2023-03-09 18:11:10 +08:00
PullAttachedIssue . find_by ( issue_id : issue . id , pull_request_id : @pull_request . id ) . update ( fixed : true )
2023-03-02 13:49:50 +08:00
end
2023-03-02 15:55:46 +08:00
# update issue to state 5
2023-03-10 11:50:47 +08:00
issue . issue_participants . create! ( { participant_type : " edited " , participant_id : current_user . id } ) unless issue . issue_participants . exists? ( participant_type : " edited " , participant_id : current_user . id )
journal = issue . journals . create! ( { user_id : current_user . id } )
journal . journal_details . create! ( { property : " attr " , prop_key : " status_id " , old_value : issue . status_id , value : 5 } )
2023-03-02 15:55:46 +08:00
issue . update ( status_id : 5 )
2023-03-02 13:49:50 +08:00
end
2022-11-11 14:13:38 +08:00
# 合并请求下issue处理为关闭
@issue & . update_attributes! ( { status_id : 5 } )
2021-10-13 15:50:51 +08:00
SendTemplateMessageJob . perform_later ( 'PullRequestMerged' , current_user . id , @pull_request . id ) if Site . has_notice_menu?
2020-03-09 00:40:16 +08:00
normal_status ( 1 , " 合并成功 " )
else
2021-04-30 15:36:14 +08:00
normal_status ( - 1 , result . message )
2020-03-09 00:40:16 +08:00
end
rescue = > e
2023-07-11 15:16:46 +08:00
logger_error ( e )
2020-03-09 00:40:16 +08:00
normal_status ( - 1 , e . message )
raise ActiveRecord :: Rollback
end
end
end
end
def check_can_merge
target_head = params [ :head ] #源分支
target_base = params [ :base ] #目标分支
2021-11-25 11:19:50 +08:00
is_original = params [ :is_original ] || false
2020-03-09 00:40:16 +08:00
if target_head . blank? || target_base . blank?
2020-06-12 18:22:42 +08:00
normal_status ( - 2 , " 请选择分支 " )
2020-06-30 09:44:28 +08:00
elsif target_head === target_base && ! is_original
2020-06-12 18:22:42 +08:00
normal_status ( - 2 , " 分支内容相同,无需创建合并请求 " )
2020-03-09 00:40:16 +08:00
else
2020-11-06 15:21:27 +08:00
can_merge = @project & . pull_requests . where ( head : target_head , base : target_base , status : 0 , is_original : is_original , fork_project_id : params [ :fork_project_id ] )
2020-03-09 00:40:16 +08:00
if can_merge . present?
render json : {
status : - 2 ,
2021-10-11 18:10:28 +08:00
message : " 在这些分支之间的合并请求已存在:<a href='/ #{ @owner . login } / #{ @project . identifier } /pulls/ #{ can_merge . first . id } ''> #{ can_merge . first . try ( :title ) } </a> " ,
2020-03-09 00:40:16 +08:00
}
else
normal_status ( 0 , " 可以合并 " )
end
end
end
2020-11-03 18:37:47 +08:00
def files
2023-03-27 14:16:06 +08:00
@files_result = Gitea :: PullRequest :: FilesService . call ( @owner . login , @project . identifier , @pull_request . gitea_number , @owner & . gitea_token )
2020-11-03 18:37:47 +08:00
# render json: @files_result
end
def commits
2023-03-27 14:16:06 +08:00
@commits_result = Gitea :: PullRequest :: CommitsService . call ( @owner . login , @project . identifier , @pull_request . gitea_number , @owner & . gitea_token )
2020-11-03 18:37:47 +08:00
# render json: @commits_result
2020-08-15 13:30:44 +08:00
end
2020-08-15 13:21:33 +08:00
2020-11-03 18:37:47 +08:00
private
def load_pull_request
2021-11-25 15:08:59 +08:00
@pull_request = @project . pull_requests . where ( gitea_number : params [ :id ] ) . where . not ( id : params [ :id ] ) . take || PullRequest . find_by_id ( params [ :id ] )
2020-03-09 00:40:16 +08:00
end
def find_pull_request
2021-11-25 15:08:59 +08:00
@pull_request = @project . pull_requests . where ( gitea_number : params [ :id ] ) . where . not ( id : params [ :id ] ) . take || PullRequest . find_by_id ( params [ :id ] )
2020-03-09 00:40:16 +08:00
@issue = @pull_request & . issue
if @pull_request . blank?
normal_status ( - 1 , " 合并请求不存在 " )
elsif @issue . present? && @issue . is_lock && ! ( @project . member? ( current_user ) || current_user . admin? )
normal_status ( - 1 , " 您没有权限 " )
end
end
2020-06-12 18:22:42 +08:00
2020-06-30 15:00:41 +08:00
def get_relatived
2020-06-12 18:22:42 +08:00
@project_tags = @project . issue_tags & . select ( :id , :name , :color ) . as_json
2022-10-18 13:43:16 +08:00
@project_versions = @project . versions . opening & . select ( :id , :name , :status ) . as_json
2021-04-29 10:23:16 +08:00
@project_members = @project . all_developers
2020-06-12 18:22:42 +08:00
@project_priories = IssuePriority & . select ( :id , :name , :position ) . as_json
end
2020-06-30 15:00:41 +08:00
def merge_params
2020-06-12 18:22:42 +08:00
@local_params = {
title : params [ :title ] , #标题
body : params [ :body ] , #内容
head : params [ :head ] , #源分支
base : params [ :base ] , #目标分支
2023-04-11 10:12:24 +08:00
# milestone: 0, #里程碑,未与本地的里程碑关联
2020-06-12 18:22:42 +08:00
}
2022-01-14 10:55:01 +08:00
assignee_login = User . find_by_id ( params [ :assigned_to_id ] ) & . login
2023-04-11 10:12:24 +08:00
@requests_params = @local_params . merge ( { assignees : [ assignee_login . to_s ] . reject! ( & :empty? ) } )
2020-06-12 18:22:42 +08:00
@issue_params = {
author_id : current_user . id ,
project_id : @project . id ,
subject : params [ :title ] ,
description : params [ :body ] ,
assigned_to_id : params [ :assigned_to_id ] ,
fixed_version_id : params [ :fixed_version_id ] ,
issue_tags_value : params [ :issue_tag_ids ] . present? ? params [ :issue_tag_ids ] . join ( " , " ) : " " ,
2021-11-29 11:05:33 +08:00
priority_id : params [ :priority_id ] ,
2020-06-12 18:22:42 +08:00
issue_classify : " pull_request " ,
issue_type : params [ :issue_type ] || " 1 " ,
tracker_id : 2 ,
status_id : 1 ,
}
end
2021-09-03 09:37:30 +08:00
def check_menu_authorize
return render_not_found unless @project . has_menu_permission ( " pulls " )
end
2020-06-30 15:00:41 +08:00
end