Skip to content

Commit

Permalink
[csolution] Add list configs command to list configuration files #922 (
Browse files Browse the repository at this point in the history
…#661) (#1074)

* [csolution] Add list configs command to list configuration files #922

Co-authored-by: Evgueni Driouk <[email protected]>
  • Loading branch information
grasci-arm and edriouk authored Jul 25, 2023
1 parent f7bb38a commit cc0078c
Show file tree
Hide file tree
Showing 10 changed files with 191 additions and 28 deletions.
9 changes: 9 additions & 0 deletions libs/rtemodel/include/RteInstance.h
Original file line number Diff line number Diff line change
Expand Up @@ -1423,6 +1423,15 @@ class RteFileInstance : public RteItemInstance
*/
int HasNewVersion() const;

/**
* @brief creates an info string of the config file (for specified target)
RTE folder path used for placing files is taken from target's parent project
* @param targetName target name
* @param relativeTo calculate relative path to the supplied if not empty, otherwise to project
* @return info string
*/
std::string GetInfoString(const std::string& targetName, const std::string& relativeTo = RteUtils::EMPTY_STRING) const;

/**
* @brief get file category
* @return RteFile::Category value
Expand Down
42 changes: 42 additions & 0 deletions libs/rtemodel/src/RteInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "RteModel.h"
#include "RteProject.h"

#include "RteConstants.h"
#include "RteFsUtils.h"
#include "XMLTree.h"

Expand Down Expand Up @@ -779,6 +780,47 @@ int RteFileInstance::HasNewVersion() const
return newVersion;
}

std::string RteFileInstance::GetInfoString(const std::string& targetName, const string& relativeTo) const
{
string info;
string absPath = GetAbsolutePath();
if (!relativeTo.empty()) {
info = RteFsUtils::RelativePath(absPath, relativeTo);
} else {
info = GetInstanceName();
}

const string& baseVersion = GetAttribute("version"); // explicitly check the file instance version
if (!baseVersion.empty()) {
info += RteConstants::PREFIX_CVERSION;
info += baseVersion;
}
RteFile* f = GetFile(targetName);
const string& updateVersion = f ? f->GetVersionString() : RteUtils::EMPTY_STRING;

string state;
if (!RteFsUtils::Exists(absPath)) {
state = "not exist";
} else if (!updateVersion.empty()) {
if (VersionCmp::Compare(baseVersion, updateVersion) == 0) {
state = "up to date";
} else {
state = "update";
state += RteConstants::PREFIX_CVERSION;
state += updateVersion;
}
}
if (!state.empty()) {
info += RteConstants::SPACE_STR;
info += RteConstants::OBRACE_STR;
info += state;
info += RteConstants::CBRACE_STR;
}
info += " from ";
info += GetComponentID(true);
return info;
}

RteComponentInstance* RteFileInstance::GetComponentInstance(const string& targetName) const
{
RteProject* project = GetProject();
Expand Down
41 changes: 22 additions & 19 deletions libs/rtemodel/src/RteProject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -463,9 +463,7 @@ void RteProject::InitFileInstance(RteFileInstance* fi, RteFile* f, int index, Rt
fi->SetRemoved(false);
string absPath = fi->GetAbsolutePath();
bool bExists = RteFsUtils::Exists(absPath);
if (!bExists) {
UpdateFileInstance(fi, f, false, false);
} else {
if (bExists) {
UpdateFileInstanceVersion(fi, savedVersion);
}
UpdateConfigFileBackups(fi, f);
Expand Down Expand Up @@ -943,25 +941,30 @@ void RteProject::Update()
}
}

// add forced copy files
for (auto itf = forcedFiles.begin(); itf != forcedFiles.end(); itf++) {
RteFile* f = *itf;
string dst = GetProjectPath() + f->GetInstancePathName(EMPTY_STRING, 0, GetRteFolder());
// copy files if update is enabled
if (ShouldUpdateRte()) {
for (auto itt = m_targets.begin(); itt != m_targets.end(); itt++) {
WriteInstanceFiles(itt->first);
}
// add forced copy files
for (auto itf = forcedFiles.begin(); itf != forcedFiles.end(); itf++) {
RteFile* f = *itf;
string dst = GetProjectPath() + f->GetInstancePathName(EMPTY_STRING, 0, GetRteFolder());

error_code ec;
if (fs::exists(dst, ec))
continue;
string src = f->GetOriginalAbsolutePath();
if (!RteFsUtils::CopyCheckFile(src, dst, false)) {
string str = "Error: cannot copy file\n";
str += src;
str += "\n to\n";
str += dst;
str += "\nOperation failed\n";
GetCallback()->OutputErrMessage(str);
error_code ec;
if (fs::exists(dst, ec))
continue;
string src = f->GetOriginalAbsolutePath();
if (!RteFsUtils::CopyCheckFile(src, dst, false)) {
string str = "Error: cannot copy file\n";
str += src;
str += "\n to\n";
str += dst;
str += "\nOperation failed\n";
GetCallback()->OutputErrMessage(str);
}
}
}

CollectSettings();
}

Expand Down
34 changes: 29 additions & 5 deletions libs/rtemodel/test/src/RteModelTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,17 @@ TEST_F(RteModelPrjTest, LoadCprj) {
const string CompConfig_1_Base_Version = rteDir + "RteTest/" + "[email protected]";
EXPECT_TRUE(RteFsUtils::Exists(CompConfig_0_Base_Version));
EXPECT_TRUE(RteFsUtils::Exists(CompConfig_1_Base_Version));
RteFileInstance * fi = activeCprjProject->GetFileInstance("RTE/RteTest/ComponentLevelConfig_0.h");
ASSERT_NE(fi, nullptr);
EXPECT_EQ(fi->GetInfoString(activeTarget->GetName()),
"RTE/RteTest/[email protected] (up to date) from ARM::RteTest:[email protected]");
EXPECT_EQ(fi->GetInfoString(activeTarget->GetName(), prjsDir),
"RteTestM3/RTE/RteTest/[email protected] (up to date) from ARM::RteTest:[email protected]");

ASSERT_NE(fi, nullptr);
fi = activeCprjProject->GetFileInstance("RTE/RteTest/ComponentLevelConfig_1.h");
EXPECT_EQ(fi->GetInfoString(activeTarget->GetName()),
"RTE/RteTest/[email protected] (up to date) from ARM::RteTest:[email protected]");
error_code ec;
const fs::perms write_mask = fs::perms::owner_write | fs::perms::group_write | fs::perms::others_write;
// check config file PLM: existence and permissions
Expand All @@ -337,6 +347,10 @@ TEST_F(RteModelPrjTest, LoadCprj) {
EXPECT_EQ((fs::status(deviceDir + "[email protected]", ec).permissions() & write_mask), fs::perms::none);

EXPECT_FALSE(RteFsUtils::Exists(deviceDir + "[email protected]"));
fi = activeCprjProject->GetFileInstance("RTE/Device/RteTest_ARMCM3/system_ARMCM3.c");
ASSERT_NE(fi, nullptr);
EXPECT_EQ(fi->GetInfoString(activeTarget->GetName()),
"RTE/Device/RteTest_ARMCM3/[email protected] ([email protected]) from ARM::Device:Startup&RteTest [email protected]");
}

TEST_F(RteModelPrjTest, LoadCprj_NoRTEFileCreation) {
Expand All @@ -345,30 +359,40 @@ TEST_F(RteModelPrjTest, LoadCprj_NoRTEFileCreation) {
rteKernel.SetCmsisPackRoot(RteModelTestConfig::CMSIS_PACK_ROOT);
RteCprjProject* loadedCprjProject = rteKernel.LoadCprj(RteTestM3_cprj, RteUtils::EMPTY_STRING, true, false);
ASSERT_NE(loadedCprjProject, nullptr);
RteTarget* activeTarget = loadedCprjProject->GetActiveTarget();
ASSERT_NE(activeTarget, nullptr);

const string rteDir = RteUtils::ExtractFilePath(RteTestM3_cprj, true) + "RTE/";
const string CompConfig_0_Base_Version = rteDir + "RteTest/" + "[email protected]";
const string CompConfig_1_Base_Version = rteDir + "RteTest/" + "[email protected]";
EXPECT_FALSE(RteFsUtils::Exists(CompConfig_0_Base_Version));
EXPECT_FALSE(RteFsUtils::Exists(CompConfig_1_Base_Version));
RteFileInstance* fi = loadedCprjProject->GetFileInstance("RTE/RteTest/ComponentLevelConfig_0.h");
ASSERT_NE(fi, nullptr);
EXPECT_EQ(fi->GetInfoString(activeTarget->GetName()),
"RTE/RteTest/[email protected] (up to date) from ARM::RteTest:[email protected]");

const string deviceDir = rteDir + "Device/RteTest_ARMCM3/";
EXPECT_FALSE(RteFsUtils::Exists(deviceDir + "[email protected]"));
EXPECT_FALSE(RteFsUtils::Exists(deviceDir + "[email protected]"));
EXPECT_FALSE(RteFsUtils::Exists(deviceDir + "[email protected]"));

fi = loadedCprjProject->GetFileInstance("RTE/Device/RteTest_ARMCM3/system_ARMCM3.c");
ASSERT_NE(fi, nullptr);
EXPECT_EQ(fi->GetInfoString(activeTarget->GetName()),
"RTE/Device/RteTest_ARMCM3/[email protected] ([email protected]) from ARM::Device:Startup&RteTest [email protected]");
RteFsUtils::RemoveFile(fi->GetAbsolutePath());
EXPECT_EQ(fi->GetInfoString(activeTarget->GetName()),
"RTE/Device/RteTest_ARMCM3/[email protected] (not exist) from ARM::Device:Startup&RteTest [email protected]");

// additionally test support for RTE folder with spaces
auto& fileInstances= loadedCprjProject->GetFileInstances();
// take existing file instance
auto it = fileInstances.find("RTE/Device/RteTest_ARMCM3/startup_ARMCM3.c");
RteFileInstance* fi = it != fileInstances.end() ? it->second : nullptr;
ASSERT_NE(fi, nullptr);
// use its file to create path with another RTE directory
RteFile* f = fi ? fi->GetFile(loadedCprjProject->GetActiveTargetName()) : nullptr ;
ASSERT_NE(f, nullptr);
const string& deviceName = loadedCprjProject->GetActiveTarget()->GetDeviceName();
string pathName = f->GetInstancePathName(deviceName, 0 , "RTE With Spaces");
EXPECT_EQ(pathName, "RTE With Spaces/Device/RteTest_ARMCM3/startup_ARMCM3.c");
EXPECT_EQ(pathName, "RTE With Spaces/Device/RteTest_ARMCM3/system_ARMCM3.c");
}

TEST_F(RteModelPrjTest, LoadCprj_PackPath) {
Expand Down
3 changes: 3 additions & 0 deletions libs/rteutils/include/RteConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ class RteConstants
static constexpr const char* CSQBRACE_STR = "]";
static constexpr const char CSQBRACE_CHAR = ']';

static constexpr const char* SPACE_STR = " ";
static constexpr const char SPACE_CHAR = ' ';


static constexpr const char* COMPONENT_DELIMITERS = ":&@";

Expand Down
1 change: 1 addition & 0 deletions tools/projmgr/include/ProjMgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ class ProjMgr {
bool RunListBoards(void);
bool RunListDevices(void);
bool RunListComponents(void);
bool RunListConfigs(void);
bool RunListDependencies(void);
bool RunListContexts(void);
bool RunListGenerators(void);
Expand Down
8 changes: 8 additions & 0 deletions tools/projmgr/include/ProjMgrWorker.h
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,14 @@ class ProjMgrWorker {
*/
bool ListComponents(std::vector<std::string>& components, const std::string& filter = RteUtils::EMPTY_STRING);

