From 4add6a29b56b3a8804fee3f552533cd22cd7f50e Mon Sep 17 00:00:00 2001 From: Daniel Brondani Date: Thu, 28 May 2026 18:17:12 +0200 Subject: [PATCH 1/3] Extend PackReference with locked and missing nodes --- tools/projmgr/CMakeLists.txt | 4 +-- tools/projmgr/include/ProjMgrWorker.h | 5 +++ tools/projmgr/src/ProjMgrRpcServer.cpp | 16 ++++++--- tools/projmgr/src/ProjMgrWorker.cpp | 6 +++- .../pack_reference_locked.cbuild-pack.yml | 5 +++ .../pack_reference_locked.csolution.yml | 10 ++++++ tools/projmgr/test/src/ProjMgrRpcTests.cpp | 33 +++++++++++++++++++ 7 files changed, 72 insertions(+), 7 deletions(-) create mode 100644 tools/projmgr/test/data/TestSolution/PackLocking/pack_reference_locked.cbuild-pack.yml create mode 100644 tools/projmgr/test/data/TestSolution/PackLocking/pack_reference_locked.csolution.yml diff --git a/tools/projmgr/CMakeLists.txt b/tools/projmgr/CMakeLists.txt index a7f04d926..9d457d650 100644 --- a/tools/projmgr/CMakeLists.txt +++ b/tools/projmgr/CMakeLists.txt @@ -24,8 +24,8 @@ include(FetchContent) FetchContent_Declare( rpc-interface DOWNLOAD_EXTRACT_TIMESTAMP ON - URL https://github.com/Open-CMSIS-Pack/csolution-rpc/releases/download/v0.0.10/csolution-rpc.zip - URL_HASH SHA256=246e1f6e5c1a6e269aeadf37f6bf62897c5bb9d374b7fbfdf0e19af61449379e + URL https://github.com/brondani/csolution-rpc/releases/download/v0.0.11/csolution-rpc.zip + URL_HASH SHA256=a86beedb89e89a8425d93d820a9b971b6ceb73b1beaf1a587f46d28c3927362b ) FetchContent_MakeAvailable(rpc-interface) diff --git a/tools/projmgr/include/ProjMgrWorker.h b/tools/projmgr/include/ProjMgrWorker.h index f95f3740d..672080d2a 100644 --- a/tools/projmgr/include/ProjMgrWorker.h +++ b/tools/projmgr/include/ProjMgrWorker.h @@ -96,6 +96,9 @@ struct ToolchainItem { * pack information pack, * path to pack path, * origin file, + * selected-by entry, + * resolved pack identifier, + * missing flag, */ struct PackageItem { PackInfo pack; @@ -103,6 +106,7 @@ struct PackageItem { std::string origin; std::string selectedBy; std::string resolvedTo; + bool missing = false; }; /** @@ -581,6 +585,7 @@ struct ContextItem { std::set unresolvedComponents; StrMap availablePackVersions; StrMap absPathSequences; + StrVec lockedPacks; }; /** diff --git a/tools/projmgr/src/ProjMgrRpcServer.cpp b/tools/projmgr/src/ProjMgrRpcServer.cpp index 0aad379da..56941e5b4 100644 --- a/tools/projmgr/src/ProjMgrRpcServer.cpp +++ b/tools/projmgr/src/ProjMgrRpcServer.cpp @@ -445,24 +445,32 @@ PackReferenceVector RpcHandler::CollectPackReferences(const string& context) { PackReferenceVector packRefs; auto contextItem = GetContext(context); for(const auto& packItem : contextItem.packRequirements) { - const auto& packId = packItem.resolvedTo; - RpcArgs::PackReference packRef; packRef.pack = packItem.selectedBy; if(!packItem.path.empty()) { packRef.resolvedPack = packItem.selectedBy; packRef.path = packItem.path; - } else if(!packId.empty()) { - packRef.resolvedPack = packId; + } else if(!packItem.resolvedTo.empty()) { + packRef.resolvedPack = packItem.resolvedTo; } packRef.origin = packItem.origin; packRef.selected = true; // initially pack is selected; + const auto& packId = packItem.pack.vendor + "::" + packItem.pack.name + "@" + packItem.pack.version; if(packItem.path.empty() && !packId.empty()) { const auto availableVersionIt = contextItem.availablePackVersions.find(packId); if(availableVersionIt != contextItem.availablePackVersions.end() && !availableVersionIt->second.empty()) { packRef.upgrade = availableVersionIt->second; } } + // set optional 'locked' pack identifier if pack is not resolved and locked pack identifier is tracked + if (packItem.resolvedTo.empty() && find(contextItem.lockedPacks.begin(), + contextItem.lockedPacks.end(), packId) != contextItem.lockedPacks.end()) { + packRef.locked = packId; + } + // set optional 'missing' if pack is not found + if (packItem.missing) { + packRef.missing = true; + } packRefs.push_back(packRef); } return packRefs; diff --git a/tools/projmgr/src/ProjMgrWorker.cpp b/tools/projmgr/src/ProjMgrWorker.cpp index 575603975..7f90b588a 100644 --- a/tools/projmgr/src/ProjMgrWorker.cpp +++ b/tools/projmgr/src/ProjMgrWorker.cpp @@ -411,6 +411,7 @@ bool ProjMgrWorker::CollectRequiredPdscFiles(ContextItem& context, const std::st auto pdsc = m_kernel->GetEffectivePdscFile(attributes); const string& pdscFile = pdsc.second; packItem.resolvedTo = pdsc.first; // store resolved ID if any + packItem.missing = pdsc.first.empty(); if (pdscFile.empty()) { if (!bPackFilter) { std::string packageName = @@ -1861,9 +1862,12 @@ void ProjMgrWorker::ResolvePackRequirement(ContextItem& context, const PackItem& if (!locked.empty()) { // TODO: When wildcards will be fully stored in cbuild-pack there may be multiple matches const auto& lockedId = locked.front(); + CollectionUtils::PushBackUniquely(context.lockedPacks, lockedId); if (lockedId != packId) { // Save available version if different from locked - context.availablePackVersions[lockedId] = package.pack.version; + if (!packId.empty()) { + context.availablePackVersions[lockedId] = package.pack.version; + } // Keep the locked pack packId = lockedId; package.pack.version = RtePackage::VersionFromId(lockedId); diff --git a/tools/projmgr/test/data/TestSolution/PackLocking/pack_reference_locked.cbuild-pack.yml b/tools/projmgr/test/data/TestSolution/PackLocking/pack_reference_locked.cbuild-pack.yml new file mode 100644 index 000000000..a2370b595 --- /dev/null +++ b/tools/projmgr/test/data/TestSolution/PackLocking/pack_reference_locked.cbuild-pack.yml @@ -0,0 +1,5 @@ +cbuild-pack: + resolved-packs: + - resolved-pack: ARM::RteTest_DFP@0.1.0 + selected-by-pack: + - ARM::RteTest_DFP diff --git a/tools/projmgr/test/data/TestSolution/PackLocking/pack_reference_locked.csolution.yml b/tools/projmgr/test/data/TestSolution/PackLocking/pack_reference_locked.csolution.yml new file mode 100644 index 000000000..f80fca762 --- /dev/null +++ b/tools/projmgr/test/data/TestSolution/PackLocking/pack_reference_locked.csolution.yml @@ -0,0 +1,10 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/Open-CMSIS-Pack/devtools/main/tools/projmgr/schemas/csolution.schema.json + +solution: + target-types: + - type: CM0 + device: RteTest_ARMCM0 + packs: + - pack: ARM::RteTest_DFP + projects: + - project: ./project_with_dfp_components.cproject.yml diff --git a/tools/projmgr/test/src/ProjMgrRpcTests.cpp b/tools/projmgr/test/src/ProjMgrRpcTests.cpp index 8fb27af86..ee6452551 100644 --- a/tools/projmgr/test/src/ProjMgrRpcTests.cpp +++ b/tools/projmgr/test/src/ProjMgrRpcTests.cpp @@ -1089,6 +1089,39 @@ TEST_F(ProjMgrRpcTests, RpcGetUsedItemsLocked) { EXPECT_EQ(packs[0]["upgrade"], "0.2.0"); } +TEST_F(ProjMgrRpcTests, PackReferenceLocked) { + string context = "project_with_dfp_components+CM0"; + vector contextList = { context }; + auto requests = CreateLoadRequests("/TestSolution/PackLocking/pack_reference_locked.csolution.yml", "", contextList); + requests += FormatRequest(3, "GetUsedItems", json({ { "context", context } })); + const auto& responses = RunRpcMethods(requests); + EXPECT_TRUE(responses[2]["result"]["success"]); + auto packs = responses[2]["result"]["packs"]; + EXPECT_EQ(packs.size(), 1); + // Locked field should be present as string containing packId + EXPECT_TRUE(packs[0].contains("locked")); + EXPECT_TRUE(packs[0]["locked"].is_string()); + EXPECT_FALSE(packs[0]["locked"].get().empty()); +} + +TEST_F(ProjMgrRpcTests, PackReferenceMissing) { + string context = "project+Miss"; + vector contextList = { context }; + auto requests = CreateLoadRequests("/TestSolution/PackMissing/missing_pack.csolution.yml", "", contextList); + requests += FormatRequest(3, "GetUsedItems", json({{ "context", context }})); + const auto& responses = RunRpcMethods(requests); + EXPECT_TRUE(responses[2]["result"]["success"]); + auto packs = responses[2]["result"]["packs"]; + // Verify missing field for unresolved packs + for(const auto& pack : packs) { + if(!pack.contains("resolvedPack")) { + EXPECT_TRUE(pack.contains("missing")); + EXPECT_TRUE(pack["missing"].is_boolean()); + EXPECT_TRUE(pack["missing"].get()); + } + } +} + TEST_F(ProjMgrRpcTests, RpcGetPacksInfoSimple) { string context = "selectable+CM0"; vector contextList = { From 0596084efa87b6782455aee374e824d9dc852ec2 Mon Sep 17 00:00:00 2001 From: Daniel Brondani Date: Fri, 29 May 2026 09:19:05 +0200 Subject: [PATCH 2/3] Address review comment --- tools/projmgr/test/src/ProjMgrRpcTests.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/projmgr/test/src/ProjMgrRpcTests.cpp b/tools/projmgr/test/src/ProjMgrRpcTests.cpp index ee6452551..6ca9d090b 100644 --- a/tools/projmgr/test/src/ProjMgrRpcTests.cpp +++ b/tools/projmgr/test/src/ProjMgrRpcTests.cpp @@ -1098,10 +1098,9 @@ TEST_F(ProjMgrRpcTests, PackReferenceLocked) { EXPECT_TRUE(responses[2]["result"]["success"]); auto packs = responses[2]["result"]["packs"]; EXPECT_EQ(packs.size(), 1); - // Locked field should be present as string containing packId + // Locked field should be present as string containing locked packId EXPECT_TRUE(packs[0].contains("locked")); - EXPECT_TRUE(packs[0]["locked"].is_string()); - EXPECT_FALSE(packs[0]["locked"].get().empty()); + EXPECT_EQ(packs[0]["locked"], "ARM::RteTest_DFP@0.1.0"); } TEST_F(ProjMgrRpcTests, PackReferenceMissing) { From a4f778a68b3accbce47102c0e3bf9431ab765ffa Mon Sep 17 00:00:00 2001 From: Daniel Brondani Date: Fri, 29 May 2026 18:04:08 +0200 Subject: [PATCH 3/3] Update csolution-rpc hash --- tools/projmgr/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/projmgr/CMakeLists.txt b/tools/projmgr/CMakeLists.txt index 9d457d650..0ce3ae56a 100644 --- a/tools/projmgr/CMakeLists.txt +++ b/tools/projmgr/CMakeLists.txt @@ -24,8 +24,8 @@ include(FetchContent) FetchContent_Declare( rpc-interface DOWNLOAD_EXTRACT_TIMESTAMP ON - URL https://github.com/brondani/csolution-rpc/releases/download/v0.0.11/csolution-rpc.zip - URL_HASH SHA256=a86beedb89e89a8425d93d820a9b971b6ceb73b1beaf1a587f46d28c3927362b + URL https://github.com/Open-CMSIS-Pack/csolution-rpc/releases/download/v0.0.11/csolution-rpc.zip + URL_HASH SHA256=1999e1a158922c319626959384643a8490bac4a716a88fa8868b2fd6701097df ) FetchContent_MakeAvailable(rpc-interface)