Skip to content

Commit

Permalink
use faster worktree instead of cloning
Browse files Browse the repository at this point in the history
extracted from #944
  • Loading branch information
grosser committed Oct 5, 2018
1 parent 62adc03 commit 5db20db
Show file tree
Hide file tree
Showing 7 changed files with 31 additions and 80 deletions.
29 changes: 13 additions & 16 deletions app/models/git_repository.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@ def checkout_workspace(work_dir, git_reference)
executor.output.write("# Beginning git repo setup\n")

ensure_mirror_current &&
create_workspace(work_dir) &&
checkout(git_reference, work_dir) &&
checkout_submodules(work_dir)
checkout(git_reference, work_dir) &&
checkout_submodules(work_dir)
end

# @return [nil, sha1]
Expand Down Expand Up @@ -91,6 +90,11 @@ def update_mirror
exclusive { (mirrored? ? update! : clone!) }
end

# clear worktrees that are deleted
def prune_worktree
executor.execute("cd #{repo_cache_dir}", "git worktree prune")
end

private

attr_reader :repository_url, :repository_directory
Expand Down Expand Up @@ -129,11 +133,6 @@ def clone!
end
add_tracer :clone!

def create_workspace(temp_dir)
executor.execute "git clone #{repo_cache_dir} #{temp_dir}"
end
add_tracer :create_workspace

def update!
executor.execute("cd #{repo_cache_dir}", 'git fetch -p')
end
Expand All @@ -143,25 +142,23 @@ def sha_exist?(sha)
!!capture_stdout("git", "cat-file", "-t", sha)
end

def checkout(git_reference, pwd)
executor.execute("cd #{pwd}", "git checkout --quiet #{git_reference.shellescape}")
def checkout(git_reference, work_dir)
executor.execute(
"cd #{repo_cache_dir}",
"git worktree add #{work_dir.shellescape} #{git_reference.shellescape} --force"
)
end

def checkout_submodules(pwd)
return true unless File.exist? "#{pwd}/.gitmodules"

recursive_flag = " --recursive" if git_supports_recursive_flag?
executor.execute(
"cd #{pwd}",
"git submodule sync#{recursive_flag}",
"git submodule sync --recursive",
"git submodule update --init --recursive"
)
end

def git_supports_recursive_flag?
Samson::GitInfo.version >= Gem::Version.new("1.8.1")
end

def mirrored?
Dir.exist?(repo_cache_dir)
end
Expand Down
3 changes: 3 additions & 0 deletions app/models/job_execution.rb
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ def build_finder
@build_finder ||= Samson::BuildFinder.new(@output, @job, @reference)
end

# TODO: @repository.checkout_workspace should manage the tempdir and prune after
def make_tempdir
result = nil
Dir.mktmpdir("samson-#{@job.project.permalink}-#{@job.id}") do |dir|
Expand All @@ -279,5 +280,7 @@ def make_tempdir
rescue Errno::ENOTEMPTY, Errno::ENOENT
ErrorNotifier.notify("Notify: make_tempdir error #{$!.message.split('@').first}")
result # tempdir ensure sometimes fails ... not sure why ... return normally
ensure
@repository.prune_worktree
end
end
4 changes: 4 additions & 0 deletions config/initializers/git.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# frozen_string_literal: true
min = "2.5.0"
raise "Git not found" unless version = `git --version`[/\d+\.\d+\.\d+/]
raise "Need git v#{min}+" if Gem::Version.new(version) < Gem::Version.new(min)
14 changes: 0 additions & 14 deletions lib/samson/git_info.rb

This file was deleted.

20 changes: 0 additions & 20 deletions test/lib/samson/git_info_test.rb

This file was deleted.

31 changes: 1 addition & 30 deletions test/models/git_repository_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,6 @@
repository.send(:repository_directory).must_equal project.repository_directory
end

describe "#create_workspace" do
it 'clones a repository' do
Dir.mktmpdir do |dir|
create_repo_without_tags
FileUtils.mv(repo_temp_dir, repository.repo_cache_dir)

repository.send(:create_workspace, dir).must_equal true
Dir.exist?("#{dir}/.git").must_equal true
end
end

it "returns false when clone fails" do
Dir.mktmpdir do |dir|
repository.send(:create_workspace, dir).must_equal false
Dir.exist?("#{dir}/.git").must_equal false
end
end
end

describe "#ensure_mirror_current" do
def call
repository.send(:ensure_mirror_current)
Expand Down Expand Up @@ -95,24 +76,14 @@ def call
public = file.split(/^ private$/).first
methods = public.scan(/^ def ([a-z_\?\!]+)(.*?)^ end/m)
methods.size.must_be :>, 5 # making sure the logic is sound
methods.delete_if { |method, _| method == "update_mirror" }
methods.delete_if { |method, _| ["update_mirror", "prune_worktree"].include?(method) }
methods.each do |name, body|
next if ["initialize", "repo_cache_dir", "clean!", "valid_url?"].include?(name)
body.must_include "ensure_mirror_current", "Expected #{name} to update the repo with ensure_mirror_current"
end
end
end

describe "#checkout" do
it 'switches to a different branch' do
create_repo_with_an_additional_branch
repository.send(:checkout, 'master', repo_temp_dir).must_equal(true)
Dir.chdir(repo_temp_dir) { current_branch.must_equal('master') }
repository.send(:checkout, 'test_user/test_branch', repo_temp_dir).must_equal(true)
Dir.chdir(repo_temp_dir) { current_branch.must_equal('test_user/test_branch') }
end
end

describe "#commit_from_ref" do
it 'returns the full commit id' do
create_repo_with_tags
Expand Down
10 changes: 10 additions & 0 deletions test/models/job_execution_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def last_line_of_output
user.name = 'John Doe'
user.email = '[email protected]'
project.repository.send(:clone!)
project.repository.stubs(:prune_worktree)
job.deploy = deploy
freeze_time
end
Expand Down Expand Up @@ -478,5 +479,14 @@ def perform
111
end.must_equal 111
end

it "removes deleted worktrees" do
project.repository.unstub(:prune_worktree)
before = `cd #{project.repository.repo_cache_dir} && git worktree list`
execution.send(:make_tempdir) do |dir|
assert project.repository.checkout_workspace(dir, "master")
end
`cd #{project.repository.repo_cache_dir} && git worktree list`.must_equal before
end
end
end

0 comments on commit 5db20db

Please sign in to comment.