summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouwe Maan <douwe@gitlab.com>2017-12-01 14:31:42 +0000
committerDouwe Maan <douwe@gitlab.com>2017-12-01 14:31:42 +0000
commit7e81de5ba8fa2aaa13c6035c0e333b4b0ff0df9b (patch)
tree0a860cc696c9b2c9563c731debf607ff6d3aa8fd
parent76e75549b9bec9dee1e856969ef169a4450b3f30 (diff)
parent2e44e3176fa726119ea9e74b62b14f540770425d (diff)
downloadgitlab-shell-7e81de5ba8fa2aaa13c6035c0e333b4b0ff0df9b.tar.gz
Merge branch '116-fix-fork-project-for-hashed-storage' into 'master'v5.10.0
Add a 'fork-repository' command that works with hashed storage Closes #116 See merge request gitlab-org/gitlab-shell!174
-rw-r--r--CHANGELOG3
-rw-r--r--VERSION2
-rw-r--r--lib/gitlab_projects.rb31
-rw-r--r--spec/gitlab_projects_spec.rb68
4 files changed, 103 insertions, 1 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 3e0d977..37609ac 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,6 @@
+v5.10.0
+ - Add a 'fork-repository' command that works with hashed storage (!174)
+
v5.9.4
- Add relative git object dir envvars to check access request
diff --git a/VERSION b/VERSION
index c5b7013..509b0b6 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-5.9.4
+5.10.0
diff --git a/lib/gitlab_projects.rb b/lib/gitlab_projects.rb
index 9586345..ad62cce 100644
--- a/lib/gitlab_projects.rb
+++ b/lib/gitlab_projects.rb
@@ -69,6 +69,8 @@ class GitlabProjects
import_project
when 'fork-project';
fork_project
+ when 'fork-repository';
+ fork_repository
when 'fetch-remote';
fetch_remote
when 'push-branches';
@@ -360,6 +362,35 @@ class GitlabProjects
end
end
+ def fork_repository
+ from_path = full_path
+
+ new_repos_path = ARGV.shift
+ new_full_path = ARGV.shift
+
+ unless new_repos_path && new_full_path
+ $logger.error "fork-repository failed: no destination repository path provided."
+ return false
+ end
+
+ to_path = File.join(new_repos_path, new_full_path)
+
+ # The repository cannot already exist
+ if File.exists?(to_path)
+ $logger.error "fork-repository failed: destination repository <#{to_path}> already exists."
+ return false
+ end
+
+ # Ensure the namepsace / hashed storage directory exists
+ FileUtils.mkdir_p(File.dirname(to_path), mode: 0770)
+
+ $logger.info "Forking repository from <#{from_path}> to <#{to_path}>."
+ cmd = %W(git clone --bare -- #{from_path} #{to_path})
+ system(*cmd) && self.class.create_hooks(to_path)
+ end
+
+ # DEPRECATED in favour of fork_repository, which takes a source and destination
+ # repository path and so can work with hashed storage. Remove in v6.0.0
def fork_project
destination_repos_path = ARGV.shift
diff --git a/spec/gitlab_projects_spec.rb b/spec/gitlab_projects_spec.rb
index ffba3d4..7cf408b 100644
--- a/spec/gitlab_projects_spec.rb
+++ b/spec/gitlab_projects_spec.rb
@@ -491,6 +491,74 @@ describe GitlabProjects do
end
end
+ describe :fork_repository do
+ let(:source_repos_path) { tmp_repos_path }
+ let(:dest_repos_path) { tmp_repos_path }
+ let(:source_repo_name) { File.join('source-namespace', repo_name) }
+ let(:dest_repo_name) { File.join('@hashed', 'aa', 'bb', 'xyz.git') }
+ let(:dest_repo) { File.join(dest_repos_path, dest_repo_name) }
+ let(:dest_namespace) { File.dirname(dest_repo) }
+ let(:gl_repo_fork) { build_gitlab_projects('fork-repository', source_repos_path, source_repo_name, dest_repos_path, dest_repo_name) }
+ let(:gl_projects_import) { build_gitlab_projects('import-project', source_repos_path, source_repo_name, 'https://gitlab.com/gitlab-org/gitlab-test.git') }
+
+ before do
+ FileUtils.mkdir_p(dest_repos_path)
+ gl_projects_import.exec
+ end
+
+ after do
+ FileUtils.rm_rf(dest_repos_path)
+ end
+
+ it "should not fork without a source repository path" do
+ missing_arg = build_gitlab_projects('fork-repository', tmp_repos_path, source_repo_name)
+ expect($logger).to receive(:error).with("fork-repository failed: no destination repository path provided.")
+ expect(missing_arg.exec).to be_false
+ end
+
+ it "should not fork without a destination repository path" do
+ missing_arg = build_gitlab_projects('fork-repository', tmp_repos_path, source_repo_name, tmp_repos_path)
+ $logger.should_receive(:error).with("fork-repository failed: no destination repository path provided.")
+ expect(missing_arg.exec).to be_false
+ end
+
+ it "should fork the repository" do
+ expect(gl_repo_fork.exec).to be_true
+ expect(File.exists?(dest_repo)).to be_true
+ expect(File.exists?(File.join(dest_repo, 'hooks', 'pre-receive'))).to be_true
+ expect(File.exists?(File.join(dest_repo, 'hooks', 'post-receive'))).to be_true
+ end
+
+ it "should not fork if a project of the same name already exists" do
+ # create a fake project at the intended destination
+ FileUtils.mkdir_p(dest_repo)
+
+ # trying to fork again should fail as the repo already exists
+ message = "fork-repository failed: destination repository <#{dest_repo}> already exists."
+ expect($logger).to receive(:error).with(message)
+ expect(gl_repo_fork.exec).to be_false
+ end
+
+ it "should log a fork-project event" do
+ message = "Forking repository from <#{File.join(tmp_repos_path, source_repo_name)}> to <#{dest_repo}>."
+ expect($logger).to receive(:info).with(message)
+
+ expect(gl_repo_fork.exec).to be_true
+ end
+
+ context 'different storages' do
+ let(:dest_repos_path) { File.join(ROOT_PATH, 'tmp', 'alternative') }
+
+ it "should fork the repo" do
+ expect(gl_repo_fork.exec).to be_true
+ expect(File.exists?(dest_repo)).to be_true
+ expect(File.exists?(File.join(dest_repo, 'hooks', 'pre-receive'))).to be_true
+ expect(File.exists?(File.join(dest_repo, 'hooks', 'post-receive'))).to be_true
+ end
+ end
+ end
+
+
describe :fork_project do
let(:source_repo_name) { File.join('source-namespace', repo_name) }
let(:dest_repo) { File.join(tmp_repos_path, 'forked-to-namespace', repo_name) }