/**
* @brief list configuration files
* @param reference to list of file description strings
* @param filter words to filter results
* @return true if executed successfully
*/
bool ListConfigs(std::vector<std::string>& dependencies, const std::string& filter = RteUtils::EMPTY_STRING);

/**
* @brief list available dependencies
* @param reference to list of dependencies
Expand Down
30 changes: 29 additions & 1 deletion tools/projmgr/src/ProjMgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Usage:\n\
Commands:\n\
convert Convert user input *.yml files to *.cprj files\n\
list boards Print list of available board names\n\
list configs Print list of configuration files\n\
list contexts Print list of contexts in a <name>.csolution.yml\n\
list components Print list of available components\n\
list dependencies Print list of unresolved project dependencies\n\
Expand Down Expand Up @@ -147,6 +148,7 @@ int ProjMgr::RunProjMgr(int argc, char **argv, char** envp) {
{"list packs", { true, {context, debug, filter, load, missing, schemaCheck, toolchain, verbose}}},
{"list boards", { true, {context, debug, filter, load, schemaCheck, toolchain, verbose}}},
{"list devices", { true, {context, debug, filter, load, schemaCheck, toolchain, verbose}}},
{"list configs", { true, {context, debug, filter, load, schemaCheck, toolchain, verbose}}},
{"list components", { true, {context, debug, filter, load, schemaCheck, toolchain, verbose}}},
{"list dependencies", { false, {context, debug, filter, load, schemaCheck, toolchain, verbose}}},
{"list contexts", { false, {debug, filter, schemaCheck, verbose, ymlOrder}}},
Expand Down Expand Up @@ -292,6 +294,10 @@ int ProjMgr::RunProjMgr(int argc, char **argv, char** envp) {
if (!manager.RunListComponents()) {
return 1;
}
} else if (manager.m_args == "configs") {
if (!manager.RunListConfigs()) {
return 1;
}
} else if (manager.m_args == "dependencies") {
if (!manager.RunListDependencies()) {
return 1;
Expand Down Expand Up @@ -600,6 +606,28 @@ bool ProjMgr::RunListComponents(void) {
return true;
}

bool ProjMgr::RunListConfigs() {
if (!m_csolutionFile.empty()) {
// Parse all input files and create contexts
if (!PopulateContexts()) {
return false;
}
}
// Parse context selection
if (!m_worker.ParseContextSelection(m_context, m_contextReplacement)) {
return false;
}
vector<string> configFiles;
if (!m_worker.ListConfigs(configFiles, m_filter)) {
ProjMgrLogger::Error("processing config list failed");
return false;
}
for (const auto& configFile : configFiles) {
cout << configFile << endl;
}
return true;
}

bool ProjMgr::RunListDependencies(void) {
// Parse all input files and create contexts
if (!PopulateContexts()) {
Expand Down Expand Up @@ -743,7 +771,7 @@ bool ProjMgr::RunListEnvironment(void) {
cout << "CMSIS_COMPILER_ROOT=" << (env.cmsis_compiler_root.empty() ? notFound : env.cmsis_compiler_root) << endl;
CrossPlatformUtils::REG_STATUS status = CrossPlatformUtils::GetLongPathRegStatus();
if (status != CrossPlatformUtils::REG_STATUS::NOT_SUPPORTED) {
cout << "Long pathname support=" <<
cout << "Long pathname support=" <<
(status == CrossPlatformUtils::REG_STATUS::ENABLED ? "enabled" : "disabled") << endl;
}
return true;
Expand Down
26 changes: 26 additions & 0 deletions tools/projmgr/src/ProjMgrWorker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2862,6 +2862,32 @@ bool ProjMgrWorker::ListComponents(vector<string>& components, const string& fil
return true;
}

bool ProjMgrWorker::ListConfigs(vector<string>& configFiles, const string& filter) {
set<string>configSet;
for (const auto& selectedContext : m_selectedContexts) {
ContextItem& context = m_contexts[selectedContext];
if (!ProcessContext(context, true, false, false)) {
return false;
}
const string& targetName = context.rteActiveTarget->GetName();
for (auto [_, fi] : context.rteActiveProject->GetFileInstances()) {
configSet.insert(fi->GetInfoString(targetName, context.csolution->path));
}
}
vector<string> configVec(configSet.begin(), configSet.end());
if (!filter.empty()) {
vector<string> filteredConfigs;
ApplyFilter(configVec, SplitArgs(filter), filteredConfigs);
if (filteredConfigs.empty()) {
ProjMgrLogger::Error("no unresolved dependency was found with filter '" + filter + "'");
return false;
}
configVec = filteredConfigs;
}
configFiles.assign(configVec.begin(), configVec.end());
return true;
}

bool ProjMgrWorker::ListDependencies(vector<string>& dependencies, const string& filter) {
RteCondition::SetVerboseFlags(m_verbose ? VERBOSE_DEPENDENCY : m_debug ? VERBOSE_FILTER | VERBOSE_DEPENDENCY : 0);
set<string>dependenciesSet;
Expand Down
25 changes: 22 additions & 3 deletions tools/projmgr/test/src/ProjMgrUnitTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3264,16 +3264,17 @@ TEST_F(ProjMgrUnitTests, RunProjMgr_ContextMap) {
}

TEST_F(ProjMgrUnitTests, RunProjMgr_UpdateRte) {
char* argv[8];
const string rteDir = testinput_folder + "/TestSolution/TestProject1/RTE/";
const string configFile = rteDir + "Device/RteTest_ARMCM0/startup_ARMCM0.c";
const string baseFile = configFile + "[email protected]";
RteFsUtils::RemoveDir(rteDir);
RteFsUtils::CreateFile(configFile, "");
RteFsUtils::CreateFile(baseFile, "");
RteFsUtils::CreateFile(configFile, "// config file");
RteFsUtils::CreateFile(baseFile, "// config file@base");

StdStreamRedirect streamRedirect;
string csolutionFile = testinput_folder + "/TestSolution/test.csolution.yml";
char* argv[9];
argv[0] = (char*)"";
argv[1] = (char*)"update-rte";
argv[2] = (char*)csolutionFile.c_str();
argv[3] = (char*)"-c";
Expand All @@ -3295,6 +3296,24 @@ info csolution: config files for each component:\n\

auto outStr = streamRedirect.GetOutString();
EXPECT_TRUE(regex_match(outStr, regex(expected)));

streamRedirect.ClearStringStreams();
argv[1] = (char*)"list";
argv[2] = (char*)"configs";
argv[3] = (char*)csolutionFile.c_str();
argv[4] = (char*)"-c";
argv[5] = (char*)"test1.Debug+CM0";
argv[6] = (char*)"-o";
argv[7] = (char*)testoutput_folder.c_str();
argv[8] = (char*)"-v";
EXPECT_EQ(0, RunProjMgr(9, argv, 0));

outStr = streamRedirect.GetOutString();
const string expected1 =
"../TestProject1/RTE/Device/RteTest_ARMCM0/[email protected] (up to date) from ARM::Device:Startup&RteTest [email protected]\n"\
"../TestProject1/RTE/Device/RteTest_ARMCM0/[email protected] ([email protected]) from ARM::Device:Startup&RteTest [email protected]\n"\
"../TestProject1/RTE/Device/RteTest_ARMCM0/[email protected] (up to date) from ARM::Device:Startup&RteTest [email protected]\n";
EXPECT_EQ(outStr, expected1);
}

TEST_F(ProjMgrUnitTests, RunProjMgr_No_target_Types) {
Expand Down

0 comments on commit cc0078c

Please sign in to comment.