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 15 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
​
​
​
​
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  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]
  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. @project_menu_type = 6
  151. @type = params[:type]
  152. @request = @g.merge_request(@project.gpid, params[:id])
  153. @commits = @g.merge_request_commits(@project.gpid, params[:id].to_i)
  154. @commits_count = @commits.count
  155. # @commits_day = @commits.chunk
  156. @changes = @g.merge_request_changes(@project.gpid, params[:id]).try(:changes)
  157. @changes_count = @changes.count
  158. @comments = @g.merge_request_comments(@project.gpid, params[:id]).reverse
  159. @comments_count = @comments.count
  160. @limit = 10
  161. @is_remote = true
  162. @count = @comments_count
  163. @pages = Paginator.new @count, @limit, params['page'] || 1
  164. @offset ||= @pages.offset
  165. @comments = paginateHelper @comments, 10
  166. end
  167. # Accept a merge request.
  168. # If merge success you get 200 OK.
  169. # Accept a merge request.
  170. #
  171. # @example
  172. # Gitlab.accept_pull_rquest(5, 1)
  173. #
  174. # @param [Integer] project The ID of a project.
  175. # @param [Integer] id The ID of a merge request.
  176. # @return [Gitlab::ObjectifiedHash]
  177. def accept_pull_request
  178. begin
  179. status = @g.accept_merge_rquest(@project.gpid, params[:id], User.current.gid)
  180. # 接受后,给用户发消息
  181. send_message_to_author(@project.id, status.author.try(:username), params[:id], 2)
  182. respond_to do |format|
  183. format.js{redirect_to project_pull_request_path(status.id, :project_id => @project.id)}
  184. end
  185. rescue Exception => e
  186. @message = e.message
  187. end
  188. end
  189. # Updates a merge request.
  190. #
  191. # @example
  192. # Gitlab.update_merge_request(5, 42, :title => 'New title')
  193. #
  194. # @param [Integer] project The ID of a project.
  195. # @param [Integer] id The ID of a merge request.
  196. # @param [Hash] options A customizable set of options.
  197. # @option options [String] :title The title of a merge request.
  198. # @option options [String] :source_branch The source branch name.
  199. # @option options [String] :target_branch The target branch name.
  200. # @option options [Integer] :assignee_id The ID of a user to assign merge request.
  201. # @option options [String] :state_event New state (close|reopen|merge).
  202. # @return [Gitlab::ObjectifiedHash] Information about updated merge request.
  203. def update_pull_request
  204. begin
  205. request = @g.update_merge_request(@project.gpid, params[:id], User.current.gid, :state_event => params[:state])
  206. user = User.find_by_login(request.author.try(:username))
  207. status = params[:state] == "close" ? 4 : 3
  208. send_message_to_manager(@project.id, params[:id], status)
  209. if is_project_manager?(User.current.id, @project.id)
  210. send_message_to_author(@project.id, user.login, request.id, status)
  211. end
  212. respond_to do |format|
  213. format.html{redirect_to project_pull_request_path(params[:id], :project_id => @project.id)}
  214. end
  215. rescue Exception => e
  216. @message = e.message
  217. end
  218. end
  219. # Creates a merge request.
  220. #
  221. # @example
  222. # Gitlab.create_merge_request(5, 'New merge request',
  223. # :source_branch => 'source_branch', :target_branch => 'target_branch')
  224. # Gitlab.create_merge_request(5, 'New merge request',
  225. # :source_branch => 'source_branch', :target_branch => 'target_branch', :assignee_id => 42)
  226. def create_pull_request_comment
  227. content = params[:pull_request_comment]
  228. begin
  229. @comments = @g.create_merge_request_comment(@project.gpid, params[:id], content, User.current.gid)
  230. respond_to do |format|
  231. format.js{redirect_to project_pull_request_path(params[:id], :project_id => @project.id)}
  232. end
  233. rescue Exception => e
  234. @message = e.message
  235. end
  236. end
  237. # Gets the comments on a merge request.
  238. #
  239. # @example
  240. # Gitlab.merge_request_comments(5, 1)
  241. def pull_request_comments
  242. begin
  243. @comments = @g.merge_request_comments(@project.gpid, params[:id]).reverse
  244. @comments_count = @comments.count
  245. @limit = 10
  246. @is_remote = true
  247. @count = @comments_count
  248. @pages = Paginator.new @count, @limit, params['page'] || 1
  249. @offset ||= @pages.offset
  250. @comments = paginateHelper @comments, 10
  251. rescue Exception => e
  252. @message = e.message
  253. end
  254. end
  255. # Get a list of merge request commits.
  256. # Parameters:
  257. # id (required) - The ID of a project
  258. # merge_request_id (required) - The ID of MR
  259. def pull_request_commits
  260. begin
  261. @type = params[:type]
  262. @commits = @g.merge_request_commits(@project.gpid, params[:id])
  263. @commits_count = @commits.count
  264. @limit = 10
  265. @is_remote = true
  266. @count = @commits_count
  267. @pages = Paginator.new @count, @limit, params['page'] || 1
  268. @offset ||= @pages.offset
  269. @commits = paginateHelper @commits, 10
  270. rescue Exception => e
  271. @message = e.message
  272. end
  273. end
  274. # 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.
  275. # Parameters:
  276. # id (required) - The ID of a project
  277. # merge_request_id (required) - The ID of MR
  278. def pull_request_changes
  279. @type = params[:type]
  280. @changes = @g.merge_request_changes(@project.gpid, params[:id]).try(:changes)
  281. @changes_count = @changes.count
  282. @limit = 10
  283. @is_remote = true
  284. @count = @changes_count
  285. @pages = Paginator.new @count, @limit, params['page'] || 1
  286. @offset ||= @pages.offset
  287. @changes = paginateHelper @changes, 10
  288. end
  289. private
  290. # post 相关操作权限控制
  291. # 项目管理员可操作
  292. def manager_allowed
  293. unless is_project_manager?(User.current.id, @project.id)
  294. return render_403
  295. end
  296. end
  297. # 项目成员可操作
  298. def member_allowed
  299. unless User.current.member_of?(@project)
  300. return render_403
  301. end
  302. end
  303. def send_message_to_manager project_id, pull_request_id, status
  304. project = Project.find(project_id)
  305. project.members.each do |member|
  306. if is_project_manager?(member.user_id, project_id) && User.current.id != member.user_id
  307. add_message(member.user_id, project_id, pull_request_id, status)
  308. end
  309. end
  310. end
  311. def send_message_to_author(project_id, user_login, request_id, status)
  312. user = get_user_by_login_and(user_login)
  313. if user.id != User.current.id
  314. add_message(user.id, project_id, request_id, status)
  315. end
  316. end
  317. def add_message(user_id, project_id, pull_request_id, status)
  318. ForgeMessage.create(:user_id => user_id,
  319. :project_id => project_id,
  320. :forge_message_id => pull_request_id,
  321. :forge_message_type => "PullRequest",
  322. :viewed => true,
  323. :status => status,
  324. :operate_user_id => User.current.id,
  325. )
  326. end
  327. def authorize_logged
  328. if !User.current.logged?
  329. redirect_to signin_path
  330. return
  331. end
  332. end
  333. def connect_gitlab
  334. @g = Gitlab.client
  335. end
  336. def find_project_and_repository
  337. @project = Project.find(params[:project_id])
  338. render_404 if @project.gpid.blank?
  339. @repository = Repository.where(:project_id => @project.id, :type => "Repository::Gitlab").first
  340. rescue ActiveRecord::RecordNotFound
  341. render_404
  342. end
  343. end

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