summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2013-05-02 23:41:07 -0700
committerDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2013-05-02 23:41:07 -0700
commitf40d4e6685ca749c69bfc480a747a430f6c9825f (patch)
tree0cfdb3e6276c6b4cce664b89c4da37f55adaac55 /app
parent36efe0f5807e92c2a0b6ec71b828387e6684a9ab (diff)
parentec63804831d1a55171abfb7fc0894af20d4298e8 (diff)
downloadgitlab-ce-f40d4e6685ca749c69bfc480a747a430f6c9825f.tar.gz
Merge pull request #3597 from amacarthur/fork-pull-request
updated fork feature to use gitlab-shell for v5 of gitlab
Diffstat (limited to 'app')
-rw-r--r--app/contexts/projects/fork_context.rb45
-rw-r--r--app/controllers/projects_controller.rb15
-rw-r--r--app/models/ability.rb4
-rw-r--r--app/models/forked_project_link.rb8
-rw-r--r--app/models/project.rb7
-rw-r--r--app/observers/project_observer.rb12
-rw-r--r--app/views/projects/_clone_panel.html.haml3
7 files changed, 88 insertions, 6 deletions
diff --git a/app/contexts/projects/fork_context.rb b/app/contexts/projects/fork_context.rb
new file mode 100644
index 00000000000..f2a0684b01c
--- /dev/null
+++ b/app/contexts/projects/fork_context.rb
@@ -0,0 +1,45 @@
+module Projects
+ class ForkContext < BaseContext
+ include Gitlab::ShellAdapter
+
+ def initialize(project, user)
+ @from_project, @current_user = project, user
+ end
+
+ def execute
+ project = Project.new
+ project.initialize_dup(@from_project)
+ project.name = @from_project.name
+ project.path = @from_project.path
+ project.namespace = current_user.namespace
+ project.creator = current_user
+
+ # If the project cannot save, we do not want to trigger the project destroy
+ # as this can have the side effect of deleting a repo attached to an existing
+ # project with the same name and namespace
+ if project.valid?
+ begin
+ Project.transaction do
+ #First save the DB entries as they can be rolled back if the repo fork fails
+ project.build_forked_project_link(forked_to_project_id: project.id, forked_from_project_id: @from_project.id)
+ if project.save
+ project.users_projects.create(project_access: UsersProject::MASTER, user: current_user)
+ end
+ #Now fork the repo
+ unless gitlab_shell.fork_repository(@from_project.path_with_namespace, project.namespace.path)
+ raise "forking failed in gitlab-shell"
+ end
+ project.ensure_satellite_exists
+ end
+ rescue => ex
+ project.errors.add(:base, "Fork transaction failed.")
+ project.destroy
+ end
+ else
+ project.errors.add(:base, "Invalid fork destination")
+ end
+ project
+
+ end
+ end
+end
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 8e55aa01cc9..255baba0ecb 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -78,4 +78,19 @@ class ProjectsController < ProjectResourceController
format.html { redirect_to root_path }
end
end
+
+ def fork
+ @project = ::Projects::ForkContext.new(project, current_user).execute
+
+ respond_to do |format|
+ format.html do
+ if @project.saved? && @project.forked?
+ redirect_to(@project, notice: 'Project was successfully forked.')
+ else
+ render action: "new"
+ end
+ end
+ format.js
+ end
+ end
end
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 5b49104da8a..eb7f89dcfc1 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -67,7 +67,9 @@ class Ability
def project_report_rules
project_guest_rules + [
:download_code,
- :write_snippet
+ :write_snippet,
+ :fork_project
+
]
end
diff --git a/app/models/forked_project_link.rb b/app/models/forked_project_link.rb
new file mode 100644
index 00000000000..c3199ca264e
--- /dev/null
+++ b/app/models/forked_project_link.rb
@@ -0,0 +1,8 @@
+class ForkedProjectLink < ActiveRecord::Base
+ attr_accessible :forked_from_project_id, :forked_to_project_id
+
+ # Relations
+ belongs_to :forked_to_project, class_name: Project
+ belongs_to :forked_from_project, class_name: Project
+
+end
diff --git a/app/models/project.rb b/app/models/project.rb
index e811cbe7f41..291316f3088 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -45,6 +45,8 @@ class Project < ActiveRecord::Base
has_one :last_event, class_name: 'Event', order: 'events.created_at DESC', foreign_key: 'project_id'
has_one :gitlab_ci_service, dependent: :destroy
+ has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id"
+ has_one :forked_from_project, through: :forked_project_link
has_many :events, dependent: :destroy
has_many :merge_requests, dependent: :destroy
@@ -402,4 +404,9 @@ class Project < ActiveRecord::Base
def protected_branch? branch_name
protected_branches_names.include?(branch_name)
end
+
+ def forked?
+ !(forked_project_link.nil? || forked_project_link.forked_from_project.nil?)
+ end
+
end
diff --git a/app/observers/project_observer.rb b/app/observers/project_observer.rb
index 7d7ecdd319f..de9edf41c6d 100644
--- a/app/observers/project_observer.rb
+++ b/app/observers/project_observer.rb
@@ -1,11 +1,13 @@
class ProjectObserver < BaseObserver
def after_create(project)
- GitlabShellWorker.perform_async(
- :add_repository,
- project.path_with_namespace
- )
+ unless project.forked?
+ GitlabShellWorker.perform_async(
+ :add_repository,
+ project.path_with_namespace
+ )
- log_info("#{project.owner.name} created a new project \"#{project.name_with_namespace}\"")
+ log_info("#{project.owner.name} created a new project \"#{project.name_with_namespace}\"")
+ end
end
def after_update(project)
diff --git a/app/views/projects/_clone_panel.html.haml b/app/views/projects/_clone_panel.html.haml
index 9c07bd0da18..02b09ab73d9 100644
--- a/app/views/projects/_clone_panel.html.haml
+++ b/app/views/projects/_clone_panel.html.haml
@@ -5,6 +5,9 @@
.span3.pull-right
.pull-right
- unless @project.empty_repo?
+ - if can? current_user, :fork_project, @project
+ = link_to fork_project_path(@project), title: "Fork", class: "btn small grouped", method: "POST" do
+ Fork
- if can? current_user, :download_code, @project
= link_to archive_project_repository_path(@project), class: "btn grouped" do
%i.icon-download-alt