File indexing completed on 2024-05-19 05:42:09
0001 // ct_lvtldr_physicalloader.m.cpp -*-C++-*- 0002 0003 /* 0004 // Copyright 2023 Codethink Ltd <codethink@codethink.co.uk> 0005 // SPDX-License-Identifier: Apache-2.0 0006 // 0007 // Licensed under the Apache License, Version 2.0 (the "License"); 0008 // you may not use this file except in compliance with the License. 0009 // You may obtain a copy of the License at 0010 // 0011 // http://www.apache.org/licenses/LICENSE-2.0 0012 // 0013 // Unless required by applicable law or agreed to in writing, software 0014 // distributed under the License is distributed on an "AS IS" BASIS, 0015 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 0016 // See the License for the specific language governing permissions and 0017 // limitations under the License. 0018 */ 0019 0020 #include <ct_lvtldr_lakosiannode.h> 0021 #include <ct_lvtldr_nodestorage.h> 0022 #include <ct_lvtldr_physicalloader.h> 0023 0024 #include <ct_lvtshr_graphenums.h> 0025 0026 #include <cstdlib> 0027 #include <filesystem> 0028 #include <iostream> 0029 #include <string> 0030 0031 #include <QCommandLineOption> 0032 #include <QCommandLineParser> 0033 #include <QCoreApplication> 0034 #include <QString> 0035 0036 using namespace Codethink; 0037 0038 namespace { 0039 0040 struct CommandLineArgs { 0041 std::filesystem::path dbPath; 0042 lvtshr::DiagramType type = lvtshr::DiagramType::NoneType; 0043 std::string qualifiedName; 0044 bool fwdDeps = false; 0045 bool revDeps = false; 0046 bool extDeps = false; 0047 }; 0048 0049 enum class CommandLineParseResult { 0050 Ok, 0051 Error, 0052 Help, 0053 }; 0054 0055 CommandLineParseResult parseCommandLine(QCommandLineParser& parser, CommandLineArgs& args, std::string& errorMessage) 0056 { 0057 parser.setApplicationDescription("Run physical loader"); 0058 0059 parser.addPositionalArgument("CODE_DATABASE", "Path to the code database (required)"); 0060 0061 const QCommandLineOption helpOption = parser.addHelpOption(); 0062 0063 const QCommandLineOption component("component", "Component graph to load", "QUALIFIED_NAME"); 0064 const QCommandLineOption package("package", "Package graph to load", "QUALIFIED_NAME"); 0065 const QCommandLineOption group("group", "Package group graph to load", "QUALIFIED_NAME"); 0066 0067 const QCommandLineOption fwdDeps("fwdDeps", "Enable forward dependencies"); 0068 const QCommandLineOption revDeps("revDeps", "Enable reverse dependencies"); 0069 const QCommandLineOption extDeps("extDeps", "Enable external dependencies"); 0070 0071 parser.addOptions({component, package, group, fwdDeps, revDeps, extDeps}); 0072 0073 if (!parser.parse(QCoreApplication::arguments())) { 0074 errorMessage = qPrintable(parser.errorText()); 0075 return CommandLineParseResult::Error; 0076 } 0077 0078 if (parser.isSet(helpOption)) { 0079 return CommandLineParseResult::Help; 0080 } 0081 0082 // positional arguments 0083 const QStringList posArgs = parser.positionalArguments(); 0084 if (posArgs.empty()) { 0085 errorMessage = "Missing CODE_DATABASE"; 0086 return CommandLineParseResult::Error; 0087 } 0088 if (posArgs.size() > 1) { 0089 errorMessage = "Too many positional arguments"; 0090 return CommandLineParseResult::Error; 0091 } 0092 0093 args.dbPath = posArgs.at(0).toStdString(); 0094 if (!std::filesystem::is_regular_file(args.dbPath)) { 0095 errorMessage = args.dbPath.string() + " is not a file"; 0096 return CommandLineParseResult::Error; 0097 } 0098 0099 // type + qualifiedName 0100 // we can only have one of --component, --package, --group 0101 if ((parser.isSet(component) && parser.isSet(package)) || (parser.isSet(component) && parser.isSet(group)) 0102 || (parser.isSet(package) && parser.isSet(group))) { 0103 errorMessage = "Only one of --component, --package and --group can be given"; 0104 return CommandLineParseResult::Error; 0105 } 0106 0107 if (parser.isSet(component)) { 0108 args.type = lvtshr::DiagramType::ComponentType; 0109 args.qualifiedName = parser.value(component).toStdString(); 0110 } else if (parser.isSet(package)) { 0111 args.type = lvtshr::DiagramType::PackageType; 0112 args.qualifiedName = parser.value(package).toStdString(); 0113 } else if (parser.isSet(group)) { 0114 args.type = lvtshr::DiagramType::PackageType; 0115 args.qualifiedName = parser.value(group).toStdString(); 0116 } else { 0117 errorMessage = "Please specify exactly one of --component, --package or --group"; 0118 return CommandLineParseResult::Error; 0119 } 0120 0121 args.fwdDeps = parser.isSet(fwdDeps); 0122 args.revDeps = parser.isSet(revDeps); 0123 args.extDeps = parser.isSet(extDeps); 0124 0125 return CommandLineParseResult::Ok; 0126 } 0127 0128 } // namespace 0129 0130 int main(int argc, char **argv) 0131 { 0132 QCoreApplication app(argc, argv); 0133 0134 QCommandLineParser parser; 0135 CommandLineArgs args; 0136 std::string errorMessage; 0137 0138 switch (parseCommandLine(parser, args, errorMessage)) { 0139 case CommandLineParseResult::Ok: 0140 break; 0141 case CommandLineParseResult::Error: 0142 if (!errorMessage.empty()) { 0143 std::cerr << errorMessage << std::endl; 0144 std::cerr << std::endl; 0145 } 0146 std::cerr << qPrintable(parser.helpText()); 0147 return EXIT_FAILURE; 0148 case CommandLineParseResult::Help: 0149 parser.showHelp(); 0150 Q_UNREACHABLE(); 0151 } 0152 0153 // TODO 695 0154 /* 0155 lvtcdb::CodebaseDb db; 0156 db.setPath(args.dbPath.string()); 0157 if (!db.open(Codethink::lvtcdb::BaseDb::OpenType::ExistingDatabase)) { 0158 std::cerr << "Error opening code database " << args.dbPath << std::endl; 0159 } 0160 */ 0161 0162 lvtldr::NodeStorage storage; 0163 // storage.setDatabaseSourcePath(db.path()); 0164 0165 lvtldr::PhysicalLoader loader(storage); // debug=true 0166 lvtldr::LakosianNode *node = storage.findByQualifiedName(args.type, args.qualifiedName); 0167 loader.clear(); 0168 loader.setMainNode(node); 0169 loader.setExtDeps(args.extDeps); 0170 0171 if (!loader.load(node, lvtldr::NodeLoadFlags{})) { 0172 return EXIT_FAILURE; 0173 } 0174 0175 return EXIT_SUCCESS; 0176 }