Skip to content

Commit 260963d

Browse files
Allowing profile import to either be a single path or a list of paths
1 parent 0ce8213 commit 260963d

File tree

3 files changed

+132
-44
lines changed

3 files changed

+132
-44
lines changed

DefaultYAMLs/Default/g++.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ Languages: ["c++"]
4343
# See "./CommonFileTypes.yaml" for FilesTypes
4444
# FilesTypes: ...
4545

46-
# We can use the "Import" field to import other yaml files. We are importing "FilesTypes" here
46+
# (Optional) We can use the "Import" field to import other yaml files. We are importing "FilesTypes" here.
47+
# Import can either be a single path or a list of paths.
48+
# All the fields in the imported yaml files will be merged together
4749
Import: "./CommonFileTypes.yaml"
4850

4951
# Specify the compiler settings

Src/Tests/ConfigParsingTest.cpp

Lines changed: 84 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,8 @@ int main(int argc, char** argv)
301301
const char* mainConfigYamlStr = R"(
302302
PreferredProfile: "imported-profile"
303303
Profiles:
304-
- Import: "Default/g++.yaml"
304+
- Import: ["Default/gcc.yaml", "Default/gccCompilerLinker.yaml"]
305+
305306
- Name: "second-profile"
306307
FileExtensions: [.cpp, .cc, .cxx]
307308
Languages: ["c++"]
@@ -334,12 +335,15 @@ int main(int argc, char** argv)
334335
LinkTypes: *TypeInfoEntries
335336
)";
336337

337-
const char* importedProfileYamlStr = R"(
338+
const char* importedGccProfileYamlStr = R"(
338339
Name: "imported-profile"
339-
NameAliases: ["gcc"]
340+
NameAliases: ["g++"]
340341
FileExtensions: [.cpp, .cc]
341342
Languages: ["c++"]
342343
Import: "filetypes.yaml"
344+
)";
345+
346+
const char* importedCompilerLinkerYamlStr = R"(
343347
Compiler:
344348
CheckExistence:
345349
DefaultPlatform: "imported-gcc -v"
@@ -387,80 +391,124 @@ int main(int argc, char** argv)
387391
.ReturnsResult();
388392

389393
//Setup filesystem exist for the import yaml files
390-
std::string firstExpectedImportPath = "some/config/dir/Default/g++.yaml";
391-
std::string secondExpectedImportPath = "some/config/dir/Default/filetypes.yaml";
394+
std::string gccExpectedImportPath = "some/config/dir/Default/gcc.yaml";
395+
std::string filetypesExpectedImportPath = "some/config/dir/Default/filetypes.yaml";
396+
std::string gccCompilerLinkerExpectedImportPath =
397+
"some/config/dir/Default/gccCompilerLinker.yaml";
392398

393-
std::shared_ptr<OverrideResult> firstImportFileExistResult =
399+
std::shared_ptr<OverrideResult> gccImportFileExistResult =
394400
CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists)
395401
.WhenCalledWith<const std::string&,
396-
CO_ANY_TYPE>( firstExpectedImportPath,
402+
CO_ANY_TYPE>( gccExpectedImportPath,
397403
CO_ANY)
398404
.Returns<bool>(true)
399405
.ReturnsResult();
400-
std::shared_ptr<OverrideResult> secondImportFileExistResult =
406+
std::shared_ptr<OverrideResult> filetypesImportFileExistResult =
401407
CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists)
402408
.WhenCalledWith<const std::string&,
403-
CO_ANY_TYPE>( secondExpectedImportPath,
409+
CO_ANY_TYPE>( filetypesExpectedImportPath,
404410
CO_ANY)
405411
.Returns<bool>(true)
406412
.ReturnsResult();
413+
std::shared_ptr<OverrideResult> gccCompilerLinkerImportFileExistResult =
414+
CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists)
415+
.WhenCalledWith
416+
<
417+
const std::string&,
418+
CO_ANY_TYPE
419+
>
420+
(
421+
gccCompilerLinkerExpectedImportPath,
422+
CO_ANY
423+
)
424+
.Returns<bool>(true)
425+
.ReturnsResult();
407426

