diff options
author | Grzegorz Bizon <grzesiek.bizon@gmail.com> | 2016-01-08 12:35:49 +0100 |
---|---|---|
committer | Grzegorz Bizon <grzesiek.bizon@gmail.com> | 2016-01-14 12:48:15 +0100 |
commit | 387b27813d1d496c015f4f174812b4761c32648d (patch) | |
tree | 59061040f651df04895060bfc48d9b5f36ee5f34 | |
parent | 09c82c6fdc494de0d64cb58b4b61a86104ff1131 (diff) | |
download | gitlab-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.haml | 2 | ||||
-rw-r--r-- | lib/gitlab/ci/build/artifacts/metadata.rb | 68 | ||||
-rw-r--r-- | spec/fixtures/ci_build_artifacts_metadata.gz | bin | 242 -> 309 bytes | |||
-rw-r--r-- | spec/lib/gitlab/ci/build/artifacts/metadata_spec.rb | 15 |
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 Binary files differindex 82d6a79c72f..c394f83bf87 100644 --- a/spec/fixtures/ci_build_artifacts_metadata.gz +++ b/spec/fixtures/ci_build_artifacts_metadata.gz 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 |