diff options
author | Rémy Coutable <remy@rymai.me> | 2019-04-17 10:30:49 +0000 |
---|---|---|
committer | Rémy Coutable <remy@rymai.me> | 2019-04-17 10:30:49 +0000 |
commit | cfa5c30792ced178e53d1f7782ae027204ce8821 (patch) | |
tree | 31e7251dd6d2a57739ce6544ca5131955ef7f612 /lib | |
parent | 128f91fce7a62c7f6c444e670a00294ce1b777a1 (diff) | |
parent | e052d49a4c342624d5f6c6a7e1354ea6a8003d05 (diff) | |
download | gitlab-ce-cfa5c30792ced178e53d1f7782ae027204ce8821.tar.gz |
Merge branch '24704-restore-download-repository-path' into 'master'
Restore "download repository path" feature, now with fixes and a feature flag
Closes gitlab-workhorse#218 and #24704
See merge request gitlab-org/gitlab-ce!27275
Diffstat (limited to 'lib')
-rw-r--r-- | lib/gitlab/git/repository.rb | 7 | ||||
-rw-r--r-- | lib/gitlab/workhorse.rb | 65 |
2 files changed, 64 insertions, 8 deletions
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index be9e926728c..a22e3c4b9dd 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -231,12 +231,12 @@ module Gitlab end end - def archive_metadata(ref, storage_path, project_path, format = "tar.gz", append_sha:) + def archive_metadata(ref, storage_path, project_path, format = "tar.gz", append_sha:, path: nil) ref ||= root_ref commit = Gitlab::Git::Commit.find(self, ref) return {} if commit.nil? - prefix = archive_prefix(ref, commit.id, project_path, append_sha: append_sha) + prefix = archive_prefix(ref, commit.id, project_path, append_sha: append_sha, path: path) { 'ArchivePrefix' => prefix, @@ -248,13 +248,14 @@ module Gitlab # This is both the filename of the archive (missing the extension) and the # name of the top-level member of the archive under which all files go - def archive_prefix(ref, sha, project_path, append_sha:) + def archive_prefix(ref, sha, project_path, append_sha:, path:) append_sha = (ref != sha) if append_sha.nil? formatted_ref = ref.tr('/', '-') prefix_segments = [project_path, formatted_ref] prefix_segments << sha if append_sha + prefix_segments << path.tr('/', '-').gsub(%r{^/|/$}, '') if path prefix_segments.join('-') end diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb index 0c2acac3d1e..46a7b5b982a 100644 --- a/lib/gitlab/workhorse.rb +++ b/lib/gitlab/workhorse.rb @@ -63,16 +63,34 @@ module Gitlab ] end - def send_git_archive(repository, ref:, format:, append_sha:) + def send_git_archive(repository, ref:, format:, append_sha:, path: nil) + path_enabled = Feature.enabled?(:git_archive_path, default_enabled: true) + path = nil unless path_enabled + format ||= 'tar.gz' format = format.downcase - params = repository.archive_metadata(ref, Gitlab.config.gitlab.repository_downloads_path, format, append_sha: append_sha) - raise "Repository or ref not found" if params.empty? - params['GitalyServer'] = gitaly_server_hash(repository) + metadata = repository.archive_metadata( + ref, + Gitlab.config.gitlab.repository_downloads_path, + format, + append_sha: append_sha, + path: path + ) - # If present DisableCache must be a Boolean. Otherwise workhorse ignores it. + raise "Repository or ref not found" if metadata.empty? + + params = + if path_enabled + send_git_archive_params(repository, metadata, path, archive_format(format)) + else + metadata + end + + # If present, DisableCache must be a Boolean. Otherwise + # workhorse ignores it. params['DisableCache'] = true if git_archive_cache_disabled? + params['GitalyServer'] = gitaly_server_hash(repository) [ SEND_DATA_HEADER, @@ -216,10 +234,19 @@ module Gitlab protected + # This is the outermost encoding of a senddata: header. It is safe for + # inclusion in HTTP response headers def encode(hash) Base64.urlsafe_encode64(JSON.dump(hash)) end + # This is for encoding individual fields inside the senddata JSON that + # contain binary data. In workhorse, the corresponding struct field should + # be type []byte + def encode_binary(binary) + Base64.encode64(binary) + end + def gitaly_server_hash(repository) { address: Gitlab::GitalyClient.address(repository.project.repository_storage), @@ -238,6 +265,34 @@ module Gitlab def git_archive_cache_disabled? ENV['WORKHORSE_ARCHIVE_CACHE_DISABLED'].present? || Feature.enabled?(:workhorse_archive_cache_disabled) end + + def archive_format(format) + case format + when "tar.bz2", "tbz", "tbz2", "tb2", "bz2" + Gitaly::GetArchiveRequest::Format::TAR_BZ2 + when "tar" + Gitaly::GetArchiveRequest::Format::TAR + when "zip" + Gitaly::GetArchiveRequest::Format::ZIP + else + Gitaly::GetArchiveRequest::Format::TAR_GZ + end + end + + def send_git_archive_params(repository, metadata, path, format) + { + 'ArchivePath' => metadata['ArchivePath'], + 'GetArchiveRequest' => encode_binary( + Gitaly::GetArchiveRequest.new( + repository: repository.gitaly_repository, + commit_id: metadata['CommitId'], + prefix: metadata['ArchivePrefix'], + format: format, + path: path.presence || "" + ).to_proto + ) + } + end end end end |