diff options
author | Stan Hu <stanhu@gmail.com> | 2018-04-06 21:32:42 +0000 |
---|---|---|
committer | Stan Hu <stanhu@gmail.com> | 2018-04-06 21:32:42 +0000 |
commit | 151d87e4a052b01f08b9b3826dba06ff8f20f278 (patch) | |
tree | 15b5a4128407d7cbe9d38a47792ed3eea4dd6b9f /lib | |
parent | fe96152d8beab2f7f9fe8bdf1a8552fb0d98ebae (diff) | |
parent | 76cd2d7881da69697f5c6584be04abbfb9411a22 (diff) | |
download | gitlab-ce-151d87e4a052b01f08b9b3826dba06ff8f20f278.tar.gz |
Merge branch 'da-gitaly-calculate-repository-checksum' into 'master'
Repository checksum calculation is handled by Gitaly when feature is enabled
See merge request gitlab-org/gitlab-ce!18210
Diffstat (limited to 'lib')
-rw-r--r-- | lib/gitlab/git/checksum.rb | 82 | ||||
-rw-r--r-- | lib/gitlab/git/repository.rb | 40 | ||||
-rw-r--r-- | lib/gitlab/gitaly_client/repository_service.rb | 6 |
3 files changed, 46 insertions, 82 deletions
diff --git a/lib/gitlab/git/checksum.rb b/lib/gitlab/git/checksum.rb deleted file mode 100644 index 3ef0f0a8854..00000000000 --- a/lib/gitlab/git/checksum.rb +++ /dev/null @@ -1,82 +0,0 @@ -module Gitlab - module Git - class Checksum - include Gitlab::Git::Popen - - EMPTY_REPOSITORY_CHECKSUM = '0000000000000000000000000000000000000000'.freeze - - Failure = Class.new(StandardError) - - attr_reader :path, :relative_path, :storage, :storage_path - - def initialize(storage, relative_path) - @storage = storage - @storage_path = Gitlab.config.repositories.storages[storage].legacy_disk_path - @relative_path = "#{relative_path}.git" - @path = File.join(storage_path, @relative_path) - end - - def calculate - unless repository_exists? - failure!(Gitlab::Git::Repository::NoRepository, 'No repository for such path') - end - - calculate_checksum_by_shelling_out - end - - private - - def repository_exists? - raw_repository.exists? - end - - def calculate_checksum_by_shelling_out - args = %W(--git-dir=#{path} show-ref --heads --tags) - output, status = run_git(args) - - if status&.zero? - refs = output.split("\n") - - result = refs.inject(nil) do |checksum, ref| - value = Digest::SHA1.hexdigest(ref).hex - - if checksum.nil? - value - else - checksum ^ value - end - end - - result.to_s(16) - else - # Empty repositories return with a non-zero status and an empty output. - if output&.empty? - EMPTY_REPOSITORY_CHECKSUM - else - failure!(Gitlab::Git::Checksum::Failure, output) - end - end - end - - def failure!(klass, message) - Gitlab::GitLogger.error("'git show-ref --heads --tags' in #{path}: #{message}") - - raise klass.new("Could not calculate the checksum for #{path}: #{message}") - end - - def circuit_breaker - @circuit_breaker ||= Gitlab::Git::Storage::CircuitBreaker.for_storage(storage) - end - - def raw_repository - Gitlab::Git::Repository.new(storage, relative_path, nil) - end - - def run_git(args) - circuit_breaker.perform do - popen([Gitlab.config.git.bin_path, *args], path) - end - end - end - end -end diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index 5678c28cf3a..79cacd9f6f5 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -23,6 +23,7 @@ module Gitlab SQUASH_WORKTREE_PREFIX = 'squash'.freeze GITALY_INTERNAL_URL = 'ssh://gitaly/internal.git'.freeze GITLAB_PROJECTS_TIMEOUT = Gitlab.config.gitlab_shell.git_timeout + EMPTY_REPOSITORY_CHECKSUM = '0000000000000000000000000000000000000000'.freeze NoRepository = Class.new(StandardError) InvalidBlobName = Class.new(StandardError) @@ -31,6 +32,7 @@ module Gitlab DeleteBranchError = Class.new(StandardError) CreateTreeError = Class.new(StandardError) TagExistsError = Class.new(StandardError) + ChecksumError = Class.new(StandardError) class << self # Unlike `new`, `create` takes the repository path @@ -1502,6 +1504,16 @@ module Gitlab FileUtils.rm_rf(worktree_git_path) if worktree_git_path && File.exist?(worktree_git_path) end + def checksum + gitaly_migrate(:calculate_checksum) do |is_enabled| + if is_enabled + gitaly_repository_client.calculate_checksum + else + calculate_checksum_by_shelling_out + end + end + end + private def local_write_ref(ref_path, ref, old_ref: nil, shell: true) @@ -2420,6 +2432,34 @@ module Gitlab def sha_from_ref(ref) rev_parse_target(ref).oid end + + def calculate_checksum_by_shelling_out + raise NoRepository unless exists? + + args = %W(--git-dir=#{path} show-ref --heads --tags) + output, status = run_git(args) + + if status.nil? || !status.zero? + # Empty repositories return with a non-zero status and an empty output. + return EMPTY_REPOSITORY_CHECKSUM if output&.empty? + + raise ChecksumError, output + end + + refs = output.split("\n") + + result = refs.inject(nil) do |checksum, ref| + value = Digest::SHA1.hexdigest(ref).hex + + if checksum.nil? + value + else + checksum ^ value + end + end + + result.to_s(16) + end end end end diff --git a/lib/gitlab/gitaly_client/repository_service.rb b/lib/gitlab/gitaly_client/repository_service.rb index b5a734aaef6..6441065f5fe 100644 --- a/lib/gitlab/gitaly_client/repository_service.rb +++ b/lib/gitlab/gitaly_client/repository_service.rb @@ -262,6 +262,12 @@ module Gitlab response.license_short_name.presence end + + def calculate_checksum + request = Gitaly::CalculateChecksumRequest.new(repository: @gitaly_repo) + response = GitalyClient.call(@storage, :repository_service, :calculate_checksum, request) + response.checksum.presence + end end end end |