You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

pull_requests_controller.rb 17 kB

10 years ago
10 years ago
​
10 years ago
10 years ago
10 years ago
​
10 years ago
10 years ago
10 years ago
10 years ago
​
​
10 years ago
​
​
​
​
​
​
​
​
​
10 years ago
​
10 years ago
​
​
​
​
10 years ago
​
10 years ago
​
​
10 years ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
​
​
​
​
​
​
​
10 years ago
​
10 years ago
10 years ago
10 years ago
​
​
​
10 years ago
10 years ago
​
​
​
10 years ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
10 years ago
​
​
​
​
​
​
10 years ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
10 years ago
​
​
​
​
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. # encoding: utf-8
  2. # 如果你对改模块任何功能不清楚,请不要随便改
  3. # @Hjqreturn
  4. class PullRequestsController < ApplicationController
  5. before_filter :authorize_logged
  6. before_filter :find_project_and_repository
  7. 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]
  8. before_filter :member_allowed, :only => [:new, :create, :create_pull_request_comment]
  9. before_filter :manager_allowed, :only => [:accept_pull_request]
  10. layout "base_projects"
  11. include PullRequestsHelper
  12. include ApplicationHelper
  13. require 'ostruct'
  14. # 返回json格式
  15. def index
  16. # project_menu_type 为了控制base顶部导航
  17. @project_menu_type = 6
  18. # 不符合pullrequest条件的给出提示
  19. @allow_to_pull_request = allow_pull_request(@project) > 0
  20. type = params[:type]
  21. merge_requests = @g.merge_requests(@project.gpid)
  22. merge_requests_count = merge_requests.count
  23. case type
  24. when nil, "1"
  25. @requests = merge_requests.select{|request| request.state == "opened" || request.state == "reopened"}
  26. # 更新统计数字
  27. project_score = @project.project_score.update_column(:pull_request_num, merge_requests_count)
  28. when "2"
  29. @requests = merge_requests.select{|request| request.state == "merged"}
  30. when "3"
  31. @requests = merge_requests.select{|request| request.state == "closed"}
  32. end
  33. @requests_opened_count = @requests.count
  34. @requests_merged_count = merge_requests.select{|request| request.state == "merged"}.count
  35. @requests_closed_count = merge_requests.select{|request| request.state == "closed"}.count
  36. @limit = 20
  37. @is_remote = true
  38. @count = type_count(type, @requests_opened_count, @requests_merged_count, @requests_closed_count)
  39. @pages = Paginator.new @count, @limit, params['page'] || 1
  40. @offset ||= @pages.offset
  41. @requests = paginateHelper @requests, 20
  42. respond_to do |format|
  43. format.html
  44. format.js
  45. end
  46. end
  47. # 主要取源项目和目标项目分支及标识(用户名/版本库名)
  48. # @tip 为空的时候表明发送的pr请求有改动,为1的时候源分支和目标分支没有改动,则不能成功创建
  49. def new
  50. # project_menu_type 为了控制base顶部导航
  51. @project_menu_type = 6
  52. @tip = params[:show_tip]
  53. identifier = get_rep_identifier_by_project @project
  54. @source_project_name = "#{get_user_name(@project.user_id)}/#{identifier}"
  55. @source_rev = @g.branches(@project.gpid).map{|b| b.name}
  56. # 获取forked源项目信息
  57. if @project.forked_from_project_id
  58. @forked_project = Project.find(@project.forked_from_project_id)
  59. identifier = get_rep_identifier_by_project @forked_project
  60. @forked_project_name = "#{get_user_name(@forked_project.user_id)}/#{identifier}"
  61. @forked_rev = @g.branches(@forked_project.gpid).map{|b| b.name}
  62. end
  63. end
  64. # Creates a merge request.
  65. # 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.
  66. #
  67. # @example
  68. # Gitlab.create_merge_request(5, 'New merge request',
  69. # :source_branch => 'source_branch', :target_branch => 'target_branch')
  70. # Gitlab.create_merge_request(5, 'New merge request',
  71. # :source_branch => 'source_branch', :target_branch => 'target_branch', :assignee_id => 42)
  72. #
  73. # @param [Integer] project The ID of a project.
  74. # @param [String] title The title of a merge request.
  75. # @param [Hash] options A customizable set of options.
  76. # @option options [String] :source_branch (required) The source branch name.
  77. # @option options [String] :target_branch (required) The target branch name.
  78. # @option options [Integer] :assignee_id (optional) The ID of a user to assign merge request.
  79. # @return [Gitlab::ObjectifiedHash] Information about created merge request.
  80. def create
  81. title = params[:title]
  82. description = params[:description]
  83. source_branch = params[:source_branch]
  84. target_branch = params[:target_branch]
  85. target_project_id = params[:target_project_id]
  86. begin
  87. # 如果分支有改动
  88. if compare_pull_request(source_branch, target_project_id, target_branch)
  89. # 如果传送了目标项目ID即向fork源项目发送请求
  90. # if params[:forked_project_id] && params[:source_project] == "forked_project_name"
  91. if !params[:target_project_id].blank? && params[:target_project_id].to_i != @project.id
  92. target_project_id = params[:forked_project_id].to_i
  93. 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)
  94. @fork_project_name = Project.find(params[:target_project_id]).try(:name)
  95. @fork_pr_message = true if @fork_project_name
  96. # 向管理员发送消息
  97. send_message_to_manager(params[:target_project_id].to_i, request.id, 1)
  98. PullRequest.create(:pull_request_id => request.id, :user_id => User.current.id, :status => 1, :project_id => target_project_id, :title => title)
  99. else
  100. @project_member = Member.where(:project_id => @project.id)
  101. request = @g.create_merge_request(@project.gpid, title, User.current.gid, :description => description, :source_branch => source_branch, :target_branch => target_branch)
  102. # 发送消息
  103. send_message_to_manager(@project.id, request.id, 1)
  104. # 创建Trustie数据
  105. PullRequest.create(:pull_request_id => request.id, :user_id => User.current.id, :status => 1, :project_id => @project.id, :title => title)
  106. respond_to do |format|
  107. format.js{redirect_to project_pull_request_path(request.id, :project_id => @project.id)}
  108. end
  109. end
  110. else
  111. tip = 1
  112. respond_to do |format|
  113. format.js{redirect_to new_project_pull_request_path(:show_tip => tip)}
  114. end
  115. end
  116. rescue Gitlab::Error::Forbidden => e
  117. @message = l(:label_pull_request_forbidden)
  118. rescue Gitlab::Error::Conflict => e
  119. @message = l(:label_pull_request_conflic)
  120. rescue Gitlab::Error::NotFound => e
  121. @message = l(:label_pull_request_notfound)
  122. rescue Exception => e
  123. puts e
  124. end
  125. end
  126. # Compare branch for MR
  127. # 判断源分支和目标分支是否有改动
  128. # status 为true 表示有改动; false:便是没有改动
  129. def compare_pull_request source_branch, target_project, target_branch
  130. user_name_source = @project.owner.try(:login)
  131. identifier = @repository.identifier.downcase
  132. git_source_tree = '--git-dir=/home/git/repositories/' + user_name_source + '/' + identifier + '.git'
  133. if target_project
  134. forked_source_project = Project.find(target_project)
  135. user_name_target = forked_source_project.owner.try(:login)
  136. git_target_tree = '--git-dir=/home/git/repositories/' + user_name_target + '/' + identifier + '.git'
  137. git_sourse_commit_id = @g.get_branch_commit_id(@project.gpid, git_source_tree, source_branch)
  138. git_target_commit_id = @g.get_branch_commit_id(forked_source_project.gpid, git_target_tree, target_branch)
  139. else
  140. git_sourse_commit_id = @g.get_branch_commit_id(@project.gpid, git_source_tree, source_branch)
  141. git_target_commit_id = @g.get_branch_commit_id(@project.gpid, git_source_tree, target_branch)
  142. end
  143. status = (git_sourse_commit_id.try(:commit_id) == git_target_commit_id.try(:commit_id) ? false : true)
  144. end
  145. # @project_menu_type 为了控制base顶部导航
  146. # merge_when_succeeds
  147. def show
  148. # compare_pull_request source_project, source_branch, target_project, target_branch
  149. # compare_pull_request
  150. # 如何从个人主页点击进入,则将该消息设为“已读”
  151. ForgeMessage.where(:forge_message_id => params[:id], :forge_message_type => "PullRequest", :user_id => User.current.id, :viewed => false).update_all(:viewed => true)
  152. @project_menu_type = 6
  153. @type = params[:type]
  154. @request = @g.merge_request(@project.gpid, params[:id])
  155. @commits = @g.merge_request_commits(@project.gpid, params[:id].to_i)
  156. @commits_count = @commits.count
  157. # @commits_day = @commits.chunk
  158. @changes = @g.merge_request_changes(@project.gpid, params[:id]).try(:changes)
  159. @changes_count = @changes.count
  160. @comments = @g.merge_request_comments(@project.gpid, params[:id]).reverse
  161. @comments_count = @comments.count
  162. @limit = 10
  163. @is_remote = true
  164. @count = @comments_count
  165. @pages = Paginator.new @count, @limit, params['page'] || 1
  166. @offset ||= @pages.offset
  167. @comments = paginateHelper @comments, 10
  168. end
  169. # Accept a merge request.
  170. # If merge success you get 200 OK.
  171. # Accept a merge request.
  172. #
  173. # @example
  174. # Gitlab.accept_pull_rquest(5, 1)
  175. #
  176. # @param [Integer] project The ID of a project.
  177. # @param [Integer] id The ID of a merge request.
  178. # @return [Gitlab::ObjectifiedHash]
  179. def accept_pull_request
  180. begin
  181. @status = @g.accept_merge_rquest(@project.gpid, params[:id], User.current.gid)
  182. user = User.find_by_login(@status.author.try(:username))
  183. # 更新管理员的pullrequest消息
  184. update_pullrequest_message(params[:id].to_i, @project.id, "PullRequest", 2)
  185. # 接受后,给用户发消息
  186. if ForgeMessage.where(:forge_message_id => params[:id].to_i, :project_id => @project.id, :forge_message_type => "PullRequest", :user_id => user.id).count == 0
  187. send_message_to_author(@project.id, @status.author.try(:username), params[:id], 2)
  188. end
  189. respond_to do |format|
  190. format.js{redirect_to project_pull_request_path(@status.id, :project_id => @project.id)}
  191. end
  192. rescue Gitlab::Error::Forbidden => e
  193. @message = l(:label_pull_request_forbidden)
  194. rescue Gitlab::Error::DataNotAccepted => e
  195. @message = l(:label_pull_request_datanotaccepted)
  196. rescue Gitlab::Error::NotFound => e
  197. @message = l(:label_pull_request_notfound)
  198. rescue Exception => e
  199. puts e
  200. end
  201. end
  202. # Updates a merge request.
  203. #
  204. # @example
  205. # Gitlab.update_merge_request(5, 42, :title => 'New title')
  206. #
  207. # @param [Integer] project The ID of a project.
  208. # @param [Integer] id The ID of a merge request.
  209. # @param [Hash] options A customizable set of options.
  210. # @option options [String] :title The title of a merge request.
  211. # @option options [String] :source_branch The source branch name.
  212. # @option options [String] :target_branch The target branch name.
  213. # @option options [Integer] :assignee_id The ID of a user to assign merge request.
  214. # @option options [String] :state_event New state (close|reopen|merge).
  215. # @return [Gitlab::ObjectifiedHash] Information about updated merge request.
  216. def update_pull_request
  217. begin
  218. request = @g.update_merge_request(@project.gpid, params[:id], User.current.gid, :state_event => params[:state])
  219. user = User.find_by_login(request.author.try(:username))
  220. status = params[:state] == "close" ? 4 : 3
  221. #send_message_to_manager(@project.id, params[:id], status)
  222. update_pullrequest_message(request.id, @project.id, "PullRequest", status)
  223. # 给作者发送消息,如何已经发送了消息,则不发
  224. 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
  225. send_message_to_author(@project.id, user.login, request.id, status)
  226. end
  227. respond_to do |format|
  228. format.html{redirect_to project_pull_request_path(params[:id], :project_id => @project.id)}
  229. end
  230. rescue Exception => e
  231. @message = e.message
  232. end
  233. end
  234. # Creates a merge request.
  235. #
  236. # @example
  237. # Gitlab.create_merge_request(5, 'New merge request',
  238. # :source_branch => 'source_branch', :target_branch => 'target_branch')
  239. # Gitlab.create_merge_request(5, 'New merge request',
  240. # :source_branch => 'source_branch', :target_branch => 'target_branch', :assignee_id => 42)
  241. def create_pull_request_comment
  242. content = params[:pull_request_comment]
  243. begin
  244. @comments = @g.create_merge_request_comment(@project.gpid, params[:id], content, User.current.gid)
  245. respond_to do |format|
  246. format.js{redirect_to project_pull_request_path(params[:id], :project_id => @project.id)}
  247. end
  248. rescue Exception => e
  249. @message = e.message
  250. end
  251. end
  252. # Gets the comments on a merge request.
  253. #
  254. # @example
  255. # Gitlab.merge_request_comments(5, 1)
  256. def pull_request_comments
  257. begin
  258. @comments = @g.merge_request_comments(@project.gpid, params[:id]).reverse
  259. @comments_count = @comments.count
  260. @limit = 10
  261. @is_remote = true
  262. @count = @comments_count
  263. @pages = Paginator.new @count, @limit, params['page'] || 1
  264. @offset ||= @pages.offset
  265. @comments = paginateHelper @comments, 10
  266. rescue Exception => e
  267. @message = e.message
  268. end
  269. end
  270. # Get a list of merge request commits.
  271. # Parameters:
  272. # id (required) - The ID of a project
  273. # merge_request_id (required) - The ID of MR
  274. def pull_request_commits
  275. begin
  276. @type = params[:type]
  277. @commits = @g.merge_request_commits(@project.gpid, params[:id])
  278. @commits_count = @commits.count
  279. @limit = 10
  280. @is_remote = true
  281. @count = @commits_count
  282. @pages = Paginator.new @count, @limit, params['page'] || 1
  283. @offset ||= @pages.offset
  284. @commits = paginateHelper @commits, 10
  285. rescue Exception => e
  286. @message = e.message
  287. end
  288. end
  289. # 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.
  290. # Parameters:
  291. # id (required) - The ID of a project
  292. # merge_request_id (required) - The ID of MR
  293. def pull_request_changes
  294. @type = params[:type]
  295. @changes = @g.merge_request_changes(@project.gpid, params[:id]).try(:changes)
  296. @changes_count = @changes.count
  297. @limit = 10
  298. @is_remote = true
  299. @count = @changes_count
  300. @pages = Paginator.new @count, @limit, params['page'] || 1
  301. @offset ||= @pages.offset
  302. @changes = paginateHelper @changes, 10
  303. end
  304. private
  305. # post 相关操作权限控制
  306. # 项目管理员可操作
  307. def manager_allowed
  308. unless is_project_manager?(User.current.id, @project.id)
  309. return render_403
  310. end
  311. end
  312. # 项目成员可操作
  313. def member_allowed
  314. unless User.current.member_of?(@project)
  315. return render_403
  316. end
  317. end
  318. def send_message user_id, project_id, pull_request_id
  319. ForgeMessage.create(:user_id => user_id, :project_id => project_id,
  320. :forge_message_id => pull_request_id, :forge_message_type => "PullRequest", :viewed => true)
  321. end
  322. def send_message_to_manager project_id, pull_request_id, status
  323. project = Project.find(project_id)
  324. project.members.each do |member|
  325. if is_project_manager?(member.user_id, project_id) && User.current.id != member.user_id
  326. add_message(member.user_id, project_id, pull_request_id, status)
  327. end
  328. end
  329. end
  330. def send_message_to_author(project_id, user_login, request_id, status)
  331. user = get_user_by_login_and(user_login)
  332. if user.id != User.current.id
  333. add_message(user.id, project_id, request_id, status)
  334. end
  335. end
  336. def add_message(user_id, project_id, pull_request_id, status)
  337. ForgeMessage.create(:user_id => user_id,
  338. :project_id => project_id,
  339. :forge_message_id => pull_request_id,
  340. :forge_message_type => "PullRequest",
  341. :viewed => false,
  342. :status => status,
  343. :operate_user_id => User.current.id,
  344. )
  345. end
  346. def update_pullrequest_message forge_message_id, project_id, forge_message_type, status
  347. # 更新这条pullrequest消息所有相关的信息
  348. 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)
  349. # 更新自己的消息为已读
  350. 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)
  351. # 更新pullrequest的status字段
  352. PullRequest.where(:pull_request_id => forge_message_id).update_all(:status => status)
  353. end
  354. def authorize_logged
  355. if !User.current.logged?
  356. redirect_to signin_path
  357. return
  358. end
  359. end
  360. def connect_gitlab
  361. @g = Gitlab.client
  362. end
  363. def find_project_and_repository
  364. @project = Project.find(params[:project_id])
  365. render_404 if @project.gpid.blank?
  366. @repository = Repository.where(:project_id => @project.id, :type => "Repository::Gitlab").first
  367. rescue ActiveRecord::RecordNotFound
  368. render_404
  369. end
  370. end

软件技术创新是当今国家整体创新能力的重要基础和发展引擎。近年来,大众参与的软件创新与创业活动已经成为网络时代软件开发和应用的新形态,正在快速改变着全球软件创新模式和软件产业格局。 ...