Skip to content

Commit 3e77d41

Browse files
authored
Purge explicit packs on solution load
1 parent 2054682 commit 3e77d41

10 files changed

Lines changed: 184 additions & 98 deletions

File tree

libs/rtemodel/include/RteModel.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,13 @@ class RteGlobalModel : public RteModel
616616
*/
617617
void ClearModel() override;
618618

619+
/**
620+
* @brief purges non-existing packs and optionally explicit packs; clears model and projects if at least one pack was removed
621+
* @param purgeExplicit when true, remove all PackageState::PS_EXPLICIT_PATH packs
622+
* @returns true if at least one pack has been removed
623+
*/
624+
bool PurgeModel(bool purgeExplicit);
625+
619626
/**
620627
* @brief setter for RteCallback object
621628
* @param callback given RteCallback object to set

libs/rtemodel/include/RtePackage.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,10 +1336,11 @@ class RtePackRegistry
13361336
bool ErasePack(const std::string& pdscFile);
13371337

13381338
/**
1339-
* @brief removes all non-existing packs
1339+
* @brief removes all non-existing packs and optionally explicitly specified packs
1340+
* @param purgeExplicit flag to remove all PackageState::PS_EXPLICIT_PATH packs
13401341
* @return true if at least one pack was removed
13411342
*/
1342-
bool PurgePacks();
1343+
bool PurgePacks(bool purgeExplicit);
13431344

