#include #include #include #include #include #include #include #include #include "package_manager_lib.h" // Output streams QTextStream out(stdout); QTextStream err(stderr); void printPackageTable(const QJsonArray& packages) { // Header out << QString("%1 %2 %3 %4") .arg("NAME", -30) .arg("CATEGORY", -15) .arg("TYPE", -10) .arg("INSTALLED", -10) << Qt::endl; out << QString("-").repeated(65) << Qt::endl; // Rows for (const QJsonValue& val : packages) { QJsonObject pkg = val.toObject(); QString name = pkg.value("name").toString(); QString category = pkg.value("category").toString(); QString type = pkg.value("type").toString(); bool installed = pkg.value("installed").toBool(); out << QString("%1 %2 %3 %4") .arg(name, -30) .arg(category, -15) .arg(type, -10) .arg(installed ? "yes" : "no", -10) << Qt::endl; } } void printPackageJson(const QJsonArray& packages) { QJsonDocument doc(packages); out << doc.toJson(QJsonDocument::Indented) << Qt::endl; } int cmdSearch(PackageManagerLib& pm, const QStringList& args, bool jsonOutput) { if (args.isEmpty()) { err << "Error: search requires a query argument" << Qt::endl; return 1; } QString query = args.first().toLower(); QJsonArray allPackages = pm.getPackages(); QJsonArray results; for (const QJsonValue& val : allPackages) { QJsonObject pkg = val.toObject(); QString name = pkg.value("name").toString().toLower(); QString description = pkg.value("description").toString().toLower(); if (name.contains(query) || description.contains(query)) { results.append(pkg); } } if (results.isEmpty()) { out << "No packages found matching '" << args.first() << "'" << Qt::endl; return 0; } if (jsonOutput) { printPackageJson(results); } else { out << "Found " << results.size() << " package(s) matching '" << args.first() << "':" << Qt::endl << Qt::endl; printPackageTable(results); } return 0; } int cmdList(PackageManagerLib& pm, const QString& category, bool installedOnly, bool jsonOutput) { QJsonArray packages; if (category.isEmpty()) { packages = pm.getPackages(); } else { packages = pm.getPackages(category); } if (installedOnly) { QJsonArray filtered; for (const QJsonValue& val : packages) { QJsonObject pkg = val.toObject(); if (pkg.value("installed").toBool()) { filtered.append(pkg); } } packages = filtered; } if (packages.isEmpty()) { out << "No packages found" << Qt::endl; return 0; } if (jsonOutput) { printPackageJson(packages); } else { out << "Found " << packages.size() << " package(s):" << Qt::endl << Qt::endl; printPackageTable(packages); } return 0; } int cmdInstallFile(PackageManagerLib& pm, const QString& filePath) { if (!QFile::exists(filePath)) { err << "Error: file not found: " << filePath << Qt::endl; return 1; } out << "Installing from file: " << filePath << "..." << Qt::flush; QString errorMsg; QString installedPath = pm.installPluginFile(filePath, errorMsg); if (installedPath.isEmpty()) { out << " FAILED" << Qt::endl; err << "Error: " << errorMsg << Qt::endl; return 1; } out << " done" << Qt::endl; out << "Installed to: " << installedPath << Qt::endl; return 0; } int cmdInstall(PackageManagerLib& pm, const QStringList& args) { if (args.isEmpty()) { err << "Error: install requires at least one package name" << Qt::endl; return 1; } out << "Resolving dependencies..." << Qt::endl; QStringList packagesToInstall = pm.resolveDependencies(args); out << "Will install " << packagesToInstall.size() << " package(s): " << packagesToInstall.join(", ") << Qt::endl << Qt::endl; int installed = 0; int failed = 0; for (const QString& packageName : packagesToInstall) { out << "Installing: " << packageName << "..." << Qt::flush; if (pm.installPackage(packageName)) { out << " done" << Qt::endl; installed++; } else { out << " FAILED" << Qt::endl; failed++; } } out << Qt::endl; if (failed == 0) { out << "Done. " << installed << " package(s) installed successfully." << Qt::endl; return 0; } else { out << "Completed with errors. " << installed << " installed, " << failed << " failed." << Qt::endl; return 1; } } int cmdCategories(PackageManagerLib& pm, bool jsonOutput) { QStringList categories = pm.getCategories(); if (jsonOutput) { QJsonArray arr; for (const QString& cat : categories) { arr.append(cat); } QJsonDocument doc(arr); out << doc.toJson(QJsonDocument::Indented) << Qt::endl; } else { out << "Available categories:" << Qt::endl; for (const QString& cat : categories) { out << " " << cat << Qt::endl; } } return 0; } int cmdInfo(PackageManagerLib& pm, const QStringList& args, bool jsonOutput) { if (args.isEmpty()) { err << "Error: info requires a package name" << Qt::endl; return 1; } QString packageName = args.first(); QJsonArray packages = pm.getPackages(); QJsonObject pkg = pm.findPackageByName(packages, packageName); if (pkg.isEmpty()) { err << "Error: package '" << packageName << "' not found" << Qt::endl; return 1; } if (jsonOutput) { QJsonDocument doc(pkg); out << doc.toJson(QJsonDocument::Indented) << Qt::endl; } else { out << "Name: " << pkg.value("name").toString() << Qt::endl; out << "Description: " << pkg.value("description").toString() << Qt::endl; out << "Category: " << pkg.value("category").toString() << Qt::endl; out << "Type: " << pkg.value("type").toString() << Qt::endl; out << "Author: " << pkg.value("author").toString() << Qt::endl; out << "Module Name: " << pkg.value("moduleName").toString() << Qt::endl; QJsonArray deps = pkg.value("dependencies").toArray(); if (!deps.isEmpty()) { QStringList depList; for (const QJsonValue& d : deps) { depList << d.toString(); } out << "Dependencies: " << depList.join(", ") << Qt::endl; } else { out << "Dependencies: none" << Qt::endl; } out << "Installed: " << (pkg.value("installed").toBool() ? "yes" : "no") << Qt::endl; } return 0; } void printHelp() { out << "lgpm - Logos Package Manager CLI" << Qt::endl; out << Qt::endl; out << "Usage: lgpm [options] [arguments]" << Qt::endl; out << Qt::endl; out << "Commands:" << Qt::endl; out << " search Search packages by name or description" << Qt::endl; out << " list List all available packages" << Qt::endl; out << " install [pkgs...] Install one or more packages" << Qt::endl; out << " install --file Install from a local LGX file" << Qt::endl; out << " categories List available categories" << Qt::endl; out << " info Show detailed package information" << Qt::endl; out << Qt::endl; out << "Options:" << Qt::endl; out << " --modules-dir Set core modules directory" << Qt::endl; out << " --ui-plugins-dir Set UI plugins directory" << Qt::endl; out << " --release GitHub release tag to use (default: latest)" << Qt::endl; out << " --category Filter by category (for list command)" << Qt::endl; out << " --installed Show only installed packages (for list command)" << Qt::endl; out << " --file Install from a local LGX file (for install command)" << Qt::endl; out << " --json Output in JSON format" << Qt::endl; out << " -h, --help Show this help message" << Qt::endl; out << " -v, --version Show version information" << Qt::endl; } int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); app.setApplicationName("lgpm"); app.setApplicationVersion("1.0.0"); QCommandLineParser parser; parser.setApplicationDescription("Logos Package Manager CLI"); // Options QCommandLineOption helpOption(QStringList() << "h" << "help", "Show help message"); QCommandLineOption versionOption(QStringList() << "v" << "version", "Show version"); QCommandLineOption pluginsDirOption("modules-dir", "Core modules directory", "path"); QCommandLineOption uiPluginsDirOption("ui-plugins-dir", "UI plugins directory", "path"); QCommandLineOption categoryOption("category", "Filter by category", "category"); QCommandLineOption installedOption("installed", "Show only installed packages"); QCommandLineOption jsonOption("json", "Output in JSON format"); QCommandLineOption fileOption("file", "Install from a local LGX file path", "path"); QCommandLineOption releaseOption("release", "GitHub release tag to use (default: latest)", "tag", "latest"); parser.addOption(helpOption); parser.addOption(versionOption); parser.addOption(pluginsDirOption); parser.addOption(uiPluginsDirOption); parser.addOption(categoryOption); parser.addOption(installedOption); parser.addOption(jsonOption); parser.addOption(fileOption); parser.addOption(releaseOption); parser.addPositionalArgument("command", "Command to run"); parser.addPositionalArgument("args", "Command arguments", "[args...]"); parser.process(app); if (parser.isSet(helpOption)) { printHelp(); return 0; } if (parser.isSet(versionOption)) { out << "lgpm version " << app.applicationVersion() << Qt::endl; return 0; } QStringList positionalArgs = parser.positionalArguments(); if (positionalArgs.isEmpty()) { printHelp(); return 1; } QString command = positionalArgs.takeFirst(); bool jsonOutput = parser.isSet(jsonOption); PackageManagerLib pm; if (parser.isSet(pluginsDirOption)) { pm.setPluginsDirectory(parser.value(pluginsDirOption)); } if (parser.isSet(uiPluginsDirOption)) { pm.setUiPluginsDirectory(parser.value(uiPluginsDirOption)); } if (parser.isSet(releaseOption)) { pm.setRelease(parser.value(releaseOption)); } if (command == "search") { return cmdSearch(pm, positionalArgs, jsonOutput); } else if (command == "list") { QString category = parser.value(categoryOption); bool installedOnly = parser.isSet(installedOption); return cmdList(pm, category, installedOnly, jsonOutput); } else if (command == "install") { if (parser.isSet(fileOption)) { return cmdInstallFile(pm, parser.value(fileOption)); } return cmdInstall(pm, positionalArgs); } else if (command == "categories") { return cmdCategories(pm, jsonOutput); } else if (command == "info") { return cmdInfo(pm, positionalArgs, jsonOutput); } else { err << "Error: unknown command '" << command << "'" << Qt::endl; err << "Run 'lgpm --help' for usage information" << Qt::endl; return 1; } }