Add an utility to list all installed packages
This commit is contained in:
parent
0385dbbe53
commit
f46a16b4a0
16
build.ninja
Normal file
16
build.ninja
Normal file
@ -0,0 +1,16 @@
|
||||
rule cxx
|
||||
command = g++ -c -o $out $in
|
||||
description = CXX $out
|
||||
|
||||
rule link
|
||||
command = g++ -o $out $in
|
||||
description = LINK $out
|
||||
|
||||
build build/package.o: cxx src/package.cpp | src/package.h
|
||||
build build/command.o: cxx src/command.cpp | src/command.h build/package.o
|
||||
|
||||
build build/main.o: cxx src/main.cpp
|
||||
|
||||
build build/slackbuilder: link build/main.o build/command.o build/package.o
|
||||
|
||||
default build/slackbuilder
|
74
src/command.cpp
Normal file
74
src/command.cpp
Normal file
@ -0,0 +1,74 @@
|
||||
#include "command.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace katja
|
||||
{
|
||||
void list::execute() const
|
||||
{
|
||||
for (const auto& package : katja::read_package_database())
|
||||
{
|
||||
std::cout << package.second.name()
|
||||
<< " " << package.second.version()
|
||||
<< " (" << package.second.tag() << ")"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void help::execute() const
|
||||
{
|
||||
std::cout << "Usage:\n"
|
||||
"\tkatja {info|help} [OPTIONS]\n\n";
|
||||
}
|
||||
|
||||
command_exception::command_exception(const command_exception_t exception_type,
|
||||
std::vector<std::string> failed_arguments) noexcept
|
||||
: m_exception_type(exception_type), m_failed_arguments(failed_arguments)
|
||||
{
|
||||
}
|
||||
|
||||
const char *command_exception::what() const noexcept
|
||||
{
|
||||
switch (m_exception_type)
|
||||
{
|
||||
case command_exception_t::no_command:
|
||||
return "No command specified.";
|
||||
case command_exception_t::too_many_arguments:
|
||||
return "Too many arguments given.";
|
||||
case command_exception_t::unknown_command:
|
||||
return "Unknown command.";
|
||||
}
|
||||
assert(false);
|
||||
}
|
||||
|
||||
const std::vector<std::string>& command_exception::failed_arguments() const noexcept
|
||||
{
|
||||
return m_failed_arguments;
|
||||
}
|
||||
|
||||
std::unique_ptr<command> parse_command_line(int argc, char **argv)
|
||||
{
|
||||
if (argc > 2)
|
||||
{
|
||||
std::vector<std::string> failed_arguments;
|
||||
|
||||
for (std::size_t i = 2; i < argc; ++i)
|
||||
{
|
||||
failed_arguments.push_back(argv[i]);
|
||||
}
|
||||
throw command_exception(command_exception_t::unknown_command);
|
||||
}
|
||||
else if (argc < 2)
|
||||
{
|
||||
throw command_exception(command_exception_t::no_command);
|
||||
}
|
||||
if (strcmp(argv[1], "list") == 0)
|
||||
{
|
||||
return std::make_unique<list>();
|
||||
}
|
||||
else if (strcmp(argv[1], "help") == 0)
|
||||
{
|
||||
return std::make_unique<help>();
|
||||
}
|
||||
throw command_exception(command_exception_t::unknown_command, { argv[1] });
|
||||
}
|
||||
}
|
48
src/command.h
Normal file
48
src/command.h
Normal file
@ -0,0 +1,48 @@
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "package.h"
|
||||
|
||||
namespace katja
|
||||
{
|
||||
class command
|
||||
{
|
||||
public:
|
||||
virtual void execute() const = 0;
|
||||
};
|
||||
|
||||
class list final : public command
|
||||
{
|
||||
public:
|
||||
void execute() const override;
|
||||
};
|
||||
|
||||
class help final : public command
|
||||
{
|
||||
public:
|
||||
void execute() const override;
|
||||
};
|
||||
|
||||
enum class command_exception_t
|
||||
{
|
||||
no_command,
|
||||
too_many_arguments,
|
||||
unknown_command,
|
||||
};
|
||||
|
||||
class command_exception final : public std::exception
|
||||
{
|
||||
command_exception_t m_exception_type;
|
||||
std::vector<std::string> m_failed_arguments;
|
||||
|
||||
public:
|
||||
explicit command_exception(const command_exception_t exception_type,
|
||||
std::vector<std::string> failed_arguments = {}) noexcept;
|
||||
|
||||
const char *what() const noexcept override;
|
||||
const std::vector<std::string>& failed_arguments() const noexcept;
|
||||
};
|
||||
|
||||
std::unique_ptr<command> parse_command_line(int argc, char **argv);
|
||||
}
|
22
src/main.cpp
Normal file
22
src/main.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
#include "command.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
std::unique_ptr<katja::command> command;
|
||||
|
||||
try
|
||||
{
|
||||
command = katja::parse_command_line(argc, argv);
|
||||
}
|
||||
catch (katja::command_exception& e)
|
||||
{
|
||||
std::cout << e.what() << std::endl << std::endl;
|
||||
|
||||
katja::help().execute();
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
command->execute();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
76
src/package.cpp
Normal file
76
src/package.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
#include "package.h"
|
||||
#include <filesystem>
|
||||
|
||||
namespace katja
|
||||
{
|
||||
package::package(const std::string& name, const std::string& version,
|
||||
const std::string& architecture, const std::string& tag)
|
||||
: m_name(name), m_version(version), m_architecture(architecture), m_tag(tag)
|
||||
{
|
||||
}
|
||||
|
||||
const std::string& package::name() const noexcept
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
const std::string& package::version() const noexcept
|
||||
{
|
||||
return m_version;
|
||||
}
|
||||
|
||||
const std::string& package::architecture() const noexcept
|
||||
{
|
||||
return m_architecture;
|
||||
}
|
||||
|
||||
const std::string& package::tag() const noexcept
|
||||
{
|
||||
return m_tag;
|
||||
}
|
||||
|
||||
std::optional<package> package::parse(const std::string& full_name) noexcept
|
||||
{
|
||||
std::size_t tag_separator = full_name.find_last_of('-');
|
||||
|
||||
if (tag_separator == std::string::npos || tag_separator == 0)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
std::size_t architecture_separator = full_name.find_last_of('-', tag_separator - 1);
|
||||
|
||||
if (architecture_separator == std::string::npos || architecture_separator == 0)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
std::size_t version_separator = full_name.find_last_of('-', architecture_separator - 1);
|
||||
|
||||
if (version_separator == std::string::npos || version_separator == 0)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
package parsed_package{
|
||||
full_name.substr(0, version_separator),
|
||||
full_name.substr(version_separator + 1, architecture_separator - version_separator - 1),
|
||||
full_name.substr(architecture_separator + 1, tag_separator - architecture_separator - 1),
|
||||
full_name.substr(tag_separator + 1)
|
||||
};
|
||||
return std::make_optional(parsed_package);
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, package> read_package_database()
|
||||
{
|
||||
std::unordered_map<std::string, package> packages;
|
||||
|
||||
for (const auto& entry : std::filesystem::directory_iterator("/var/lib/pkgtools/packages"))
|
||||
{
|
||||
std::optional<package> maybe_package = package::parse(entry.path().filename());
|
||||
|
||||
if (maybe_package.has_value())
|
||||
{
|
||||
packages.insert_or_assign(maybe_package.value().name(), maybe_package.value());
|
||||
}
|
||||
}
|
||||
return packages;
|
||||
}
|
||||
}
|
27
src/package.h
Normal file
27
src/package.h
Normal file
@ -0,0 +1,27 @@
|
||||
#include <string>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace katja
|
||||
{
|
||||
class package
|
||||
{
|
||||
std::string m_name;
|
||||
std::string m_version;
|
||||
std::string m_architecture;
|
||||
std::string m_tag;
|
||||
|
||||
public:
|
||||
explicit package(const std::string& name, const std::string& version,
|
||||
const std::string& architecture, const std::string& tag);
|
||||
|
||||
const std::string& name() const noexcept;
|
||||
const std::string& version() const noexcept;
|
||||
const std::string& architecture() const noexcept;
|
||||
const std::string& tag() const noexcept;
|
||||
|
||||
static std::optional<package> parse(const std::string& full_name) noexcept;
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, package> read_package_database();
|
||||
}
|
Loading…
Reference in New Issue
Block a user