diff options
author | Yorick Peterse <yorickpeterse@gmail.com> | 2016-06-30 10:57:43 +0000 |
---|---|---|
committer | Yorick Peterse <yorickpeterse@gmail.com> | 2016-06-30 10:57:43 +0000 |
commit | 710746ff1e6762f5072c6ae6443fd3ad75169bc1 (patch) | |
tree | 810dd76a8b3bea1048e5951cefd4d1eeee5aaefd | |
parent | 5a6d71d143a6ea5f9747b25304aafa902ed381d0 (diff) | |
parent | 18b4d39ac7172cb02cec63e7bf1cc21807a9b3f0 (diff) | |
download | gitlab-shell-710746ff1e6762f5072c6ae6443fd3ad75169bc1.tar.gz |
Merge branch 'shards' into 'master'
v3.1.0
Implement shard paths handling
See https://gitlab.com/gitlab-org/gitlab-ee/issues/583
See merge request !61
-rw-r--r-- | CHANGELOG | 3 | ||||
-rw-r--r-- | VERSION | 2 | ||||
-rwxr-xr-x | bin/check | 17 | ||||
-rwxr-xr-x | bin/create-hooks | 14 | ||||
-rwxr-xr-x | bin/install | 8 | ||||
-rw-r--r-- | config.yml.example | 6 | ||||
-rw-r--r-- | lib/gitlab_access.rb | 2 | ||||
-rw-r--r-- | lib/gitlab_access_status.rb | 7 | ||||
-rw-r--r-- | lib/gitlab_config.rb | 4 | ||||
-rw-r--r-- | lib/gitlab_net.rb | 2 | ||||
-rw-r--r-- | lib/gitlab_projects.rb | 2 | ||||
-rw-r--r-- | lib/gitlab_shell.rb | 54 | ||||
-rw-r--r-- | lib/names_helper.rb | 5 | ||||
-rw-r--r-- | spec/gitlab_access_spec.rb | 4 | ||||
-rw-r--r-- | spec/gitlab_projects_spec.rb | 41 | ||||
-rw-r--r-- | spec/gitlab_shell_spec.rb | 146 | ||||
-rw-r--r-- | spec/names_helper_spec.rb | 5 |
17 files changed, 172 insertions, 150 deletions
@@ -1,3 +1,6 @@ +v3.1.0 + - Refactor repository paths handling to allow multiple git mount points + v3.0.1 - Update PostReceive worker to provide enqueued_at time. @@ -1 +1 @@ -3.0.0 +3.1.0 @@ -23,18 +23,15 @@ end puts "\nCheck directories and files: " config = GitlabConfig.new -dirs = [config.repos_path, config.auth_file] -dirs.each do |dir| - abort("ERROR: missing option in config.yml") unless dir - print "\t#{dir}: " - if File.exists?(dir) - print 'OK' - else - abort "FAILED" - end - puts "\n" +abort("ERROR: missing option in config.yml") unless config.auth_file +print "\t#{config.auth_file}: " +if File.exists?(config.auth_file) + print 'OK' +else + abort "FAILED" end +puts "\n" print "Send ping to redis server: " abort unless GitlabNet.new.redis_client.ping diff --git a/bin/create-hooks b/bin/create-hooks index 4efa650..241e10b 100755 --- a/bin/create-hooks +++ b/bin/create-hooks @@ -7,10 +7,14 @@ require_relative '../lib/gitlab_init' require File.join(ROOT_PATH, 'lib', 'gitlab_projects') -Dir["#{GitlabConfig.new.repos_path}/*/*.git"].each do |repo| - begin - GitlabProjects.create_hooks(repo) - rescue Errno::ENOENT - # The user must have deleted their repository. Ignore. +repository_storage_paths = ARGV + +repository_storage_paths.each do |repo_path| + Dir["#{repo_path.chomp('/')}/*/*.git"].each do |repo| + begin + GitlabProjects.create_hooks(repo) + rescue Errno::ENOENT + # The user must have deleted their repository. Ignore. + end end end diff --git a/bin/install b/bin/install index 9847ae1..73ac592 100755 --- a/bin/install +++ b/bin/install @@ -8,16 +8,20 @@ require_relative '../lib/gitlab_init' config = GitlabConfig.new key_dir = File.dirname("#{config.auth_file}") +repository_storage_paths = ARGV commands = [ - %W(mkdir -p #{config.repos_path}), %W(mkdir -p #{key_dir}), %W(chmod 700 #{key_dir}), %W(touch #{config.auth_file}), %W(chmod 600 #{config.auth_file}), - %W(chmod ug+rwX,o-rwx #{config.repos_path}), ] +repository_storage_paths.each do |repository_storage_path| + commands << %W(mkdir -p #{repository_storage_path}) + commands << %W(chmod ug+rwX,o-rwx #{repository_storage_path}) +end + commands.each do |cmd| print "#{cmd.join(' ')}: " if system(*cmd) diff --git a/config.yml.example b/config.yml.example index eff354d..166e384 100644 --- a/config.yml.example +++ b/config.yml.example @@ -24,12 +24,6 @@ http_settings: # ca_path: /etc/pki/tls/certs self_signed_cert: false -# Repositories path -# Give the canonicalized absolute pathname, -# REPOS_PATH MUST NOT CONTAIN ANY SYMLINK!!! -# Check twice that none of the components is a symlink, including "/home". -repos_path: "/home/git/repositories" - # File used as authorized_keys for gitlab user auth_file: "/home/git/.ssh/authorized_keys" diff --git a/lib/gitlab_access.rb b/lib/gitlab_access.rb index 5816969..10afeef 100644 --- a/lib/gitlab_access.rb +++ b/lib/gitlab_access.rb @@ -15,7 +15,7 @@ class GitlabAccess @config = GitlabConfig.new @repo_path = repo_path.strip @actor = actor - @repo_name = extract_repo_name(@repo_path.dup, config.repos_path.to_s) + @repo_name = extract_repo_name(@repo_path.dup) @changes = changes.lines end diff --git a/lib/gitlab_access_status.rb b/lib/gitlab_access_status.rb index 7a5f7d5..7fb88be 100644 --- a/lib/gitlab_access_status.rb +++ b/lib/gitlab_access_status.rb @@ -1,16 +1,17 @@ require 'json' class GitAccessStatus - attr_reader :message + attr_reader :message, :repository_path - def initialize(status, message) + def initialize(status, message, repository_path) @status = status @message = message + @repository_path = repository_path end def self.create_from_json(json) values = JSON.parse(json) - self.new(values["status"], values["message"]) + self.new(values["status"], values["message"], values["repository_path"]) end def allowed? diff --git a/lib/gitlab_config.rb b/lib/gitlab_config.rb index ebf72d6..beaf173 100644 --- a/lib/gitlab_config.rb +++ b/lib/gitlab_config.rb @@ -11,10 +11,6 @@ class GitlabConfig ENV['HOME'] end - def repos_path - @config['repos_path'] ||= File.join(home, "repositories") - end - def auth_file @config['auth_file'] ||= File.join(home, ".ssh/authorized_keys") end diff --git a/lib/gitlab_net.rb b/lib/gitlab_net.rb index e2bc2da..dd9a4b0 100644 --- a/lib/gitlab_net.rb +++ b/lib/gitlab_net.rb @@ -38,7 +38,7 @@ class GitlabNet if resp.code == '200' GitAccessStatus.create_from_json(resp.body) else - GitAccessStatus.new(false, 'API is not accessible') + GitAccessStatus.new(false, 'API is not accessible', nil) end end diff --git a/lib/gitlab_projects.rb b/lib/gitlab_projects.rb index 767ab79..ad3d3b8 100644 --- a/lib/gitlab_projects.rb +++ b/lib/gitlab_projects.rb @@ -43,8 +43,8 @@ class GitlabProjects def initialize @command = ARGV.shift + @repos_path = ARGV.shift @project_name = ARGV.shift - @repos_path = GitlabConfig.new.repos_path @full_path = File.join(@repos_path, @project_name) unless @project_name.nil? end diff --git a/lib/gitlab_shell.rb b/lib/gitlab_shell.rb index 365c543..c5d5c02 100644 --- a/lib/gitlab_shell.rb +++ b/lib/gitlab_shell.rb @@ -9,12 +9,12 @@ class GitlabShell GIT_COMMANDS = %w(git-upload-pack git-receive-pack git-upload-archive git-annex-shell git-lfs-authenticate).freeze - attr_accessor :key_id, :repo_name, :git_cmd, :repos_path, :repo_name + attr_accessor :key_id, :repo_name, :git_cmd + attr_reader :repo_path def initialize(key_id) @key_id = key_id @config = GitlabConfig.new - @repos_path = @config.repos_path end # The origin_cmd variable contains UNTRUSTED input. If the user ran @@ -66,13 +66,10 @@ class GitlabShell when 'git-annex-shell' raise DisallowedCommandError unless @config.git_annex_enabled? - @repo_name = escape_path(args[2].sub(/\A\/~\//, '')) - - # Make sure repository has git-annex enabled - init_git_annex(@repo_name) unless gcryptsetup?(args) + @repo_name = args[2].sub(/\A\/~\//, '') when 'git-lfs-authenticate' raise DisallowedCommandError unless args.count >= 2 - @repo_name = escape_path(args[1]) + @repo_name = args[1] case args[2] when 'download' @git_access = 'git-upload-pack' @@ -83,7 +80,7 @@ class GitlabShell end else raise DisallowedCommandError unless args.count == 2 - @repo_name = escape_path(args.last) + @repo_name = args.last end end @@ -91,19 +88,22 @@ class GitlabShell status = api.check_access(@git_access, @repo_name, @key_id, '_any') raise AccessDeniedError, status.message unless status.allowed? + + self.repo_path = status.repository_path end def process_cmd(args) - repo_full_path = File.join(repos_path, repo_name) - if @git_cmd == 'git-annex-shell' raise DisallowedCommandError unless @config.git_annex_enabled? + # Make sure repository has git-annex enabled + init_git_annex unless gcryptsetup?(args) + parsed_args = args.map do |arg| # use full repo path if arg =~ /\A\/.*\.git\Z/ - repo_full_path + repo_path else arg end @@ -112,8 +112,8 @@ class GitlabShell $logger.info "gitlab-shell: executing git-annex command <#{parsed_args.join(' ')}> for #{log_username}." exec_cmd(*parsed_args) else - $logger.info "gitlab-shell: executing git command <#{@git_cmd} #{repo_full_path}> for #{log_username}." - exec_cmd(@git_cmd, repo_full_path) + $logger.info "gitlab-shell: executing git command <#{@git_cmd} #{repo_path}> for #{log_username}." + exec_cmd(@git_cmd, repo_path) end end @@ -164,23 +164,11 @@ class GitlabShell @config.audit_usernames ? username : "user with key #{@key_id}" end - def escape_path(path) - full_repo_path = File.join(repos_path, path) - - if File.absolute_path(full_repo_path) == full_repo_path - path - else - raise InvalidRepositoryPathError - end - end - - def init_git_annex(path) - full_repo_path = File.join(repos_path, path) - - unless File.exists?(File.join(full_repo_path, 'annex')) - cmd = %W(git --git-dir=#{full_repo_path} annex init "GitLab") + def init_git_annex + unless File.exists?(File.join(repo_path, 'annex')) + cmd = %W(git --git-dir=#{repo_path} annex init "GitLab") system(*cmd, err: '/dev/null', out: '/dev/null') - $logger.info "Enable git-annex for repository: #{path}." + $logger.info "Enable git-annex for repository: #{repo_name}." end end @@ -188,4 +176,12 @@ class GitlabShell non_dashed = args.reject { |a| a.start_with?('-') } non_dashed[0, 2] == %w{git-annex-shell gcryptsetup} end + + private + + def repo_path=(repo_path) + raise InvalidRepositoryPathError if File.absolute_path(repo_path) != repo_path + + @repo_path = repo_path + end end diff --git a/lib/names_helper.rb b/lib/names_helper.rb index efad56f..ec41b79 100644 --- a/lib/names_helper.rb +++ b/lib/names_helper.rb @@ -1,10 +1,9 @@ module NamesHelper - def extract_repo_name(path, base) + def extract_repo_name(path) repo_name = path.strip - repo_name.gsub!(base, "") repo_name.gsub!(/\.git$/, "") repo_name.gsub!(/^\//, "") - repo_name + repo_name.split(File::SEPARATOR).last(2).join(File::SEPARATOR) end def extract_ref_name(ref) diff --git a/spec/gitlab_access_spec.rb b/spec/gitlab_access_spec.rb index 39c3ab3..98848ae 100644 --- a/spec/gitlab_access_spec.rb +++ b/spec/gitlab_access_spec.rb @@ -7,7 +7,7 @@ describe GitlabAccess do let(:repo_path) { File.join(repository_path, repo_name) + ".git" } let(:api) do double(GitlabNet).tap do |api| - api.stub(check_access: GitAccessStatus.new(true, 'ok')) + api.stub(check_access: GitAccessStatus.new(true, 'ok', '/home/git/repositories')) end end subject do @@ -38,7 +38,7 @@ describe GitlabAccess do context "access is denied" do before do - api.stub(check_access: GitAccessStatus.new(false, 'denied')) + api.stub(check_access: GitAccessStatus.new(false, 'denied', nil)) end it "returns false" do diff --git a/spec/gitlab_projects_spec.rb b/spec/gitlab_projects_spec.rb index eeebf87..fc0909e 100644 --- a/spec/gitlab_projects_spec.rb +++ b/spec/gitlab_projects_spec.rb @@ -59,21 +59,22 @@ describe GitlabProjects do describe :initialize do before do - argv('add-project', repo_name) + argv('add-project', tmp_repos_path, repo_name) @gl_projects = GitlabProjects.new end it { @gl_projects.project_name.should == repo_name } + it { @gl_projects.repos_path.should == tmp_repos_path } + it { @gl_projects.full_path.should == "#{tmp_repos_path}/gitlab-ci.git" } it { @gl_projects.instance_variable_get(:@command).should == 'add-project' } - it { @gl_projects.instance_variable_get(:@full_path).should == "#{GitlabConfig.new.repos_path}/gitlab-ci.git" } end describe :create_tag do let(:gl_projects_create) { - build_gitlab_projects('import-project', repo_name, 'https://github.com/randx/six.git') + build_gitlab_projects('import-project', tmp_repos_path, repo_name, 'https://github.com/randx/six.git') } context "lightweight tag" do - let(:gl_projects) { build_gitlab_projects('create-tag', repo_name, 'test_tag', 'master') } + let(:gl_projects) { build_gitlab_projects('create-tag', tmp_repos_path, repo_name, 'test_tag', 'master') } it "should create a tag" do gl_projects_create.exec @@ -87,7 +88,7 @@ describe GitlabProjects do msg = 'some message' tag_name = 'test_annotated_tag' - let(:gl_projects) { build_gitlab_projects('create-tag', repo_name, tag_name, 'master', msg) } + let(:gl_projects) { build_gitlab_projects('create-tag', tmp_repos_path, repo_name, tag_name, 'master', msg) } it "should create an annotated tag" do gl_projects_create.exec @@ -106,7 +107,7 @@ describe GitlabProjects do end describe :add_project do - let(:gl_projects) { build_gitlab_projects('add-project', repo_name) } + let(:gl_projects) { build_gitlab_projects('add-project', tmp_repos_path, repo_name) } it "should create a directory" do gl_projects.stub(system: true) @@ -130,7 +131,7 @@ describe GitlabProjects do describe :list_projects do let(:gl_projects) do - build_gitlab_projects('add-project', "list_test/#{repo_name}") + build_gitlab_projects('add-project', tmp_repos_path, "list_test/#{repo_name}") end before do @@ -145,7 +146,7 @@ describe GitlabProjects do end describe :mv_project do - let(:gl_projects) { build_gitlab_projects('mv-project', repo_name, 'repo.git') } + let(:gl_projects) { build_gitlab_projects('mv-project', tmp_repos_path, repo_name, 'repo.git') } let(:new_repo_path) { File.join(tmp_repos_path, 'repo.git') } before do @@ -160,20 +161,20 @@ describe GitlabProjects do end it "should fail if no destination path is provided" do - incomplete = build_gitlab_projects('mv-project', repo_name) + incomplete = build_gitlab_projects('mv-project', tmp_repos_path, repo_name) $logger.should_receive(:error).with("mv-project failed: no destination path provided.") incomplete.exec.should be_false end it "should fail if the source path doesn't exist" do - bad_source = build_gitlab_projects('mv-project', 'bad-src.git', 'dest.git') + bad_source = build_gitlab_projects('mv-project', tmp_repos_path, 'bad-src.git', 'dest.git') $logger.should_receive(:error).with("mv-project failed: source path <#{tmp_repos_path}/bad-src.git> does not exist.") bad_source.exec.should be_false end it "should fail if the destination path already exists" do FileUtils.mkdir_p(File.join(tmp_repos_path, 'already-exists.git')) - bad_dest = build_gitlab_projects('mv-project', repo_name, 'already-exists.git') + bad_dest = build_gitlab_projects('mv-project', tmp_repos_path, repo_name, 'already-exists.git') message = "mv-project failed: destination path <#{tmp_repos_path}/already-exists.git> already exists." $logger.should_receive(:error).with(message) bad_dest.exec.should be_false @@ -187,7 +188,7 @@ describe GitlabProjects do end describe :rm_project do - let(:gl_projects) { build_gitlab_projects('rm-project', repo_name) } + let(:gl_projects) { build_gitlab_projects('rm-project', tmp_repos_path, repo_name) } before do FileUtils.mkdir_p(tmp_repo_path) @@ -207,7 +208,7 @@ describe GitlabProjects do describe :import_project do context 'success import' do - let(:gl_projects) { build_gitlab_projects('import-project', repo_name, 'https://github.com/randx/six.git') } + let(:gl_projects) { build_gitlab_projects('import-project', tmp_repos_path, repo_name, 'https://github.com/randx/six.git') } it { gl_projects.exec.should be_true } @@ -224,7 +225,7 @@ describe GitlabProjects do end context 'already exists' do - let(:gl_projects) { build_gitlab_projects('import-project', repo_name, 'https://github.com/randx/six.git') } + let(:gl_projects) { build_gitlab_projects('import-project', tmp_repos_path, repo_name, 'https://github.com/randx/six.git') } it 'should import only once' do gl_projects.exec.should be_true @@ -233,7 +234,7 @@ describe GitlabProjects do end context 'timeout' do - let(:gl_projects) { build_gitlab_projects('import-project', repo_name, 'https://github.com/gitlabhq/gitlabhq.git', '1') } + let(:gl_projects) { build_gitlab_projects('import-project', tmp_repos_path, repo_name, 'https://github.com/gitlabhq/gitlabhq.git', '1') } it { gl_projects.exec.should be_false } @@ -253,15 +254,15 @@ describe GitlabProjects do 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) } - let(:gl_projects_fork) { build_gitlab_projects('fork-project', source_repo_name, 'forked-to-namespace') } - let(:gl_projects_import) { build_gitlab_projects('import-project', source_repo_name, 'https://github.com/randx/six.git') } + let(:gl_projects_fork) { build_gitlab_projects('fork-project', tmp_repos_path, source_repo_name, 'forked-to-namespace') } + let(:gl_projects_import) { build_gitlab_projects('import-project', tmp_repos_path, source_repo_name, 'https://github.com/randx/six.git') } before do gl_projects_import.exec end it "should not fork without a destination namespace" do - missing_arg = build_gitlab_projects('fork-project', source_repo_name) + missing_arg = build_gitlab_projects('fork-project', tmp_repos_path, source_repo_name) $logger.should_receive(:error).with("fork-project failed: no destination namespace provided.") missing_arg.exec.should be_false end @@ -304,13 +305,13 @@ describe GitlabProjects do describe :exec do it 'should puts message if unknown command arg' do - gitlab_projects = build_gitlab_projects('edit-project', repo_name) + gitlab_projects = build_gitlab_projects('edit-project', tmp_repos_path, repo_name) gitlab_projects.should_receive(:puts).with('not allowed') gitlab_projects.exec end it 'should log a warning for unknown commands' do - gitlab_projects = build_gitlab_projects('hurf-durf', repo_name) + gitlab_projects = build_gitlab_projects('hurf-durf', tmp_repos_path, repo_name) $logger.should_receive(:warn).with('Attempt to execute invalid gitlab-projects command "hurf-durf".') gitlab_projects.exec end diff --git a/spec/gitlab_shell_spec.rb b/spec/gitlab_shell_spec.rb index 3be1671..79fa49b 100644 --- a/spec/gitlab_shell_spec.rb +++ b/spec/gitlab_shell_spec.rb @@ -22,7 +22,7 @@ describe GitlabShell do let(:api) do double(GitlabNet).tap do |api| api.stub(discover: { 'name' => 'John Doe' }) - api.stub(check_access: GitAccessStatus.new(true, 'ok')) + api.stub(check_access: GitAccessStatus.new(true, 'ok', repo_path)) end end @@ -30,15 +30,17 @@ describe GitlabShell do let(:ssh_cmd) { nil } let(:tmp_repos_path) { File.join(ROOT_PATH, 'tmp', 'repositories') } + let(:repo_name) { 'gitlab-ci.git' } + let(:repo_path) { File.join(tmp_repos_path, repo_name) } + before do - GitlabConfig.any_instance.stub(repos_path: tmp_repos_path, audit_usernames: false) + GitlabConfig.any_instance.stub(audit_usernames: false) end describe :initialize do let(:ssh_cmd) { 'git-receive-pack' } its(:key_id) { should == key_id } - its(:repos_path) { should == tmp_repos_path } end describe :parse_cmd do @@ -55,6 +57,7 @@ describe GitlabShell do end context 'namespace' do + let(:repo_name) { 'dmitriy.zaporozhets/gitlab-ci.git' } let(:ssh_args) { %W(git-upload-pack dmitriy.zaporozhets/gitlab-ci.git) } before do @@ -75,50 +78,24 @@ describe GitlabShell do end describe 'git-annex' do - let(:repo_path) { File.join(tmp_repos_path, 'dzaporozhets/gitlab.git') } - + let(:repo_name) { 'dzaporozhets/gitlab.git' } let(:ssh_args) { %W(git-annex-shell inannex /~/dzaporozhets/gitlab.git SHA256E) } before do GitlabConfig.any_instance.stub(git_annex_enabled?: true) - # Create existing project - FileUtils.mkdir_p(repo_path) - cmd = %W(git --git-dir=#{repo_path} init --bare) - system(*cmd) - subject.send :parse_cmd, ssh_args end its(:repo_name) { should == 'dzaporozhets/gitlab.git' } its(:git_cmd) { should == 'git-annex-shell' } - - it 'should init git-annex' do - File.exists?(File.join(tmp_repos_path, 'dzaporozhets/gitlab.git/annex')).should be_true - end - - context 'with git-annex-shell gcryptsetup' do - let(:ssh_args) { %W(git-annex-shell gcryptsetup /~/dzaporozhets/gitlab.git) } - - it 'should not init git-annex' do - File.exists?(File.join(tmp_repos_path, 'dzaporozhets/gitlab.git/annex')).should be_false - end - end - - context 'with git-annex and relative path without ~/' do - # Using a SSH URL on a custom port will generate /dzaporozhets/gitlab.git - let(:ssh_args) { %W(git-annex-shell inannex /dzaporozhets/gitlab.git SHA256E) } - - it 'should init git-annex' do - File.exists?(File.join(tmp_repos_path, 'dzaporozhets/gitlab.git/annex')).should be_true - end - end end end describe :exec do + context 'git-upload-pack' do - let(:ssh_cmd) { 'git-upload-pack gitlab-ci.git' } + let(:ssh_cmd) { "git-upload-pack gitlab-ci.git" } after { subject.exec(ssh_cmd) } it "should process the command" do @@ -126,12 +103,12 @@ describe GitlabShell do end it "should execute the command" do - subject.should_receive(:exec_cmd).with("git-upload-pack", File.join(tmp_repos_path, 'gitlab-ci.git')) + subject.should_receive(:exec_cmd).with("git-upload-pack", repo_path) end it "should log the command execution" do message = "gitlab-shell: executing git command " - message << "<git-upload-pack #{File.join(tmp_repos_path, 'gitlab-ci.git')}> " + message << "<git-upload-pack #{repo_path}> " message << "for user with key #{key_id}." $logger.should_receive(:info).with(message) end @@ -143,7 +120,7 @@ describe GitlabShell do end context 'git-receive-pack' do - let(:ssh_cmd) { 'git-receive-pack gitlab-ci.git' } + let(:ssh_cmd) { "git-receive-pack gitlab-ci.git" } after { subject.exec(ssh_cmd) } it "should process the command" do @@ -151,12 +128,12 @@ describe GitlabShell do end it "should execute the command" do - subject.should_receive(:exec_cmd).with("git-receive-pack", File.join(tmp_repos_path, 'gitlab-ci.git')) + subject.should_receive(:exec_cmd).with("git-receive-pack", repo_path) end it "should log the command execution" do message = "gitlab-shell: executing git command " - message << "<git-receive-pack #{File.join(tmp_repos_path, 'gitlab-ci.git')}> " + message << "<git-receive-pack #{repo_path}> " message << "for user with key #{key_id}." $logger.should_receive(:info).with(message) end @@ -206,34 +183,93 @@ describe GitlabShell do end describe 'git-annex' do - let(:ssh_cmd) { 'git-annex-shell commit /~/gitlab-ci.git SHA256' } + let(:repo_name) { 'dzaporozhets/gitlab.git' } before do GitlabConfig.any_instance.stub(git_annex_enabled?: true) end - after { subject.exec(ssh_cmd) } + context 'initialization' do + let(:ssh_cmd) { "git-annex-shell inannex /~/gitlab-ci.git SHA256E" } - it "should execute the command" do - subject.should_receive(:exec_cmd).with("git-annex-shell", "commit", File.join(tmp_repos_path, 'gitlab-ci.git'), "SHA256") + before do + # Create existing project + FileUtils.mkdir_p(repo_path) + cmd = %W(git --git-dir=#{repo_path} init --bare) + system(*cmd) + + subject.exec(ssh_cmd) + end + + it 'should init git-annex' do + File.exists?(repo_path).should be_true + end + + context 'with git-annex-shell gcryptsetup' do + let(:ssh_cmd) { "git-annex-shell gcryptsetup /~/dzaporozhets/gitlab.git" } + + it 'should not init git-annex' do + File.exists?(File.join(tmp_repos_path, 'dzaporozhets/gitlab.git/annex')).should be_false + end + end + + context 'with git-annex and relative path without ~/' do + # Using a SSH URL on a custom port will generate /dzaporozhets/gitlab.git + let(:ssh_cmd) { "git-annex-shell inannex dzaporozhets/gitlab.git SHA256E" } + + it 'should init git-annex' do + File.exists?(File.join(tmp_repos_path, "dzaporozhets/gitlab.git/annex")).should be_true + end + end + end + + context 'execution' do + let(:ssh_cmd) { "git-annex-shell commit /~/gitlab-ci.git SHA256" } + + after { subject.exec(ssh_cmd) } + + it "should execute the command" do + subject.should_receive(:exec_cmd).with("git-annex-shell", "commit", repo_path, "SHA256") + end end end end describe :validate_access do - let(:ssh_cmd) { 'git-upload-pack gitlab-ci.git' } - after { subject.exec(ssh_cmd) } + let(:ssh_cmd) { "git-upload-pack gitlab-ci.git" } + + describe 'check access with api' do + after { subject.exec(ssh_cmd) } - it "should call api.check_access" do - api.should_receive(:check_access). - with('git-upload-pack', 'gitlab-ci.git', key_id, '_any') + it "should call api.check_access" do + api.should_receive(:check_access).with('git-upload-pack', 'gitlab-ci.git', key_id, '_any') + end + + it "should disallow access and log the attempt if check_access returns false status" do + api.stub(check_access: GitAccessStatus.new(false, 'denied', nil)) + message = "gitlab-shell: Access denied for git command <git-upload-pack gitlab-ci.git> " + message << "by user with key #{key_id}." + $logger.should_receive(:warn).with(message) + end end - it "should disallow access and log the attempt if check_access returns false status" do - api.stub(check_access: GitAccessStatus.new(false, 'denied')) - message = "gitlab-shell: Access denied for git command <git-upload-pack gitlab-ci.git> " - message << "by user with key #{key_id}." - $logger.should_receive(:warn).with(message) + describe 'set the repository path' do + context 'with a correct path' do + before { subject.exec(ssh_cmd) } + + its(:repo_path) { should == repo_path } + end + + context "with a path that doesn't match an absolute path" do + before do + File.stub(:absolute_path) { 'y/gitlab-ci.git' } + end + + it "refuses to assign the path" do + $stderr.should_receive(:puts).with("GitLab: Invalid repository path") + expect(subject.exec(ssh_cmd)).to be_false + end + end end end @@ -262,12 +298,4 @@ describe GitlabShell do it { should be_a(GitlabNet) } end - - describe :escape_path do - let(:shell) { GitlabShell.new(key_id) } - before { File.stub(:absolute_path) { 'y' } } - subject { -> { shell.send(:escape_path, 'z') } } - - it { should raise_error(GitlabShell::InvalidRepositoryPathError) } - end end diff --git a/spec/names_helper_spec.rb b/spec/names_helper_spec.rb index 081dac9..a5fcf94 100644 --- a/spec/names_helper_spec.rb +++ b/spec/names_helper_spec.rb @@ -5,8 +5,8 @@ describe NamesHelper do include NamesHelper describe :extract_repo_name do - it { extract_repo_name(' /opt/repos/randx/gitlab.git', '/opt/repos').should == 'randx/gitlab' } - it { extract_repo_name("/opt/repos/randx/gitlab.git\r\n", '/opt/repos/').should == 'randx/gitlab' } + it { extract_repo_name(' /opt/repos/randx/gitlab.git').should == 'randx/gitlab' } + it { extract_repo_name("/opt/repos/randx/gitlab.git\r\n").should == 'randx/gitlab' } end describe :extract_ref_name do @@ -15,4 +15,3 @@ describe NamesHelper do it { extract_ref_name('refs/tags/releases/v2.2.1').should == 'releases/v2.2.1' } end end - |