From ac881d131a312eca04caa61956a3256bb4fb1c57 Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Sat, 11 Jan 2020 17:12:53 +0800 Subject: [PATCH] ADD fork project --- app/controllers/application_controller.rb | 4 +- app/controllers/forks_controller.rb | 20 ++++++++++ app/helpers/forks_helper.rb | 2 + app/models/repository.rb | 2 +- app/services/gitea/client_service.rb | 2 +- app/services/gitea/repository/fork_service.rb | 32 ++++++++++++++++ app/services/projects/fork_service.rb | 38 +++++++++++++++++++ app/views/forks/create.json.jbuilder | 6 +++ 8 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 app/controllers/forks_controller.rb create mode 100644 app/helpers/forks_helper.rb create mode 100644 app/services/gitea/repository/fork_service.rb create mode 100644 app/services/projects/fork_service.rb create mode 100644 app/views/forks/create.json.jbuilder diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index f676959f1..456f503a3 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -328,7 +328,7 @@ class ApplicationController < ActionController::Base def current_user # User.current - User.find_by_id 50207 + User.find_by_id 36401 end ## 默认输出json @@ -643,7 +643,7 @@ class ApplicationController < ActionController::Base end def find_project - @project = Project.find_by_identifier!(params[:id]) || (Project.find params[:project_id]) + @project = Project.find_by_identifier!(params[:id]) || (Project.find params[:project_id]) || (Project.find params[:id]) render_not_found("未找到’#{params[:id]}’相关的项目") unless @project end diff --git a/app/controllers/forks_controller.rb b/app/controllers/forks_controller.rb new file mode 100644 index 000000000..66253a3a4 --- /dev/null +++ b/app/controllers/forks_controller.rb @@ -0,0 +1,20 @@ +class ForksController < ApplicationController + before_action :require_login, :find_project_with_id + before_action :authenticate_project!, :authenticate_user! + + def create + @new_project = Projects::ForkService.new(current_user, @project, params[:organization]).call + end + + private + def authenticate_project! + return if current_user != @project.owner + render_result(1, "自己不能fork自己的项目") + end + + def authenticate_user! + return if @project.is_public + return if @project.member?(current_user) || current_user.admin? + render_forbidden('你没有权限操作') + end +end diff --git a/app/helpers/forks_helper.rb b/app/helpers/forks_helper.rb new file mode 100644 index 000000000..b720976ee --- /dev/null +++ b/app/helpers/forks_helper.rb @@ -0,0 +1,2 @@ +module ForksHelper +end diff --git a/app/models/repository.rb b/app/models/repository.rb index 441a3b236..a1e30f785 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -4,7 +4,7 @@ class Repository < ApplicationRecord belongs_to :user has_many :version_releases, dependent: :destroy - validates :identifier, presence: true, uniqueness: true + validates :identifier, presence: true def to_param self.identifier.parameterize diff --git a/app/services/gitea/client_service.rb b/app/services/gitea/client_service.rb index 6d9fcfd14..41f1f26c1 100644 --- a/app/services/gitea/client_service.rb +++ b/app/services/gitea/client_service.rb @@ -123,7 +123,7 @@ class Gitea::ClientService < ApplicationService mark = "[gitea] " case response.status - when 201, 200 + when 201, 200, 202 if response.body.size > 0 JSON.parse(response&.body) else diff --git a/app/services/gitea/repository/fork_service.rb b/app/services/gitea/repository/fork_service.rb new file mode 100644 index 000000000..dce925b8a --- /dev/null +++ b/app/services/gitea/repository/fork_service.rb @@ -0,0 +1,32 @@ +class Gitea::Repository::ForkService < Gitea::ClientService + attr_reader :old_owner, :target_owner, :repo_name, :organization + + # old_owner: 被clone的项目(源项目)拥有者 + # target_owner: clone后的醒目(新项目)的拥有者 + # body: + # { + # "organization": "string" #组织名称 + # } + def initialize(old_owner, target_owner, repo_name, organization=nil) + @old_owner = old_owner + @target_owner = target_owner + @repo_name = repo_name + end + + def call + post(url, request_params) + end + + private + + def request_params + hash = Hash.new.merge(token: target_owner.gitea_token) + hash = hash.merge(data: {organization: organization}) if organization + hash + end + + def url + "/repos/#{old_owner.login}/#{repo_name}/forks".freeze + end + +end diff --git a/app/services/projects/fork_service.rb b/app/services/projects/fork_service.rb new file mode 100644 index 000000000..9ad9f4fa0 --- /dev/null +++ b/app/services/projects/fork_service.rb @@ -0,0 +1,38 @@ +class Projects::ForkService < ApplicationService + attr_reader :target_owner, :project, :organization + + def initialize(target_owner, project, organization=nil) + @target_owner = target_owner + @project = project + @organization = organization + end + + def call + ActiveRecord::Base.transaction do + clone_project = + @project.deep_clone include: :repository, + only: [:name, :description,:is_public, :identifier, + :rep_identifier, :project_category_id, :project_language_id, + :license_id, :ignore_id, {repository: [:identifier, :hidden]}] + + clone_project.owner = @target_owner + clone_project.forked_from_project_id = @project.id + clone_project.save! + + new_repository = clone_project.repository + new_repository.user = @target_owner + new_repository.save! + + result = Gitea::Repository::ForkService.new(@project.owner, @target_owner, @project.identifier, @organization).call + + @project.update_column('forked_count', @project.forked_count + 1) + new_repository.update_column('url', result['clone_url']) if result + + clone_project + end + rescue => e + puts "clone project service error: #{e.message}" + raise Error, e.message + end + +end diff --git a/app/views/forks/create.json.jbuilder b/app/views/forks/create.json.jbuilder new file mode 100644 index 000000000..f9f960ef4 --- /dev/null +++ b/app/views/forks/create.json.jbuilder @@ -0,0 +1,6 @@ +if @new_project + json.id @new_project.id + json.identifier @new_project.identifier +else + json.nil! +end