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 22 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
​
​
​
​
​
​
​
8 years ago
​
​
10 years ago
​
10 years ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
10 years ago
​
​
​
​
​
​
10 years ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
10 years ago
​
​
​
​
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  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. require 'nokogiri'
  15. require 'json'
  16. require 'open-uri'
  17. require 'uri'
  18. # 返回json格式
  19. def index
  20. # project_menu_type 为了控制base顶部导航
  21. @project_menu_type = 6
  22. # 不符合pullrequest条件的给出提示
  23. @allow_to_pull_request = allow_pull_request(@project) > 0
  24. type = params[:type]
  25. merge_requests = @g.merge_requests(@project.gpid)
  26. merge_requests_count = merge_requests.count
  27. case type
  28. when nil, "1"
  29. @requests = merge_requests.select{|request| request.state == "opened" || request.state == "reopened"}
  30. # 更新统计数字
  31. project_score = @project.project_score.update_column(:pull_request_num, merge_requests_count)
  32. when "2"
  33. @requests = merge_requests.select{|request| request.state == "merged"}
  34. when "3"
  35. @requests = merge_requests.select{|request| request.state == "closed"}
  36. end
  37. @requests_opened_count = @requests.count
  38. @requests_merged_count = merge_requests.select{|request| request.state == "merged"}.count
  39. @requests_closed_count = merge_requests.select{|request| request.state == "closed"}.count
  40. @limit = 20
  41. @is_remote = true
  42. @count = type_count(type, @requests_opened_count, @requests_merged_count, @requests_closed_count)
  43. @pages = Paginator.new @count, @limit, params['page'] || 1
  44. @offset ||= @pages.offset
  45. @requests = paginateHelper @requests, 20
  46. respond_to do |format|
  47. format.html
  48. format.js
  49. end
  50. end
  51. # 主要取源项目和目标项目分支及标识(用户名/版本库名)
  52. # @tip 为空的时候表明发送的pr请求有改动,为1的时候源分支和目标分支没有改动,则不能成功创建
  53. def new
  54. # project_menu_type 为了控制base顶部导航
  55. @project_menu_type = 6
  56. @tip = params[:show_tip]
  57. identifier = get_rep_identifier_by_project @project
  58. @source_project_name = "#{get_user_name(@project.user_id)}/#{identifier}"
  59. @source_rev = @g.branches(@project.gpid).map{|b| b.name}
  60. # 获取forked源项目信息
  61. if @project.forked_from_project_id
  62. @forked_project = Project.find(@project.forked_from_project_id)
  63. identifier = get_rep_identifier_by_project @forked_project
  64. @forked_project_name = "#{get_user_name(@forked_project.user_id)}/#{identifier}"
  65. @forked_rev = @g.branches(@forked_project.gpid).map{|b| b.name}
  66. end
  67. end
  68. # Creates a merge request.
  69. # 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.
  70. #
  71. # @example
  72. # Gitlab.create_merge_request(5, 'New merge request',
  73. # :source_branch => 'source_branch', :target_branch => 'target_branch')
  74. # Gitlab.create_merge_request(5, 'New merge request',
  75. # :source_branch => 'source_branch', :target_branch => 'target_branch', :assignee_id => 42)
  76. #
  77. # @param [Integer] project The ID of a project.
  78. # @param [String] title The title of a merge request.
  79. # @param [Hash] options A customizable set of options.
  80. # @option options [String] :source_branch (required) The source branch name.
  81. # @option options [String] :target_branch (required) The target branch name.
  82. # @option options [Integer] :assignee_id (optional) The ID of a user to assign merge request.
  83. # @return [Gitlab::ObjectifiedHash] Information about created merge request.
  84. def create
  85. title = params[:title]
  86. description = params[:description]
  87. source_branch = params[:source_branch]
  88. target_branch = params[:target_branch]
  89. target_project_id = params[:target_project_id]
  90. # begin
  91. @gitlab_address = Redmine::Configuration['gitlab_address']
  92. identifier = @project.repository.try(:identifier)
  93. logger.info("1111111111111111#{identifier}")
  94. git_url = @gitlab_address.to_s+"/"+@project.owner.to_s+"/"+ identifier + "."+"git"
  95. job_name = "pr-" + "#{Time.now.to_i}"
  96. # 如果分支有改动
  97. if compare_pull_request(source_branch, target_project_id, target_branch)
  98. logger.info("2222222222222222222222")
  99. # 自动生成配置Jenkinsjob,在merge事件的时候触发jenkins、sonar
  100. # merge发送的时候还没有接收,所以分析对象应该源项目
  101. language = swith_language_type(@project.language)
  102. # exec_jenkins(source_branch, @project.gpid, git_url, job_name, language)
  103. logger.info("33333333333333333333")
  104. qa = QualityAnalysis.create(:project_id => @project.id, :author_login => User.current.login, :sonar_version => 1, :path => "./",
  105. :branch => source_branch, :language => "java", :sonar_name => "#{job_name}")
  106. logger.info("4444444444444444444444444")
  107. # 如果传送了目标项目ID即向fork源项目发送请求
  108. # if params[:forked_project_id] && params[:source_project] == "forked_project_name"
  109. if !params[:target_project_id].blank? && params[:target_project_id].to_i != @project.id
  110. target_project_id = params[:forked_project_id].to_i
  111. 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)
  112. @fork_project_name = Project.find(params[:target_project_id]).try(:name)
  113. @fork_pr_message = true if @fork_project_name
  114. # 向管理员发送消息
  115. send_message_to_manager(params[:target_project_id].to_i, request.id, 1)
  116. pr = PullRequest.create(:pull_request_id => request.id, :user_id => User.current.id, :status => 1, :project_id => target_project_id, :title => title)
  117. else
  118. @project_member = Member.where(:project_id => @project.id)
  119. request = @g.create_merge_request(@project.gpid, title, User.current.gid, :description => description, :source_branch => source_branch, :target_branch => target_branch)
  120. # 发送消息
  121. send_message_to_manager(@project.id, request.id, 1)
  122. # 创建Trustie数据
  123. pr = PullRequest.create(:pull_request_id => request.id, :user_id => User.current.id, :status => 1, :project_id => @project.id, :title => title)
  124. respond_to do |format|
  125. format.js{redirect_to project_pull_request_path(request.id, :project_id => @project.id)}
  126. end
  127. end
  128. # 关联pr和qa
  129. qa.update_attribute(:pull_request_id, request.try(:id))
  130. else
  131. tip = 1
  132. respond_to do |format|
  133. format.js{redirect_to new_project_pull_request_path(:show_tip => tip)}
  134. end
  135. end
  136. # rescue Exception => e
  137. # logger.info("create PR failed ####{e}")
  138. # end
  139. end
  140. def exec_jenkins branch, gpid, git_url, job_name, language
  141. # 发送PR之前先发送创建Jenkins Job、gitlab hook,调用sonar自动分析代码
  142. logger.info("5555555555555555#{branch}, git_url#{git_url}, job_name #{job_name}")
  143. @jenkins_address = Redmine::Configuration['jenkins_address']
  144. jenkins_username = Redmine::Configuration['jenkins_username']
  145. jenkins_password = Redmine::Configuration['jenkins_password']
  146. # connect jenkins
  147. @client_jenkins = JenkinsApi::Client.new(:server_url => @jenkins_address, :username => jenkins_username, :password => jenkins_password)
  148. @g = Gitlab.client
  149. language = language.present? ? language : "java"
  150. path = "./"
  151. # qa = QualityAnalysis.where(:project_id => @project.id, :author_login => user_name).first
  152. version = 1
  153. if language == "java"
  154. properties = "sonar.projectKey=#{job_name}
  155. sonar.projectName=#{job_name}
  156. sonar.projectVersion=#{version}
  157. sonar.sources=#{path}
  158. sonar.language=#{language.downcase}
  159. sonar.sourceEncoding=utf-8
  160. sonar.java.binaries=./"
  161. else
  162. properties = "sonar.projectKey=#{job_name}
  163. sonar.projectName=#{job_name}
  164. sonar.projectVersion=#{version}
  165. sonar.sources=#{path}
  166. sonar.language=#{language.downcase}
  167. sonar.sourceEncoding=utf-8"
  168. end
  169. # 替换配置文件
  170. @doc = Nokogiri::XML(File.open(File.join(Rails.root, 'tmp', 'config.xml')))
  171. @doc.at_xpath("//hudson.plugins.git.UserRemoteConfig/url").content = git_url
  172. @doc.at_xpath("//hudson.plugins.git.BranchSpec/name").content = "*/#{branch}"
  173. @doc.at_xpath("//hudson.plugins.sonar.SonarRunnerBuilder/properties").content = properties # sonar-properties
  174. logger.info("6666666666666666666666666")
  175. # jenkins job创建
  176. jenkins_job = @client_jenkins.job.create("#{job_name}", @doc.to_xml)
  177. logger.info("777777777777777777")
  178. # 将地址作为hook值添加到gitlab
  179. # @g.add_project_hook(@project.gpid, (@jenkins_address + "/project/#{job_name}"), merge_requests_events: true)
  180. # job创建完成后自动运行job,如果运行成功则返回‘200’
  181. code = @client_jenkins.job.build("#{job_name}")
  182. end
  183. # Compare branch for MR
  184. # 判断源分支和目标分支是否有改动
  185. # status 为true 表示有改动; false:便是没有改动
  186. def compare_pull_request source_branch, target_project, target_branch
  187. user_name_source = @project.owner.try(:login)
  188. identifier = @repository.identifier.downcase
  189. git_source_tree = '--git-dir=/home/git/repositories/' + user_name_source + '/' + identifier + '.git'
  190. if target_project
  191. forked_source_project = Project.find(target_project)
  192. user_name_target = forked_source_project.owner.try(:login)
  193. git_target_tree = '--git-dir=/home/git/repositories/' + user_name_target + '/' + identifier + '.git'
  194. # git_sourse_commit_id = @g.get_branch_commit_id(@project.gpid, git_source_tree, source_branch)
  195. git_sourse_commit_id = @g.commits(@project.gpid, :ref_name => source_branch).first.try(:id)
  196. # git_target_commit_id = @g.get_branch_commit_id(forked_source_project.gpid, git_target_tree, target_branch)
  197. git_target_commit_id = @g.commits(forked_source_project.gpid, :ref_name => target_branch).first.try(:id)
  198. else
  199. git_sourse_commit_id = @g.commits(@project.gpid, :ref_name => source_branch).first.try(:id)
  200. git_target_commit_id = @g.commits(@project.gpid, :ref_name => target_branch).first.try(:id)
  201. end
  202. logger.info("compare source_branch################{source_branch}")
  203. logger.info("compare target_project################{target_project}")
  204. logger.info("compare git_sourse_commit_id################{git_sourse_commit_id}")
  205. logger.info("compare git_target_commit_id################{git_target_commit_id}")
  206. status = (git_sourse_commit_id == git_target_commit_id ? false : true)
  207. end
  208. # 获取jenkins输出结果
  209. def pr_console
  210. job_name = params[:job_name]
  211. pr = PullRequest.where(:pull_request_id => params[:pr_id]).first
  212. jenkins_address = Redmine::Configuration['jenkins_address']
  213. jenkins_username = Redmine::Configuration['jenkins_username']
  214. jenkins_password = Redmine::Configuration['jenkins_password']
  215. # connect jenkins
  216. client_jenkins = JenkinsApi::Client.new(:server_url => jenkins_address, :username => jenkins_username, :password => jenkins_password)
  217. @output = client_jenkins.job.get_console_output("#{job_name}", build_num = 0, start = 0, mode = 'html')["output"]
  218. @output = @output.force_encoding("UTF-8") if @output.present?
  219. end
  220. # @project_menu_type 为了控制base顶部导航
  221. # merge_when_succeeds
  222. def show
  223. # compare_pull_request source_project, source_branch, target_project, target_branch
  224. # compare_pull_request
  225. # 如何从个人主页点击进入,则将该消息设为“已读”
  226. ForgeMessage.where(:forge_message_id => params[:id], :forge_message_type => "PullRequest", :user_id => User.current.id, :viewed => false).update_all(:viewed => true)
  227. @project_menu_type = 6
  228. @type = params[:type]
  229. @request = @g.merge_request(@project.gpid, params[:id])
  230. @commits = @g.merge_request_commits(@project.gpid, params[:id].to_i)
  231. @commits_count = @commits.count
  232. # @commits_day = @commits.chunk
  233. @changes = @g.merge_request_changes(@project.gpid, params[:id]).try(:changes)
  234. @changes_count = @changes.count
  235. @comments = @g.merge_request_comments(@project.gpid, params[:id]).reverse
  236. @comments_count = @comments.count
  237. @limit = 10
  238. @is_remote = true
  239. @count = @comments_count
  240. @pages = Paginator.new @count, @limit, params['page'] || 1
  241. @offset ||= @pages.offset
  242. @comments = paginateHelper @comments, 10
  243. end
  244. # Accept a merge request.
  245. # If merge success you get 200 OK.
  246. # Accept a merge request.
  247. #
  248. # @example
  249. # Gitlab.accept_pull_rquest(5, 1)
  250. #
  251. # @param [Integer] project The ID of a project.
  252. # @param [Integer] id The ID of a merge request.
  253. # @return [Gitlab::ObjectifiedHash]
  254. def accept_pull_request
  255. begin
  256. @status = @g.accept_merge_rquest(@project.gpid, params[:id], User.current.gid)
  257. user = User.find_by_login(@status.author.try(:username))
  258. # 更新管理员的pullrequest消息
  259. update_pullrequest_message(params[:id].to_i, @project.id, "PullRequest", 2)
  260. # 接受后,给用户发消息
  261. if ForgeMessage.where(:forge_message_id => params[:id].to_i, :project_id => @project.id, :forge_message_type => "PullRequest", :user_id => user.id).count == 0
  262. send_message_to_author(@project.id, @status.author.try(:username), params[:id], 2)
  263. end
  264. respond_to do |format|
  265. format.js{redirect_to project_pull_request_path(@status.id, :project_id => @project.id)}
  266. end
  267. rescue Gitlab::Error::Forbidden => e
  268. @message = l(:label_pull_request_forbidden)
  269. rescue Gitlab::Error::DataNotAccepted => e
  270. @message = l(:label_pull_request_datanotaccepted)
  271. rescue Gitlab::Error::NotFound => e
  272. @message = l(:label_pull_request_notfound)
  273. rescue Exception => e
  274. puts e
  275. end
  276. end
  277. # Updates a merge request.
  278. #
  279. # @example
  280. # Gitlab.update_merge_request(5, 42, :title => 'New title')
  281. #
  282. # @param [Integer] project The ID of a project.
  283. # @param [Integer] id The ID of a merge request.
  284. # @param [Hash] options A customizable set of options.
  285. # @option options [String] :title The title of a merge request.
  286. # @option options [String] :source_branch The source branch name.
  287. # @option options [String] :target_branch The target branch name.
  288. # @option options [Integer] :assignee_id The ID of a user to assign merge request.
  289. # @option options [String] :state_event New state (close|reopen|merge).
  290. # @return [Gitlab::ObjectifiedHash] Information about updated merge request.
  291. def update_pull_request
  292. begin
  293. request = @g.update_merge_request(@project.gpid, params[:id], User.current.gid, :state_event => params[:state])
  294. user = User.find_by_login(request.author.try(:username))
  295. status = params[:state] == "close" ? 4 : 3
  296. #send_message_to_manager(@project.id, params[:id], status)
  297. update_pullrequest_message(request.id, @project.id, "PullRequest", status)
  298. # 给作者发送消息,如何已经发送了消息,则不发
  299. 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
  300. send_message_to_author(@project.id, user.login, request.id, status)
  301. end
  302. respond_to do |format|
  303. format.html{redirect_to project_pull_request_path(params[:id], :project_id => @project.id)}
  304. end
  305. rescue Exception => e
  306. @message = e.message
  307. end
  308. end
  309. # Creates a merge request.
  310. #
  311. # @example
  312. # Gitlab.create_merge_request(5, 'New merge request',
  313. # :source_branch => 'source_branch', :target_branch => 'target_branch')
  314. # Gitlab.create_merge_request(5, 'New merge request',
  315. # :source_branch => 'source_branch', :target_branch => 'target_branch', :assignee_id => 42)
  316. def create_pull_request_comment
  317. content = params[:pull_request_comment]
  318. begin
  319. @comments = @g.create_merge_request_comment(@project.gpid, params[:id], content, User.current.gid)
  320. respond_to do |format|
  321. format.js{redirect_to project_pull_request_path(params[:id], :project_id => @project.id)}
  322. end
  323. rescue Exception => e
  324. @message = e.message
  325. end
  326. end
  327. # Gets the comments on a merge request.
  328. #
  329. # @example
  330. # Gitlab.merge_request_comments(5, 1)
  331. def pull_request_comments
  332. begin
  333. @comments = @g.merge_request_comments(@project.gpid, params[:id]).reverse
  334. @comments_count = @comments.count
  335. @limit = 10
  336. @is_remote = true
  337. @count = @comments_count
  338. @pages = Paginator.new @count, @limit, params['page'] || 1
  339. @offset ||= @pages.offset
  340. @comments = paginateHelper @comments, 10
  341. rescue Exception => e
  342. @message = e.message
  343. end
  344. end
  345. # Get a list of merge request commits.
  346. # Parameters:
  347. # id (required) - The ID of a project
  348. # merge_request_id (required) - The ID of MR
  349. def pull_request_commits
  350. begin
  351. @type = params[:type]
  352. @commits = @g.merge_request_commits(@project.gpid, params[:id])
  353. @commits_count = @commits.count
  354. @limit = 10
  355. @is_remote = true
  356. @count = @commits_count
  357. @pages = Paginator.new @count, @limit, params['page'] || 1
  358. @offset ||= @pages.offset
  359. @commits = paginateHelper @commits, 10
  360. rescue Exception => e
  361. @message = e.message
  362. end
  363. end
  364. # 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.
  365. # Parameters:
  366. # id (required) - The ID of a project
  367. # merge_request_id (required) - The ID of MR
  368. def pull_request_changes
  369. @type = params[:type]
  370. @changes = @g.merge_request_changes(@project.gpid, params[:id]).try(:changes)
  371. @changes_count = @changes.count
  372. @limit = 10
  373. @is_remote = true
  374. @count = @changes_count
  375. @pages = Paginator.new @count, @limit, params['page'] || 1
  376. @offset ||= @pages.offset
  377. @changes = paginateHelper @changes, 10
  378. end
  379. private
  380. # post 相关操作权限控制
  381. # 项目管理员可操作
  382. def manager_allowed
  383. unless is_project_manager?(User.current.id, @project.id)
  384. return render_403
  385. end
  386. end
  387. # 项目成员可操作
  388. def member_allowed
  389. unless User.current.member_of?(@project)
  390. return render_403
  391. end
  392. end
  393. def send_message user_id, project_id, pull_request_id
  394. ForgeMessage.create(:user_id => user_id, :project_id => project_id,
  395. :forge_message_id => pull_request_id, :forge_message_type => "PullRequest", :viewed => true)
  396. end
  397. def send_message_to_manager project_id, pull_request_id, status
  398. project = Project.find(project_id)
  399. project.members.each do |member|
  400. if is_project_manager?(member.user_id, project_id) && User.current.id != member.user_id
  401. add_message(member.user_id, project_id, pull_request_id, status)
  402. end
  403. end
  404. end
  405. def send_message_to_author(project_id, user_login, request_id, status)
  406. user = get_user_by_login_and(user_login)
  407. if user.id != User.current.id
  408. add_message(user.id, project_id, request_id, status)
  409. end
  410. end
  411. def add_message(user_id, project_id, pull_request_id, status)
  412. ForgeMessage.create(:user_id => user_id,
  413. :project_id => project_id,
  414. :forge_message_id => pull_request_id,
  415. :forge_message_type => "PullRequest",
  416. :viewed => false,
  417. :status => status,
  418. :operate_user_id => User.current.id,
  419. )
  420. end
  421. def update_pullrequest_message forge_message_id, project_id, forge_message_type, status
  422. # 更新这条pullrequest消息所有相关的信息
  423. 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)
  424. # 更新自己的消息为已读
  425. 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)
  426. # 更新pullrequest的status字段
  427. PullRequest.where(:pull_request_id => forge_message_id).update_all(:status => status)
  428. end
  429. def authorize_logged
  430. if !User.current.logged?
  431. redirect_to signin_path
  432. return
  433. end
  434. end
  435. def connect_gitlab
  436. @g = Gitlab.client
  437. end
  438. def find_project_and_repository
  439. @project = Project.find(params[:project_id])
  440. render_404 if @project.gpid.blank?
  441. @repository = Repository.where(:project_id => @project.id, :type => "Repository::Gitlab").first
  442. rescue ActiveRecord::RecordNotFound
  443. render_404
  444. end
  445. end

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