summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrzegorz Bizon <grzesiek.bizon@gmail.com>2016-01-08 12:35:49 +0100
committerGrzegorz Bizon <grzesiek.bizon@gmail.com>2016-01-14 12:48:15 +0100
commit387b27813d1d496c015f4f174812b4761c32648d (patch)
tree59061040f651df04895060bfc48d9b5f36ee5f34
parent09c82c6fdc494de0d64cb58b4b61a86104ff1131 (diff)
downloadgitlab-ce-387b27813d1d496c015f4f174812b4761c32648d.tar.gz
Change format of artifacts metadata from text to binary 0.0.1
This changes the format of metadata to handle paths, that may contain whitespace characters, new line characters and non-UTF-8 characters. Now those paths along with metadata in JSON format are stored as length-prefixed strings (uint32 prefix). Metadata file has a custom format: 1. First string field is metadata version field (string) 2. Second string field is metadata errors field (JSON strong) 3. All subsequent fields is pair of path (string) and path metadata in JSON format. Path's metadata contains all fields that where possible to extract from ZIP archive like date of modification, CRC, compressed size, uncompressed size and comment.
-rw-r--r--app/views/projects/artifacts/_tree_file.html.haml2
-rw-r--r--lib/gitlab/ci/build/artifacts/metadata.rb68
-rw-r--r--spec/fixtures/ci_build_artifacts_metadata.gzbin242 -> 309 bytes
-rw-r--r--spec/lib/gitlab/ci/build/artifacts/metadata_spec.rb15
4 files changed, 74 insertions, 11 deletions
diff --git a/app/views/projects/artifacts/_tree_file.html.haml b/app/views/projects/artifacts/_tree_file.html.haml
index 0059f845841..11ced45fe14 100644
--- a/app/views/projects/artifacts/_tree_file.html.haml
+++ b/app/views/projects/artifacts/_tree_file.html.haml
@@ -4,7 +4,7 @@
%span.str-truncated
= file.name
%td
- = number_to_human_size(file.metadata[:uncompressed_size], precision: 2)
+ = number_to_human_size(file.metadata[:size], precision: 2)
%td
= link_to '', class: 'btn btn-xs btn-default' do
= icon('download')
diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb
index 1f3000e7c8a..d90a64fdbb8 100644
--- a/lib/gitlab/ci/build/artifacts/metadata.rb
+++ b/lib/gitlab/ci/build/artifacts/metadata.rb
@@ -17,18 +17,33 @@ module Gitlab
File.exists?(@file)
end
+ def full_version
+ gzip do|gz|
+ read_string(gz) do |size|
+ raise StandardError, 'Artifacts metadata file empty!' unless size
+ end
+ end
+ end
+
+ def version
+ full_version.match(/\w+ (\d+\.\d+\.\d+)/).captures.first
+ end
+
+ def errors
+ gzip do|gz|
+ read_string(gz) # version
+ JSON.parse(read_string(gz))
+ end
+ end
+
def match!
raise StandardError, 'Metadata file not found !' unless exists?
- paths, metadata = [], []
- each do |line|
- next unless line =~ %r{^#{Regexp.escape(@path)}[^/\s]*/?\s}
- path, meta = line.split(' ')
- paths.push(path)
- metadata.push(meta)
+ gzip do |gz|
+ read_string(gz) # version field
+ read_string(gz) # errors field
+ iterate_entries(gz)
end
-
- [paths, metadata.map { |meta| JSON.parse(meta, symbolize_names: true) }]
end
def to_string_path
@@ -38,11 +53,44 @@ module Gitlab
private
- def each
+ def iterate_entries(gz)
+ paths, metadata = [], []
+
+ until gz.eof? do
+ begin
+ path = read_string(gz)
+ meta = read_string(gz)
+
+ next unless path =~ %r{^#{Regexp.escape(@path)}[^/\s]*/?$}
+
+ paths.push(path)
+ metadata.push(JSON.parse(meta, symbolize_names: true))
+ rescue JSON::ParserError
+ next
+ end
+ end
+
+ [paths, metadata]
+ end
+
+ def read_string_size(gz)
+ binary = gz.read(4)
+ binary.unpack('L>')[0] if binary
+ end
+
+ def read_string(gz)
+ string_size = read_string_size(gz)
+ yield string_size if block_given?
+ return false unless string_size
+ gz.read(string_size).chomp
+ end
+
+ def gzip
open do |file|
gzip = Zlib::GzipReader.new(file)
- gzip.each_line { |line| yield line }
+ result = yield gzip
gzip.close
+ result
end
end
diff --git a/spec/fixtures/ci_build_artifacts_metadata.gz b/spec/fixtures/ci_build_artifacts_metadata.gz
index 82d6a79c72f..c394f83bf87 100644
--- a/spec/fixtures/ci_build_artifacts_metadata.gz
+++ b/spec/fixtures/ci_build_artifacts_metadata.gz
Binary files differ
diff --git a/spec/lib/gitlab/ci/build/artifacts/metadata_spec.rb b/spec/lib/gitlab/ci/build/artifacts/metadata_spec.rb
index 62c86a60ac4..0c8a41cfab7 100644
--- a/spec/lib/gitlab/ci/build/artifacts/metadata_spec.rb
+++ b/spec/lib/gitlab/ci/build/artifacts/metadata_spec.rb
@@ -59,6 +59,21 @@ describe Gitlab::Ci::Build::Artifacts::Metadata do
subject { metadata('').to_string_path }
it { is_expected.to be_an_instance_of(Gitlab::StringPath) }
end
+
+ describe '#full_version' do
+ subject { metadata('').full_version }
+ it { is_expected.to eq 'GitLab Build Artifacts Metadata 0.0.1' }
+ end
+
+ describe '#version' do
+ subject { metadata('').version }
+ it { is_expected.to eq '0.0.1' }
+ end
+
+ describe '#errors' do
+ subject { metadata('').errors }
+ it { is_expected.to eq({}) }
+ end
end
context 'metadata file does not exist' do