mirror of
https://github.com/inspec/inspec
synced 2024-11-23 21:23:29 +00:00
add relative fetcher
This helps reduce any folder structures, weather on disk or in archives, to their relative root paths; i.e. ignore all file-prefixes that are given and go directly to the underlying files, relative to the common folders that contain it
This commit is contained in:
parent
f023d02bbb
commit
c9d1272f49
3 changed files with 113 additions and 2 deletions
|
@ -27,6 +27,66 @@ module Inspec
|
|||
def read(_file)
|
||||
fail "Fetcher #{self} does not implement `read(...)`. This is required."
|
||||
end
|
||||
|
||||
def relative_target
|
||||
RelFetcher.new(self)
|
||||
end
|
||||
end
|
||||
|
||||
class RelFetcher
|
||||
attr_reader :files
|
||||
|
||||
def initialize(fetcher)
|
||||
@parent = fetcher
|
||||
@prefix = get_prefix(fetcher.files)
|
||||
@files = fetcher.files.find_all { |x| x.start_with? @prefix }
|
||||
.map { |x| x[@prefix.length..-1] }
|
||||
end
|
||||
|
||||
def read(file)
|
||||
@parent.read(@prefix + file)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def get_prefix(files)
|
||||
return '' if files.empty?
|
||||
sorted = files.sort_by(&:length)
|
||||
get_folder_prefix(sorted)
|
||||
end
|
||||
|
||||
def get_folder_prefix(files, first_iteration = true)
|
||||
return get_files_prefix(files) if files.length == 1
|
||||
pre = files[0] + File::SEPARATOR
|
||||
rest = files[1..-1]
|
||||
if rest.all? { |i| i.start_with? pre }
|
||||
return get_folder_prefix(rest, false)
|
||||
end
|
||||
return get_files_prefix(files) if first_iteration
|
||||
files
|
||||
end
|
||||
|
||||
def get_files_prefix(files)
|
||||
return '' if files.empty?
|
||||
|
||||
file = files[0]
|
||||
bn = File.basename(file)
|
||||
# no more prefixes
|
||||
return '' if bn == file
|
||||
|
||||
i = file.rindex(bn)
|
||||
prefix = file[0..i-1]
|
||||
|
||||
rest = files.find_all { |f| !f.start_with?(prefix) }
|
||||
return prefix if rest.empty?
|
||||
|
||||
nu_prefix = get_prefix(rest)
|
||||
return nu_prefix if prefix.start_with? nu_prefix
|
||||
# edge case: completely different prefixes; retry prefix detection
|
||||
a = File.dirname(prefix + 'a')
|
||||
b = File.dirname(nu_prefix + 'b')
|
||||
get_prefix([a, b])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,3 +10,52 @@ describe Inspec::Fetcher do
|
|||
res.must_be_kind_of Fetchers::Local
|
||||
end
|
||||
end
|
||||
|
||||
describe Inspec::Plugins::RelFetcher do
|
||||
def fetcher
|
||||
src_fetcher.expects(:files).returns(in_files).at_least_once
|
||||
Inspec::Plugins::RelFetcher.new(src_fetcher)
|
||||
end
|
||||
|
||||
let(:src_fetcher) { mock() }
|
||||
|
||||
IN_AND_OUT = {
|
||||
[] => [],
|
||||
%w{file} => %w{file},
|
||||
# don't prefix just by filename
|
||||
%w{file file_a} => %w{file file_a},
|
||||
%w{path/file path/file_a} => %w{file file_a},
|
||||
%w{path/to/file} => %w{file},
|
||||
%w{/path/to/file} => %w{file},
|
||||
%w{alice bob} => %w{alice bob},
|
||||
# mixed paths
|
||||
%w{x/a y/b} => %w{x/a y/b},
|
||||
%w{/x/a /y/b} => %w{x/a y/b},
|
||||
%w{z/x/a z/y/b} => %w{x/a y/b},
|
||||
%w{/z/x/a /z/y/b} => %w{x/a y/b},
|
||||
# mixed with relative path
|
||||
%w{a path/to/b} => %w{a path/to/b},
|
||||
%w{path/to/b a} => %w{path/to/b a},
|
||||
%w{path/to/b path/a} => %w{to/b a},
|
||||
%w{path/to/b path/a c} => %w{path/to/b path/a c},
|
||||
# mixed with absolute paths
|
||||
%w{/path/to/b /a} => %w{path/to/b a},
|
||||
%w{/path/to/b /path/a} => %w{to/b a},
|
||||
%w{/path/to/b /path/a /c} => %w{path/to/b path/a c},
|
||||
# mixing absolute and relative paths
|
||||
%w{path/a /path/b} => %w{path/a /path/b},
|
||||
%w{/path/a path/b} => %w{/path/a path/b},
|
||||
# extract folder structure buildup
|
||||
%w{/a /a/b /a/b/c} => %w{c},
|
||||
%w{/a /a/b /a/b/c/d/e} => %w{e},
|
||||
}.each do |ins, outs|
|
||||
describe 'empty profile' do
|
||||
let(:in_files) { ins }
|
||||
|
||||
it 'also has no files' do
|
||||
fetcher.files.must_equal outs
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -32,7 +32,8 @@ describe Fetchers::Url do
|
|||
end
|
||||
|
||||
it 'must contain all files' do
|
||||
_(res.files).must_equal ["inspec.yml", "libraries", "libraries/testlib.rb", "controls", "controls/filesystem_spec.rb"]
|
||||
_(res.files).must_equal %w{inspec.yml libraries libraries/testlib.rb
|
||||
controls controls/filesystem_spec.rb}
|
||||
end
|
||||
|
||||
it 'must not read if the file isnt included' do
|
||||
|
@ -60,7 +61,8 @@ describe Fetchers::Url do
|
|||
end
|
||||
|
||||
it 'must contain all files' do
|
||||
_(res.files).must_equal ["inspec.yml", "controls", "controls/filesystem_spec.rb"]
|
||||
_(res.files).must_equal %w{inspec.yml libraries libraries/testlib.rb
|
||||
controls controls/filesystem_spec.rb}
|
||||
end
|
||||
|
||||
it 'must not read if the file isnt included' do
|
||||
|
|
Loading…
Reference in a new issue