From 7b8d6709b4c84172803ba827dbae72d8a41b6b87 Mon Sep 17 00:00:00 2001 From: Bionus Date: Sun, 21 Apr 2024 01:29:50 +0200 Subject: [PATCH] feat: add CLI commands to manage source registries --- .../site/site-add-cli-command.cpp | 4 +- .../source-registry-add-cli-command.cpp | 51 +++++++++++++++++++ .../source-registry-add-cli-command.h | 24 +++++++++ .../source-registry-cli-command.cpp | 32 ++++++++++++ .../source-registry-cli-command.h | 23 +++++++++ .../source-registry-list-cli-command.cpp | 41 +++++++++++++++ .../source-registry-list-cli-command.h | 24 +++++++++ .../source-registry-remove-cli-command.cpp | 51 +++++++++++++++++++ .../source-registry-remove-cli-command.h | 24 +++++++++ src/cli/src/cli.cpp | 15 +++--- 10 files changed, 281 insertions(+), 8 deletions(-) create mode 100644 src/cli/src/cli-commands/source-registry/source-registry-add-cli-command.cpp create mode 100644 src/cli/src/cli-commands/source-registry/source-registry-add-cli-command.h create mode 100644 src/cli/src/cli-commands/source-registry/source-registry-cli-command.cpp create mode 100644 src/cli/src/cli-commands/source-registry/source-registry-cli-command.h create mode 100644 src/cli/src/cli-commands/source-registry/source-registry-list-cli-command.cpp create mode 100644 src/cli/src/cli-commands/source-registry/source-registry-list-cli-command.h create mode 100644 src/cli/src/cli-commands/source-registry/source-registry-remove-cli-command.cpp create mode 100644 src/cli/src/cli-commands/source-registry/source-registry-remove-cli-command.h diff --git a/src/cli/src/cli-commands/site/site-add-cli-command.cpp b/src/cli/src/cli-commands/site/site-add-cli-command.cpp index 47f0cbaae..ba114517c 100644 --- a/src/cli/src/cli-commands/site/site-add-cli-command.cpp +++ b/src/cli/src/cli-commands/site/site-add-cli-command.cpp @@ -64,7 +64,7 @@ void SiteAddCliCommand::run() } m_profile->addSite(SiteFactory::fromUrl(url, source, m_profile)); - stdOut << "Site added:" << url; + stdOut << "Site added: " << url << Qt::endl; emit finished(0); return; } @@ -80,7 +80,7 @@ void SiteAddCliCommand::run() } m_profile->addSite(SiteFactory::fromUrl(url, source, m_profile)); - stdOut << "Site added:" << url; + stdOut << "Site added: " << url << Qt::endl; emit finished(0); }); sourceGuesser.start(); diff --git a/src/cli/src/cli-commands/source-registry/source-registry-add-cli-command.cpp b/src/cli/src/cli-commands/source-registry/source-registry-add-cli-command.cpp new file mode 100644 index 000000000..e16468e59 --- /dev/null +++ b/src/cli/src/cli-commands/source-registry/source-registry-add-cli-command.cpp @@ -0,0 +1,51 @@ +#include "source-registry-add-cli-command.h" +#include +#include +#include "models/profile.h" +#include "models/source-registry.h" + + +SourceRegistryAddCliCommand::SourceRegistryAddCliCommand(QStringList arguments, Profile *profile, QObject *parent) + : CliAction(std::move(arguments), parent), m_profile(profile) +{ + m_parser.addHelpOptionOnly(); + m_parser.setApplicationDescription("Add a new source registry"); + m_parser.setPrefix({ "source-registry", "add" }); + + m_parser.addPositionalArgument("url", "The URL of the source registry to add", ""); +} + + +bool SourceRegistryAddCliCommand::validate() +{ + // One and only one source registry can be added at a time + if (m_parser.positionalArguments().length() != 1) { + m_parser.showHelp(); + return false; + } + + return true; +} + +void SourceRegistryAddCliCommand::run() +{ + // Build a source registry instance using the positional arguments + const QString url = m_parser.positionalArguments().first(); + auto *sourceRegistry = new SourceRegistry(url); + + // Try to load the source registry first to ensure it's valid + connect(sourceRegistry, &SourceRegistry::loaded, [=](bool ok) { + if (!ok) { + qWarning() << "The source registry could not be added:" << url; + sourceRegistry->deleteLater(); + emit finished(1); + return; + } + + QTextStream stdOut(stdout); + m_profile->addSourceRegistry(sourceRegistry); + stdOut << "Source registry added: " << url << Qt::endl; + emit finished(0); + }); + sourceRegistry->load(); +} diff --git a/src/cli/src/cli-commands/source-registry/source-registry-add-cli-command.h b/src/cli/src/cli-commands/source-registry/source-registry-add-cli-command.h new file mode 100644 index 000000000..569862217 --- /dev/null +++ b/src/cli/src/cli-commands/source-registry/source-registry-add-cli-command.h @@ -0,0 +1,24 @@ +#ifndef SOURCE_REGISTRY_ADD_CLI_COMMAND_H +#define SOURCE_REGISTRY_ADD_CLI_COMMAND_H + +#include +#include "../cli-action.h" + + +class Profile; + +class SourceRegistryAddCliCommand : public CliAction +{ + Q_OBJECT + + public: + explicit SourceRegistryAddCliCommand(QStringList arguments, Profile *profile, QObject *parent = nullptr); + + bool validate() override; + void run() override; + + private: + Profile *m_profile; +}; + +#endif // SOURCE_REGISTRY_ADD_CLI_COMMAND_H diff --git a/src/cli/src/cli-commands/source-registry/source-registry-cli-command.cpp b/src/cli/src/cli-commands/source-registry/source-registry-cli-command.cpp new file mode 100644 index 000000000..741958ab1 --- /dev/null +++ b/src/cli/src/cli-commands/source-registry/source-registry-cli-command.cpp @@ -0,0 +1,32 @@ +#include "source-registry-cli-command.h" +#include "source-registry-add-cli-command.h" +#include "source-registry-list-cli-command.h" +#include "source-registry-remove-cli-command.h" + + +SourceRegistryCliCommand::SourceRegistryCliCommand(QStringList arguments, Profile *profile, QObject *parent) + : CliSubcommand(std::move(arguments), parent), m_profile(profile) +{ + m_parser.addHelpOptionOnly(); + m_parser.setApplicationDescription("Manage source registries"); + m_parser.setPrefix({ "source-registry" }); + + m_parser.addCommand("list", "List source registries"); + m_parser.addCommand("add", "Add a new source registry"); + m_parser.addCommand("remove", "Remove an existing source registry"); +} + + +CliCommand *SourceRegistryCliCommand::getCommand(const QString &command) +{ + if (command == "list") { + return new SourceRegistryListCliCommand(m_arguments, m_profile, parent()); + } + if (command == "add") { + return new SourceRegistryAddCliCommand(m_arguments, m_profile, parent()); + } + if (command == "remove") { + return new SourceRegistryRemoveCliCommand(m_arguments, m_profile, parent()); + } + return nullptr; +} diff --git a/src/cli/src/cli-commands/source-registry/source-registry-cli-command.h b/src/cli/src/cli-commands/source-registry/source-registry-cli-command.h new file mode 100644 index 000000000..d0caf3baf --- /dev/null +++ b/src/cli/src/cli-commands/source-registry/source-registry-cli-command.h @@ -0,0 +1,23 @@ +#ifndef SOURCE_REGISTRY_CLI_COMMAND_H +#define SOURCE_REGISTRY_CLI_COMMAND_H + +#include +#include "../cli-subcommand.h" + + +class Profile; + +class SourceRegistryCliCommand : public CliSubcommand +{ + Q_OBJECT + + public: + explicit SourceRegistryCliCommand(QStringList arguments, Profile *profile, QObject *parent = nullptr); + + CliCommand *getCommand(const QString &command) override; + + private: + Profile *m_profile; +}; + +#endif // SOURCE_REGISTRY_CLI_COMMAND_H diff --git a/src/cli/src/cli-commands/source-registry/source-registry-list-cli-command.cpp b/src/cli/src/cli-commands/source-registry/source-registry-list-cli-command.cpp new file mode 100644 index 000000000..25a421f1d --- /dev/null +++ b/src/cli/src/cli-commands/source-registry/source-registry-list-cli-command.cpp @@ -0,0 +1,41 @@ +#include "source-registry-list-cli-command.h" +#include +#include +#include +#include "models/profile.h" +#include "models/source-registry.h" + + +SourceRegistryListCliCommand::SourceRegistryListCliCommand(QStringList arguments, Profile *profile, QObject *parent) + : CliAction(std::move(arguments), parent), m_profile(profile) +{ + m_parser.addHelpOptionOnly(); + m_parser.setApplicationDescription("List source registries"); + m_parser.setPrefix({ "source-registry", "list" }); +} + + +bool SourceRegistryListCliCommand::validate() +{ + // Nothing to validate + return true; +} + +void SourceRegistryListCliCommand::run() +{ + // Log a warning and early return if no source registries are found + const QList &sourceRegistries = m_profile->getSourceRegistries(); + if (sourceRegistries.isEmpty()) { + qWarning() << "No source registries found"; + emit finished(0); + return; + } + + // Print all source registries' urls + QTextStream stdOut(stdout); + for (SourceRegistry *sourceRegistry : sourceRegistries) { + stdOut << sourceRegistry->jsonUrl() << Qt::endl; + } + + emit finished(0); +} diff --git a/src/cli/src/cli-commands/source-registry/source-registry-list-cli-command.h b/src/cli/src/cli-commands/source-registry/source-registry-list-cli-command.h new file mode 100644 index 000000000..40d7f249e --- /dev/null +++ b/src/cli/src/cli-commands/source-registry/source-registry-list-cli-command.h @@ -0,0 +1,24 @@ +#ifndef SOURCE_REGISTRY_LIST_CLI_COMMAND_H +#define SOURCE_REGISTRY_LIST_CLI_COMMAND_H + +#include +#include "../cli-action.h" + + +class Profile; + +class SourceRegistryListCliCommand : public CliAction +{ + Q_OBJECT + + public: + explicit SourceRegistryListCliCommand(QStringList arguments, Profile *profile, QObject *parent = nullptr); + + bool validate() override; + void run() override; + + private: + Profile *m_profile; +}; + +#endif // SOURCE_REGISTRY_LIST_CLI_COMMAND_H diff --git a/src/cli/src/cli-commands/source-registry/source-registry-remove-cli-command.cpp b/src/cli/src/cli-commands/source-registry/source-registry-remove-cli-command.cpp new file mode 100644 index 000000000..d0e251ab7 --- /dev/null +++ b/src/cli/src/cli-commands/source-registry/source-registry-remove-cli-command.cpp @@ -0,0 +1,51 @@ +#include "source-registry-remove-cli-command.h" +#include +#include +#include "models/profile.h" +#include "models/source-registry.h" + + +SourceRegistryRemoveCliCommand::SourceRegistryRemoveCliCommand(QStringList arguments, Profile *profile, QObject *parent) + : CliAction(std::move(arguments), parent), m_profile(profile) +{ + m_parser.addHelpOptionOnly(); + m_parser.setApplicationDescription("Remove an existing source registry"); + m_parser.setPrefix({ "source-registry", "remove" }); + + m_parser.addPositionalArgument("url", "The URL of the source registry to remove", ""); +} + + +bool SourceRegistryRemoveCliCommand::validate() +{ + // One and only one source registry can be removed at a time + if (m_parser.positionalArguments().length() != 1) { + m_parser.showHelp(); + return false; + } + + return true; +} + +void SourceRegistryRemoveCliCommand::run() +{ + const QString url = m_parser.positionalArguments().first(); + + // Find the correct source registry + auto sourceRegistryIt = std::find_if( + m_profile->getSourceRegistries().constBegin(), + m_profile->getSourceRegistries().constEnd(), + [&](SourceRegistry *registry) { return registry->jsonUrl() == url; } + ); + if (sourceRegistryIt == m_profile->getSourceRegistries().constEnd()) { + qWarning() << "The source registry was not found:" << url; + emit finished(1); + return; + } + + // Actually remove the source registry + QTextStream stdOut(stdout); + m_profile->removeSourceRegistry(*sourceRegistryIt); + stdOut << "Source registry removed: " << url << Qt::endl; + emit finished(0); +} diff --git a/src/cli/src/cli-commands/source-registry/source-registry-remove-cli-command.h b/src/cli/src/cli-commands/source-registry/source-registry-remove-cli-command.h new file mode 100644 index 000000000..d295b383c --- /dev/null +++ b/src/cli/src/cli-commands/source-registry/source-registry-remove-cli-command.h @@ -0,0 +1,24 @@ +#ifndef SOURCE_REGISTRY_REMOVE_CLI_COMMAND_H +#define SOURCE_REGISTRY_REMOVE_CLI_COMMAND_H + +#include +#include "../cli-action.h" + + +class Profile; + +class SourceRegistryRemoveCliCommand : public CliAction +{ + Q_OBJECT + + public: + explicit SourceRegistryRemoveCliCommand(QStringList arguments, Profile *profile, QObject *parent = nullptr); + + bool validate() override; + void run() override; + + private: + Profile *m_profile; +}; + +#endif // SOURCE_REGISTRY_REMOVE_CLI_COMMAND_H diff --git a/src/cli/src/cli.cpp b/src/cli/src/cli.cpp index 68048f953..54ce8f3ff 100644 --- a/src/cli/src/cli.cpp +++ b/src/cli/src/cli.cpp @@ -15,6 +15,7 @@ #include "cli-commands/get-tags-cli-command.h" #include "cli-commands/load-tag-database-cli-command.h" #include "cli-commands/site/site-cli-command.h" +#include "cli-commands/source-registry/source-registry-cli-command.h" #include "printers/json-printer.h" #include "printers/simple-printer.h" #include "logger.h" @@ -44,6 +45,7 @@ int parseAndRunCliArgsV2(QCoreApplication *app, Profile *profile, bool defaultTo } parser.addCommand("source", "Manage sources"); + parser.addCommand("source-registry", "Manage source registries"); parser.process(*app); @@ -62,10 +64,13 @@ int parseAndRunCliArgsV2(QCoreApplication *app, Profile *profile, bool defaultTo arguments.removeAll("--cli"); // Handle each specific command separately - CliCommand *cmd = nullptr; + QScopedPointer cmd; const QString command = parser.command(); if (command == "source") { - cmd = new SiteCliCommand(arguments, profile); + cmd.reset(new SiteCliCommand(arguments, profile)); + } + if (command == "source-registry") { + cmd.reset(new SourceRegistryCliCommand(arguments, profile)); } // If we're here, that means that help was requested or no command was passed @@ -75,9 +80,7 @@ int parseAndRunCliArgsV2(QCoreApplication *app, Profile *profile, bool defaultTo } // Actually run the command - int exitCode = cmd->execute(); - cmd->deleteLater(); - return exitCode; + return cmd->execute(); } @@ -90,7 +93,7 @@ int parseAndRunCliArgs(QCoreApplication *app, Profile *profile, bool defaultToGu // Go through the new CLI for the various commands supported by it const QStringList args = app->arguments(); bool guessUseCLI = (defaultToGui && (args.contains("-c") || args.contains("--cli"))) || (!defaultToGui && !args.contains("-g") && !args.contains("--gui")); - if (guessUseCLI && args.contains("source")) { + if (guessUseCLI && (args.contains("source") || args.contains("source-registry"))) { return parseAndRunCliArgsV2(app, profile, defaultToGui, params, positionalArgs); }