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 /lib | |
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.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/gitlab/ci/build/artifacts/metadata.rb | 68 |
1 files changed, 58 insertions, 10 deletions
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 |