408427
//Record if there's an ifstream created with import paths
409-
void* firstImportIfstreamInstance = nullptr;
410-
void* secondImportIfstreamInstance = nullptr;
411-
std::shared_ptr<OverrideResult> firstImportedFileStreamResult =
428+
void* gccImportIfstreamInstance = nullptr;
429+
void* filetypesImportIfstreamInstance = nullptr;
430+
void* gccCompilerLinkerImportIfstreamInstance = nullptr;
431+
std::shared_ptr<OverrideResult> gccImportedFileStreamResult =
432+
CO_SETUP_OVERRIDE (OverrideInstance, Mock_ifstream)
433+
.WhenCalledWith<const ghc::filesystem::path>
434+
(gccExpectedImportPath)
435+
.Times(1)
436+
.WhenCalledExpectedly_Do
437+
(
438+
[&gccImportIfstreamInstance]
439+
(void* instance, const std::vector<void*>&)
440+
{
441+
gccImportIfstreamInstance = instance;
442+
}
443+
)
444+
.ReturnsResult();
445+
std::shared_ptr<OverrideResult> filetypesImportedFileStreamResult =
412446
CO_SETUP_OVERRIDE (OverrideInstance, Mock_ifstream)
413447
.WhenCalledWith<const ghc::filesystem::path>
414-
(firstExpectedImportPath)
448+
(filetypesExpectedImportPath)
415449
.Times(1)
416450
.WhenCalledExpectedly_Do
417451
(
418-
[&firstImportIfstreamInstance]
452+
[&filetypesImportIfstreamInstance]
419453
(void* instance, const std::vector<void*>&)
420454
{
421-
firstImportIfstreamInstance = instance;
455+
filetypesImportIfstreamInstance = instance;
422456
}
423457
)
424458
.ReturnsResult();
425-
std::shared_ptr<OverrideResult> secondImportedFileStreamResult =
459+
std::shared_ptr<OverrideResult> gccCompilerLinkerImportedFileStreamResult =
426460
CO_SETUP_OVERRIDE (OverrideInstance, Mock_ifstream)
427461
.WhenCalledWith<const ghc::filesystem::path>
428-
(secondExpectedImportPath)
462+
(gccCompilerLinkerExpectedImportPath)
429463
.Times(1)
430464
.WhenCalledExpectedly_Do
431465
(
432-
[&secondImportIfstreamInstance]
466+
[&gccCompilerLinkerImportIfstreamInstance]
433467
(void* instance, const std::vector<void*>&)
434468
{
435-
secondImportIfstreamInstance = instance;
469+
gccCompilerLinkerImportIfstreamInstance = instance;
436470
}
437471
)
438472
.ReturnsResult();
439473

440474
//Mock for rdbuf call with specific path check for import files
441-
std::shared_ptr<OverrideResult> firstImportedFileRdbufResult =
475+
std::shared_ptr<OverrideResult> gccImportedFileRdbufResult =
442476
CO_SETUP_OVERRIDE (OverrideInstance, rdbuf)
443-
.Returns<std::string>(importedProfileYamlStr)
477+
.Returns<std::string>(importedGccProfileYamlStr)
444478
.Times(1)
445479
.If
446480
(
447-
[&firstImportIfstreamInstance]
481+
[&gccImportIfstreamInstance]
448482
(void* instance, const std::vector<void*>&) -> bool
449483
{
450-
return instance == firstImportIfstreamInstance;
484+
return instance == gccImportIfstreamInstance;
451485
}
452486
)
453487
.ReturnsResult();
454-
std::shared_ptr<OverrideResult> secondImportedFileRdbufResult =
488+
std::shared_ptr<OverrideResult> filetypesImportedFileRdbufResult =
455489
CO_SETUP_OVERRIDE (OverrideInstance, rdbuf)
456490
.Returns<std::string>(importedFiletypesYamlStr)
457491
.Times(1)
458492
.If
459493
(
460-
[&secondImportIfstreamInstance]
494+
[&filetypesImportIfstreamInstance]
495+
(void* instance, const std::vector<void*>&) -> bool
496+
{
497+
return instance == filetypesImportIfstreamInstance;
498+
}
499+
)
500+
.ReturnsResult();
501+
std::shared_ptr<OverrideResult> gccCompilerLinkerImportedFileRdbufResult =
502+
CO_SETUP_OVERRIDE (OverrideInstance, rdbuf)
503+
.Returns<std::string>(importedCompilerLinkerYamlStr)
504+
.Times(1)
505+
.If
506+
(
507+
[&gccCompilerLinkerImportIfstreamInstance]
461508
(void* instance, const std::vector<void*>&) -> bool
462509
{
463-
return instance == secondImportIfstreamInstance;
510+
return instance ==
511+
gccCompilerLinkerImportIfstreamInstance;
464512
}
465513
)
466514
.ReturnsResult();
@@ -476,14 +524,17 @@ int main(int argc, char** argv)
476524
);
477525

478526
commonOverrideStatusCheck();
479-
ssTEST_OUTPUT_ASSERT("", firstImportFileExistResult->GetSucceedCount(), 1);
480-
ssTEST_OUTPUT_ASSERT("", secondImportFileExistResult->GetSucceedCount(), 1);
527+
ssTEST_OUTPUT_ASSERT("", gccImportFileExistResult->GetSucceedCount(), 1);
528+
ssTEST_OUTPUT_ASSERT("", filetypesImportFileExistResult->GetSucceedCount(), 1);
529+
ssTEST_OUTPUT_ASSERT("", gccCompilerLinkerImportFileExistResult->GetSucceedCount(), 1);
481530

482-
ssTEST_OUTPUT_ASSERT("", firstImportedFileStreamResult->GetSucceedCount(), 1);
483-
ssTEST_OUTPUT_ASSERT("", secondImportedFileStreamResult->GetSucceedCount(), 1);
531+
ssTEST_OUTPUT_ASSERT("", gccImportedFileStreamResult->GetSucceedCount(), 1);
532+
ssTEST_OUTPUT_ASSERT("", filetypesImportedFileStreamResult->GetSucceedCount(), 1);
533+
ssTEST_OUTPUT_ASSERT("", gccCompilerLinkerImportedFileStreamResult->GetSucceedCount(), 1);
484534