13441345
/**
13451346
* @brief get collection of loaded packs

libs/rtemodel/src/RteKernel.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -451,8 +451,6 @@ bool RteKernel::GetEffectivePdscFilesAsMap(map<string, string, RtePackageCompara
451451

452452
bool RteKernel::GetEffectivePdscFiles(std::list<std::string>& pdscFiles, bool latest) const
453453
{
454-
GetPackRegistry()->PurgePacks(); // remove non-existing files from the registry
455-
456454
map<string, string, RtePackageComparator> pdscMap;
457455
if(!GetEffectivePdscFilesAsMap(pdscMap, latest)) {
458456
return false;
@@ -477,11 +475,7 @@ bool RteKernel::LoadAndInsertPacks(std::list<RtePackage*>& packs, std::list<std:
477475
if(!pack) {
478476
return false;
479477
}
480-
// pack with explicit path must override installed pack
481-
auto loadedPack = RtePackage::GetPackFromList(pack->GetID(), packs);
482-
if(!loadedPack || (loadedPack->GetPackageState() == PS_INSTALLED && pack->GetPackageState() == PS_EXPLICIT_PATH)) {
483-
newPacks.push_back(pack);
484-
}
478+
newPacks.push_back(pack);
485479
}
486480
globalModel->InsertPacks(newPacks);
487481

libs/rtemodel/src/RteModel.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -392,17 +392,9 @@ void RteModel::InsertPack(RtePackage* package)
392392
}
393393
auto state = package->GetPackageState();
394394
if(insertedPack->GetPackageState() == state) {
395-
string pdscPath = RteFsUtils::MakePathCanonical(package->GetAbsolutePackagePath());
396-
if(pdscPath.find(m_rtePath) == 0) { // regular installed pack => error
397395
// duplicate, kept it in a temporary collection till validate;
398-
m_packageDuplicates.push_back(package);
399-
return;
400-
}
401-
string insertedPdscPath = RteFsUtils::MakePathCanonical(insertedPack->GetAbsolutePackagePath());
402-
if(insertedPdscPath.find(m_rtePath) == string::npos) { // inserted pack is also from outside => error
403-
m_packageDuplicates.push_back(package);
404-
return;
405-
}
396+
m_packageDuplicates.push_back(package);
397+
return;
406398
} else if(state != PS_EXPLICIT_PATH) {
407399
return; // pack with explicit path must override installed pack
408400
}
@@ -842,7 +834,14 @@ void RteGlobalModel::ClearModel()
842834
{
843835
ClearProjectTargets();
844836
RteModel::ClearModel();
845-
m_packRegistry->PurgePacks(); // pack loading is expensive, only remove deleted
837+
}
838+
839+
bool RteGlobalModel::PurgeModel(bool purgeExplicit) {
840+
if(m_packRegistry->PurgePacks(purgeExplicit)) {
841+
Clear();
842+
return true;
843+
}
844+
return false;
846845
}
847846

848847

libs/rtemodel/src/RtePackage.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1525,13 +1525,13 @@ bool RtePackRegistry::ErasePack(const std::string& pdscFile)
15251525
return false;
15261526
}
15271527

1528-
bool RtePackRegistry::PurgePacks() {
1528+
bool RtePackRegistry::PurgePacks(bool purgeExplicit) {
15291529
ClearPdscMap(); // clear because packs can be added or removed after this call
15301530

15311531
set<string> toErase;
15321532
// collect packs that no longer exist
15331533
for(auto& [pdscFile, pack] : m_loadedPacks) {
1534-
if(!pack || !pack->Exists()) {
1534+
if(!pack || !pack->Exists() || (purgeExplicit && pack->GetPackageState() == PackageState::PS_EXPLICIT_PATH )) {
15351535
toErase.insert(pdscFile);
15361536
}
15371537
}

libs/rtemodel/test/src/RteModelTest.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@ TEST_F(RteModelTestConfig, PackRegistry) {
4040
EXPECT_TRUE(packRegistry->AddPack(pack));
4141
EXPECT_FALSE(packRegistry->AddPack(pack)); // not second time
4242
EXPECT_EQ(packRegistry->GetPack("foo"), pack);
43-
pack = new RtePackage(&testModel);
43+
pack = new RtePackage(&testModel, PackageState::PS_EXPLICIT_PATH);
4444
pack->SetAttribute("name", "bar");
4545
pack->SetRootFileName("foo");
4646
EXPECT_TRUE(packRegistry->AddPack(pack, true));
4747
EXPECT_EQ(packRegistry->GetPack("foo"), pack);
4848
EXPECT_EQ(packRegistry->GetLoadedPacks().size(), 1);
4949

50-
EXPECT_TRUE(packRegistry->PurgePacks());
50+
EXPECT_TRUE(packRegistry->PurgePacks(false)); // deleted because not exists
5151
EXPECT_EQ(packRegistry->GetPack("foo"), nullptr);
5252
EXPECT_FALSE(packRegistry->ErasePack("foo")); // already erased via Purge
5353
EXPECT_EQ(packRegistry->GetLoadedPacks().size(), 0);
@@ -128,6 +128,13 @@ TEST_F(RteModelTestConfig, PackRegistryLoadPacks) {
128128
auto t1 = pack1->GetModificationTime();
129129
EXPECT_NE(t, t1);
130130
EXPECT_EQ(pack1->GetFirstChild("dummy_child"), nullptr); // pack got loaded again => no added child
131+
132+
// test RteGlobalModel::PurgeModel
133+
pack1->SetPackageState(PackageState::PS_EXPLICIT_PATH); // simulate pack is explicit
134+
auto globalModel = rteKernel.GetGlobalModel();
135+
136+
EXPECT_FALSE(globalModel->PurgeModel(false));
137+
EXPECT_TRUE(globalModel->PurgeModel(true));
131138
}
132139

133140
TEST(RteModelTest, LoadPacks) {

tools/projmgr/src/ProjMgrRpcServer.cpp

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,10 @@ RpcArgs::SuccessResult RpcHandler::LoadPacks(void) {
305305
m_manager.Clear();
306306
m_solutionLoaded = false;
307307
// clear project and global RTE data, packs stay loaded
308-
ProjMgrKernel::Get()->GetGlobalModel()->Clear();
308+
auto globalModel = ProjMgrKernel::Get()->GetGlobalModel();
309+
globalModel->Clear();
310+
globalModel->PurgeModel(true); // clears also explicit and non-existing packs
311+
309312
m_worker.InitializeModel();
310313
m_worker.SetLoadPacksPolicy(LoadPacksPolicy::ALL);
311314
result.success = m_worker.LoadAllRelevantPacks();
@@ -319,15 +322,30 @@ RpcArgs::SuccessResult RpcHandler::LoadPacks(void) {
319322
RpcArgs::SuccessResult RpcHandler::LoadSolution(const string& solution, const string& activeTarget) {
320323
m_bUseAllPacks = false; // loading solution will first use only listed packs
321324
m_packReferences.clear(); // will be updated
325+
m_manager.Clear();
322326
m_solutionLoaded = false; // assume not loaded yet
323-
// clear only projects, global RTE data and packs stay loaded
324-
ProjMgrKernel::Get()->GetGlobalModel()->ClearProjects();
327+
auto globalModel = ProjMgrKernel::Get()->GetGlobalModel();
328+
// remove non-existing and explicit packs
329+
// clear model and projects if at least one pack is deleted
330+
bool purged = globalModel->PurgeModel(true);
331+
if(!purged) {
332+
// only projects, global RTE data and packs stay loaded
333+
globalModel->ClearProjects();
334+
}
335+
325336
RpcArgs::SuccessResult result = {false};
326337
const auto csolutionFile = RteFsUtils::MakePathCanonical(solution);
327338
if(!regex_match(csolutionFile, regex(".*\\.csolution\\.(yml|yaml)"))) {
328339
result.message = solution + " is not a *.csolution.yml file";
329340
return result;
330341
}
342+
if(purged) {
343+
// we need to add available packs to model again (the packs are already loaded)
344+
m_worker.InitializeModel();
345+
m_worker.SetLoadPacksPolicy(LoadPacksPolicy::ALL);
346+
result.success = m_worker.LoadAllRelevantPacks();
347+
m_worker.SetLoadPacksPolicy(LoadPacksPolicy::DEFAULT);
348+
}
331349
// we disregard return value of m_manager.LoadSolution() here, because we tolerate some errors
332350
m_manager.LoadSolution(csolutionFile, activeTarget);
333351
map<string, ContextItem>* contexts = nullptr;
@@ -870,8 +888,15 @@ RpcArgs::ConvertSolutionResult RpcHandler::ConvertSolution(const string& solutio
870888
m_bUseAllPacks = false; // loading solution will first use only listed packs
871889
m_packReferences.clear(); // will be updated
872890
m_solutionLoaded = false; // assume not loaded
873-
// clear only projects, RTE data and packs stay loaded
874-
ProjMgrKernel::Get()->GetGlobalModel()->ClearProjects();
891+
m_manager.Clear();
892+
auto globalModel = ProjMgrKernel::Get()->GetGlobalModel();
893+
// remove non-existing and explicit packs
894+
// clear model and projects if at least one pack is deleted
895+
bool purged = globalModel->PurgeModel(true);
896+
if(!purged) {
897+
// only projects, global RTE data and packs stay loaded
898+
globalModel->ClearProjects();
899+
}
875900

876901
if(!m_manager.RunConvert(csolutionFile, activeTarget, updateRte) || !ProjMgrLogger::Get().GetErrors().empty()) {
877902
if(m_worker.HasVarDefineError()) {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# yaml-language-server: $schema=https://raw.githubusercontent.com/Open-CMSIS-Pack/devtools/main/tools/projmgr/schemas/csolution.schema.json
2+
3+
solution:
4+
target-types:
5+
- type: CM0
6+
device: RteTest_ARMCM0
7+
8+
packs:
9+
- pack: ARM::RteTest_DFP
10+
path: ../SolutionSpecificPack1
11+
12+
projects:
13+
- project: pack_path.cproject.yml

0 commit comments

Comments
 (0)