Extract artifacts metadata implementation to separate class

This commit is contained in:
Grzegorz Bizon 2016-01-04 13:08:49 +01:00
parent df41148662
commit a7f99b67a0
5 changed files with 139 additions and 23 deletions

View file

@ -16,10 +16,7 @@ class Projects::ArtifactsController < Projects::ApplicationController
def browse
return render_404 unless build.artifacts?
current_path = params[:path] ? "./#{params[:path]}/" : './'
paths, metadata = build.artifacts_metadata_for_path(current_path)
@path = Gitlab::StringPath.new(current_path, paths, metadata)
@path = build.artifacts_metadata_string_path(params[:path] || './')
end
private

View file

@ -349,24 +349,10 @@ module Ci
artifacts? && artifacts_file.path.end_with?('zip') && artifacts_metadata.exists?
end
def artifacts_metadata_for_path(path)
return [] unless artifacts_metadata.exists?
paths, metadata = [], []
metadata_path = path.sub(/^\.\//, '')
File.open(artifacts_metadata.path) do |file|
gzip = Zlib::GzipReader.new(file)
gzip.each_line do |line|
if line =~ %r{^#{Regexp.escape(metadata_path)}[^/\s]+/?\s}
matched_path, matched_meta = line.split(' ')
paths << matched_path
metadata << JSON.parse(matched_meta)
end
end
gzip.close
end
[paths, metadata]
def artifacts_metadata_string_path(path)
file = artifacts_metadata.path
Gitlab::Ci::Build::Artifacts::Metadata.new(file, path).to_string_path
end
private

View file

@ -0,0 +1,57 @@
require 'zlib'
require 'json'
module Gitlab
module Ci
module Build
module Artifacts
class Metadata
def initialize(file, path)
@file = file
@path = path.sub(/^\.\//, '')
@path << '/' unless path.end_with?('/')
end
def exists?
File.exists?(@file)
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)
end
[paths, metadata.map { |meta| JSON.parse(meta) }]
end
def to_string_path
universe, metadata = match!
::Gitlab::StringPath.new(@path, universe, metadata)
end
private
def each
open do |file|
gzip = Zlib::GzipReader.new(file)
gzip.each_line { |line| yield line }
gzip.close
end
end
def open
File.open(@file) { |file| yield file }
end
end
end
end
end
end

View file

@ -75,7 +75,7 @@ module Gitlab
end
def directories!
has_parent? ? directories.prepend(parent) : directories
@path =~ %r{^\./[^/]/} ? directories.prepend(parent) : directories
end
def files
@ -119,7 +119,7 @@ module Gitlab
raise ArgumentError, 'Invalid path' if clean_path.start_with?('../')
prefix = './' unless clean_path =~ %r{^[\.|/]}
suffix = '/' if path.end_with?('/') || clean_path =~ /^[\.|\.\.]$/
suffix = '/' if path.end_with?('/') || ['.', '..'].include?(clean_path)
prefix.to_s + clean_path + suffix.to_s
end
end

View file

@ -0,0 +1,76 @@
require 'spec_helper'
describe Gitlab::Ci::Build::Artifacts::Metadata do
def metadata(path = '')
described_class.new(metadata_file_path, path)
end
let(:metadata_file_path) do
Rails.root + 'spec/fixtures/ci_build_artifacts_metadata.gz'
end
context 'metadata file exists' do
describe '#exists?' do
subject { metadata.exists? }
it { is_expected.to be true }
end
describe '#match! ./' do
subject { metadata('./').match! }
it 'matches correct paths' do
expect(subject.first).to contain_exactly 'ci_artifacts.txt',
'other_artifacts_0.1.2/',
'rails_sample.jpg'
end
it 'matches metadata for every path' do
expect(subject.last.count).to eq 3
end
it 'return Hashes for each metadata' do
expect(subject.last).to all(be_kind_of(Hash))
end
end
describe '#match! other_artifacts_0.1.2' do
subject { metadata('other_artifacts_0.1.2').match! }
it 'matches correct paths' do
expect(subject.first).
to contain_exactly 'other_artifacts_0.1.2/doc_sample.txt',
'other_artifacts_0.1.2/another-subdirectory/'
end
end
describe '#match! other_artifacts_0.1.2/another-subdirectory' do
subject { metadata('other_artifacts_0.1.2/another-subdirectory/').match! }
it 'matches correct paths' do
expect(subject.first).
to contain_exactly 'other_artifacts_0.1.2/another-subdirectory/empty_directory/',
'other_artifacts_0.1.2/another-subdirectory/banana_sample.gif'
end
end
describe '#to_string_path' do
subject { metadata('').to_string_path }
it { is_expected.to be_an_instance_of(Gitlab::StringPath) }
end
end
context 'metadata file does not exist' do
let(:metadata_file_path) { '' }
describe '#exists?' do
subject { metadata.exists? }
it { is_expected.to be false }
end
describe '#match!' do
it 'raises error' do
expect { metadata.match! }.to raise_error(StandardError, /Metadata file not found/)
end
end
end
end