diff --git a/lib/review/yamlloader.rb b/lib/review/yamlloader.rb index 5f976de0c..68ff0c3d2 100644 --- a/lib/review/yamlloader.rb +++ b/lib/review/yamlloader.rb @@ -5,30 +5,42 @@ class YAMLLoader def initialize end + # load YAML files + # + # `inherit: [3.yml, 6.yml]` in 7.yml; `inherit: [1.yml, 2.yml]` in 3.yml; `inherit: [4.yml, 5.yml]` in 6.yml + # => 7.yml > 6.yml > 5.yml > 4.yml > 3.yml > 2.yml > 1.yml + # def load_file(yamlfile) - current_file = yamlfile + file_queue = [File.expand_path(yamlfile)] loaded_files = {} yaml = {} loop do - current_yaml = YAML.load_file(current_file) - yaml = current_yaml.deep_merge(yaml) - # Check exit condition - if !yaml.key?('inherit') + if file_queue.empty? return yaml end - inherit_file = File.expand_path(yaml['inherit'], File.dirname(yamlfile)) - - # Check loop - if loaded_files[inherit_file] - raise "Found circular YAML inheritance '#{inherit_file}' in #{yamlfile}." + current_file = file_queue.shift + current_yaml = YAML.load_file(current_file) + yaml = current_yaml.deep_merge(yaml) + + if yaml.key?('inherit') + buf = [] + yaml['inherit'].reverse_each do |item| + inherit_file = File.expand_path(item, File.dirname(yamlfile)) + + # Check loop + if loaded_files[inherit_file] + raise "Found circular YAML inheritance '#{inherit_file}' in #{yamlfile}." + end + + loaded_files[inherit_file] = true + buf << inherit_file + end + yaml.delete('inherit') + file_queue = buf + file_queue end - - loaded_files[inherit_file] = true - yaml.delete('inherit') - current_file = inherit_file end end end diff --git a/test/test_yamlloader.rb b/test/test_yamlloader.rb index e792dcd7f..eaaa49774 100644 --- a/test/test_yamlloader.rb +++ b/test/test_yamlloader.rb @@ -33,7 +33,7 @@ def test_load_file_inherit k1: name: "test" array: [{name: "N", val: "V"}] -inherit: "test2.yml" +inherit: ["test2.yml"] EOB end File.open(yaml_file2, "w") do |f| @@ -53,4 +53,134 @@ def test_load_file_inherit yaml) end end + + def test_load_file_inherit2 + Dir.mktmpdir do |dir| + yaml_file = File.join(dir, "test.yml") + yaml_file2 = File.join(dir, "test2.yml") + yaml_file3 = File.join(dir, "test3.yml") + File.open(yaml_file, "w") do |f| + f.write < 2, + "k1" => {"name1"=>"value1-1", "name2"=>"value2-2", "name3"=>"value3-3"}, + "k2" => "B", + "k3" => "C", + }, + yaml) + end + end + + def test_load_file_inherit3 + Dir.mktmpdir do |dir| + yaml_file1 = File.join(dir, "test1.yml") + yaml_file2 = File.join(dir, "test2.yml") + yaml_file3 = File.join(dir, "test3.yml") + yaml_file4 = File.join(dir, "test4.yml") + yaml_file5 = File.join(dir, "test5.yml") + yaml_file6 = File.join(dir, "test6.yml") + yaml_file7 = File.join(dir, "test7.yml") + File.open(yaml_file7, "w") do |f| + f.write < {"name1"=>"N7", + "name2"=>"N6", + "name3"=>"N5", + "name4"=>"N4", + "name5"=>"N3", + "name6"=>"N2", + "name7"=>"N1", + }, + }, + yaml) + end + end end