@@ -43,13 +43,15 @@ auto dereference(const std::filesystem::path &base,
4343 sourcemeta::core::JSON &input,
4444 const sourcemeta::core::Pointer &location,
4545 std::unordered_set<std::string> &visited,
46- std::unordered_set<std::string> &all_files) -> void {
46+ std::unordered_set<std::string> &all_files, const bool is_root)
47+ -> void {
4748 assert (base.is_absolute ());
4849 if (!input.is_object ()) {
4950 return ;
5051
51- // Read extensions
52- } else if (input.defines (" extends" ) && input.at (" extends" ).is_array ()) {
52+ // Read extensions (only at the top level, not inside contents)
53+ } else if (is_root && input.defines (" extends" ) &&
54+ input.at (" extends" ).is_array ()) {
5355 auto accumulator{sourcemeta::core::JSON::make_object ()};
5456 for (const auto &entry : input.at (" extends" ).as_array ()) {
5557 if (entry.is_string ()) {
@@ -63,7 +65,8 @@ auto dereference(const std::filesystem::path &base,
6365 all_files.emplace (target_path.native ());
6466 auto extension{read_file (base, new_location, target_path)};
6567 if (extension.is_object ()) {
66- dereference (target_path, extension, new_location, visited, all_files);
68+ dereference (target_path, extension, new_location, visited, all_files,
69+ true );
6770 accumulator.merge (std::move (extension).as_object ());
6871 }
6972
@@ -75,7 +78,7 @@ auto dereference(const std::filesystem::path &base,
7578 accumulator.merge (input.as_object ());
7679 input = std::move (accumulator);
7780 assert (!input.defines (" extends" ));
78- dereference (base, input, location, visited, all_files);
81+ dereference (base, input, location, visited, all_files, is_root );
7982
8083 // Read included files
8184 } else if (!location.empty () && input.defines (" include" ) &&
@@ -92,7 +95,7 @@ auto dereference(const std::filesystem::path &base,
9295 }
9396 all_files.emplace (target_path.native ());
9497 input.into (read_file (base, new_location, target_path));
95- dereference (target_path, input, new_location, visited, all_files);
98+ dereference (target_path, input, new_location, visited, all_files, is_root );
9699 visited.erase (target_path.native ());
97100
98101 // Revisit and relativize paths
@@ -117,7 +120,8 @@ auto dereference(const std::filesystem::path &base,
117120 [](const auto &entry) { return entry.first ; });
118121 for (const auto &key : keys) {
119122 dereference (base, input.at (" contents" ).at (key),
120- location.concat ({" contents" , key}), visited, all_files);
123+ location.concat ({" contents" , key}), visited, all_files,
124+ false );
121125 }
122126 }
123127}
@@ -198,7 +202,7 @@ auto Configuration::read(const std::filesystem::path &configuration_path,
198202 configuration_files.emplace (canonical_config);
199203 std::unordered_set<std::string> visited;
200204 visited.emplace (canonical_config);
201- dereference (configuration_path, data, {}, visited, configuration_files);
205+ dereference (configuration_path, data, {}, visited, configuration_files, true );
202206
203207 if (data.is_object () && data.defines (" url" ) && data.defines (" contents" ) &&
204208 data.at (" contents" ).is_object ()) {
0 commit comments