485-
ssTEST_OUTPUT_ASSERT("", firstImportedFileRdbufResult->GetSucceedCount(), 1);
486-
ssTEST_OUTPUT_ASSERT("", secondImportedFileRdbufResult->GetSucceedCount(), 1);
535+
ssTEST_OUTPUT_ASSERT("", gccImportedFileRdbufResult->GetSucceedCount(), 1);
536+
ssTEST_OUTPUT_ASSERT("", filetypesImportedFileRdbufResult->GetSucceedCount(), 1);
537+
ssTEST_OUTPUT_ASSERT("", gccCompilerLinkerImportedFileRdbufResult->GetSucceedCount(), 1);
487538

488539
ssTEST_OUTPUT_ASSERT("ReadUserConfig should succeed", parseResult);
489540
ssTEST_OUTPUT_ASSERT("Should parse 2 profiles (1 imported + 1 inline)", profiles.size(), 2);
@@ -503,7 +554,7 @@ int main(int argc, char** argv)
503554
"file-prefix");
504555
ssTEST_OUTPUT_ASSERT( "First profile should have correct name aliases",
505556
profiles[0].NameAliases.size() == 1 &&
506-
profiles[0].NameAliases.find("gcc") !=
557+
profiles[0].NameAliases.find("g++") !=
507558
profiles[0].NameAliases.end());
508559
ssTEST_OUTPUT_ASSERT( "PreferredProfile should match the imported profile",
509560
preferredProfile,

Src/runcpp2/ConfigParsing.cpp

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,51 @@ namespace
3535
ssLOG_FUNC_INFO();
3636

3737
ghc::filesystem::path currentImportFilePath = configPath;
38-
while(runcpp2::ExistAndHasChild(currentProfileNode, "Import"))
38+
std::stack<ghc::filesystem::path> pathsToImport;
39+
while(runcpp2::ExistAndHasChild(currentProfileNode, "Import") || !pathsToImport.empty())
3940
{
40-
if(!INTERNAL_RUNCPP2_BIT_CONTANTS( currentProfileNode["Import"].type().type,
41-
ryml::NodeType_e::KEYVAL))
41+
//If we import field, we should deal with it instead
42+
if(runcpp2::ExistAndHasChild(currentProfileNode, "Import"))
4243
{
43-
ssLOG_ERROR("Import must be a path to a YAML file");
44-
return false;
44+
const ryml::NodeType_e importNodeType = currentProfileNode["Import"].type().type;
45+
if( !INTERNAL_RUNCPP2_BIT_CONTANTS(importNodeType, ryml::NodeType_e::KEYVAL) &&
46+
!INTERNAL_RUNCPP2_BIT_CONTANTS(importNodeType, ryml::NodeType_e::SEQ))
47+
{
48+
ssLOG_ERROR("Import must be a path or sequence of paths of YAML file(s)");
49+
return false;
50+
}
51+
52+
ghc::filesystem::path currentImportDir = currentImportFilePath;
53+
currentImportDir = currentImportDir.parent_path();
54+
if(currentProfileNode["Import"].is_keyval())
55+
{
56+
pathsToImport.push( currentImportDir /
57+
runcpp2::GetValue(currentProfileNode["Import"]));
58+
}
59+
else
60+
{
61+
if(currentProfileNode["Import"].num_children() == 0)
62+
{
63+
ssLOG_ERROR("An import sequence cannot be an empty");
64+
return false;
65+
}
66+
67+
for(int i = 0; i < currentProfileNode["Import"].num_children(); ++i)
68+
{
69+
if(!currentProfileNode["Import"][i].is_val())
70+
{
71+
ssLOG_ERROR("It must be a sequence of paths");
72+
return false;
73+
}
74+
75+
pathsToImport.push( currentImportDir /
76+
runcpp2::GetValue(currentProfileNode["Import"][i]));
77+
}
78+
}
4579
}
4680

47-
ghc::filesystem::path currentImportDir = currentImportFilePath;
48-
currentImportDir = currentImportDir.parent_path();
49-
currentImportFilePath =
50-
currentImportDir / runcpp2::GetValue(currentProfileNode["Import"]);
81+
currentImportFilePath = pathsToImport.top();
82+
pathsToImport.pop();
5183

5284
std::error_code ec;
5385
if(!ghc::filesystem::exists(currentImportFilePath, ec))
@@ -77,7 +109,10 @@ namespace
77109

78110
//Replace the current import field if the import profile has an import field
79111
if(runcpp2::ExistAndHasChild(importProfileNode, "Import"))
80-
currentProfileNode["Import"] << runcpp2::GetValue(importProfileNode["Import"]);
112+
{
113+
currentProfileNode.remove_child("Import");
114+
importProfileNode["Import"].duplicate(currentProfileNode, {});
115+
}
81116
//Otherwise, remove the current import field
82117
else
83118
currentProfileNode.remove_child("Import");

0 commit comments

Comments
 (0)