summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/controllers/projects/artifacts_controller.rb5
-rw-r--r--app/models/ci/build.rb20
-rw-r--r--lib/gitlab/ci/build/artifacts/metadata.rb57
-rw-r--r--lib/gitlab/string_path.rb4
-rw-r--r--spec/lib/gitlab/ci/build/artifacts/metadata_spec.rb76
5 files changed, 139 insertions, 23 deletions
diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb
index 5bd0c8cd780..ee1b1f375dc 100644
--- a/app/controllers/projects/artifacts_controller.rb
+++ b/app/controllers/projects/artifacts_controller.rb
@@ -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
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index df51a5ce079..7983ce0e88e 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -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
diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb
new file mode 100644
index 00000000000..5313182d55f
--- /dev/null
+++ b/lib/gitlab/ci/build/artifacts/metadata.rb
@@ -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
diff --git a/lib/gitlab/string_path.rb b/lib/gitlab/string_path.rb
index e7d99a35869..9948502e8ea 100644
--- a/lib/gitlab/string_path.rb
+++ b/lib/gitlab/string_path.rb
@@ -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
diff --git a/spec/lib/gitlab/ci/build/artifacts/metadata_spec.rb b/spec/lib/gitlab/ci/build/artifacts/metadata_spec.rb
new file mode 100644
index 00000000000..8c648be5f02
--- /dev/null
+++ b/spec/lib/gitlab/ci/build/artifacts/metadata_spec.rb
@@ -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