diff options
Diffstat (limited to 'lib/gitlab/ci/build/artifacts/adapters/gzip_stream.rb')
-rw-r--r-- | lib/gitlab/ci/build/artifacts/adapters/gzip_stream.rb | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/lib/gitlab/ci/build/artifacts/adapters/gzip_stream.rb b/lib/gitlab/ci/build/artifacts/adapters/gzip_stream.rb new file mode 100644 index 00000000000..ee3647f24fd --- /dev/null +++ b/lib/gitlab/ci/build/artifacts/adapters/gzip_stream.rb @@ -0,0 +1,48 @@ +module Gitlab + module Ci + module Build + module Artifacts + module Adapters + class GzipStream + attr_reader :stream + + InvalidStreamError = Class.new(StandardError) + + def initialize(stream) + raise InvalidStreamError, "Stream is required" unless stream + + @stream = stream + end + + def each_blob + stream.seek(0) + + until stream.eof? + gzip(stream) do |gz| + yield gz.read, gz.orig_name + unused = gz.unused&.length.to_i + # pos has already reached to EOF at the moment + # We rewind the pos to the top of unused files + # to read next gzip stream, to support multistream archives + # https://golang.org/src/compress/gzip/gunzip.go#L117 + stream.seek(-unused, IO::SEEK_CUR) + end + end + end + + private + + def gzip(stream, &block) + gz = Zlib::GzipReader.new(stream) + yield(gz) + rescue Zlib::Error => e + raise InvalidStreamError, e.message + ensure + gz&.finish + end + end + end + end + end + end +end |