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 }