summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRémy Coutable <remy@rymai.me>2019-04-17 10:30:49 +0000
committerRémy Coutable <remy@rymai.me>2019-04-17 10:30:49 +0000
commitcfa5c30792ced178e53d1f7782ae027204ce8821 (patch)
tree31e7251dd6d2a57739ce6544ca5131955ef7f612 /lib
parent128f91fce7a62c7f6c444e670a00294ce1b777a1 (diff)
parente052d49a4c342624d5f6c6a7e1354ea6a8003d05 (diff)
downloadgitlab-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.rb7
-rw-r--r--lib/gitlab/workhorse.rb65
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