2016-01-04 07:08:49 -05:00
|
|
|
require 'zlib'
|
|
|
|
require 'json'
|
|
|
|
|
|
|
|
module Gitlab
|
|
|
|
module Ci
|
|
|
|
module Build
|
|
|
|
module Artifacts
|
|
|
|
class Metadata
|
2016-01-09 08:41:43 -05:00
|
|
|
VERSION_PATTERN = '[\w\s]+(\d+\.\d+\.\d+)'
|
|
|
|
attr_reader :file, :path, :full_version
|
2016-01-04 07:08:49 -05:00
|
|
|
|
2016-01-09 08:41:43 -05:00
|
|
|
def initialize(file, path)
|
|
|
|
@file, @path = file, path
|
|
|
|
@full_version = read_version
|
2016-01-08 06:35:49 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def version
|
2016-01-09 08:41:43 -05:00
|
|
|
@full_version.match(/#{VERSION_PATTERN}/).captures.first
|
2016-01-08 06:35:49 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def errors
|
|
|
|
gzip do|gz|
|
|
|
|
read_string(gz) # version
|
2016-01-09 08:41:43 -05:00
|
|
|
errors = read_string(gz)
|
|
|
|
raise StandardError, 'Errors field not found!' unless errors
|
|
|
|
JSON.parse(errors)
|
2016-01-08 06:35:49 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-01-04 07:08:49 -05:00
|
|
|
def match!
|
2016-01-08 06:35:49 -05:00
|
|
|
gzip do |gz|
|
2016-01-09 08:41:43 -05:00
|
|
|
2.times { read_string(gz) } # version and errors fields
|
|
|
|
match_entries(gz)
|
2016-01-04 09:07:49 -05:00
|
|
|
end
|
2016-01-04 07:08:49 -05:00
|
|
|
end
|
|
|
|
|
2016-01-09 08:41:43 -05:00
|
|
|
def to_path
|
|
|
|
Path.new(@path, *match!)
|
2016-01-04 07:08:49 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2016-01-09 08:41:43 -05:00
|
|
|
def match_entries(gz)
|
2016-01-08 06:35:49 -05:00
|
|
|
paths, metadata = [], []
|
2016-01-11 03:57:03 -05:00
|
|
|
match_pattern = %r{^#{Regexp.escape(@path)}[^/\s]*/?$}
|
2016-01-11 06:50:21 -05:00
|
|
|
invalid_pattern = %r{(^\.?\.?/)|(/\.?\.?/)}
|
2016-01-09 08:41:43 -05:00
|
|
|
|
2016-01-08 06:35:49 -05:00
|
|
|
until gz.eof? do
|
|
|
|
begin
|
|
|
|
path = read_string(gz)
|
|
|
|
meta = read_string(gz)
|
|
|
|
|
2016-01-11 03:57:03 -05:00
|
|
|
next unless path =~ match_pattern
|
2016-01-11 06:50:21 -05:00
|
|
|
next if path =~ invalid_pattern
|
2016-01-09 08:41:43 -05:00
|
|
|
|
2016-01-08 06:35:49 -05:00
|
|
|
paths.push(path)
|
2016-01-09 08:41:43 -05:00
|
|
|
metadata.push(JSON.parse(meta.chomp, symbolize_names: true))
|
2016-01-08 06:35:49 -05:00
|
|
|
rescue JSON::ParserError
|
|
|
|
next
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
[paths, metadata]
|
|
|
|
end
|
|
|
|
|
2016-01-09 08:41:43 -05:00
|
|
|
def read_version
|
|
|
|
gzip do|gz|
|
|
|
|
version_string = read_string(gz)
|
|
|
|
|
|
|
|
unless version_string
|
|
|
|
raise StandardError, 'Artifacts metadata file empty!'
|
|
|
|
end
|
|
|
|
|
|
|
|
unless version_string =~ /^#{VERSION_PATTERN}/
|
|
|
|
raise StandardError, 'Invalid version!'
|
|
|
|
end
|
|
|
|
|
|
|
|
version_string.chomp
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def read_uint32(gz)
|
2016-01-08 06:35:49 -05:00
|
|
|
binary = gz.read(4)
|
|
|
|
binary.unpack('L>')[0] if binary
|
|
|
|
end
|
|
|
|
|
|
|
|
def read_string(gz)
|
2016-01-09 08:41:43 -05:00
|
|
|
string_size = read_uint32(gz)
|
2016-01-08 06:35:49 -05:00
|
|
|
return false unless string_size
|
2016-01-09 08:41:43 -05:00
|
|
|
gz.read(string_size)
|
2016-01-08 06:35:49 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def gzip
|
2016-01-04 07:08:49 -05:00
|
|
|
open do |file|
|
|
|
|
gzip = Zlib::GzipReader.new(file)
|
2016-01-08 06:35:49 -05:00
|
|
|
result = yield gzip
|
2016-01-04 07:08:49 -05:00
|
|
|
gzip.close
|
2016-01-08 06:35:49 -05:00
|
|
|
result
|
2016-01-04 07:08:49 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def open
|
|
|
|
File.open(@file) { |file| yield file }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|