summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/command.cpp118
-rw-r--r--src/command.h56
-rw-r--r--src/component.cpp76
-rw-r--r--src/component.h20
-rw-r--r--src/config.h3
-rw-r--r--src/main.cpp22
-rw-r--r--src/package.cpp106
-rw-r--r--src/package.h50
-rw-r--r--src/sbo.cpp232
-rw-r--r--src/sbo.h73
10 files changed, 0 insertions, 756 deletions
diff --git a/src/command.cpp b/src/command.cpp
deleted file mode 100644
index 9443372..0000000
--- a/src/command.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-#include "command.h"
-#include <cassert>
-#include "config.h"
-#include "sbo.h"
-#include <ftxui/dom/elements.hpp>
-#include <ftxui/component/screen_interactive.hpp>
-#include "component.h"
-
-namespace katja
-{
- void list::execute() const
- {
- sbo sbo_repository;
- std::unordered_map<std::string, package> packages = katja::read_package_database();
- std::vector<std::vector<std::string>> table_data;
- std::set<std::string> installed_packages;
- std::unordered_map<std::string, package> package_database = read_package_database();
-
- for (const auto& package : package_database)
- {
- std::string tag = package.second.tag();
- if (tag.find("_SBo") == std::string::npos)
- {
- continue;
- }
- installed_packages.insert(package.first);
- }
- for (const auto& package : sbo_repository.list(installed_packages))
- {
- if (package_database.find(package.first)->second.version() == package.second.version())
- {
- continue;
- }
- table_data.push_back({
- package.second.name(),
- package.second.version(),
- package.second.tag(),
- package.second.architecture(),
- "SBo"
- });
- }
-
- auto screen = ftxui::ScreenInteractive::Fullscreen();
- PackageList list_component{
- { "Package name", "Version", "Tag", "Architecture", "Repository" },
- table_data
- };
-
- screen.Loop(std::make_shared<PackageList>(list_component));
- }
-
- void help::execute() const
- {
- std::cout << "Usage:\n"
- "\tkatja {list|update|help} [OPTIONS]\n\n";
- }
-
- void update::execute() const
- {
- sbo().refresh();
- }
-
- 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], "update") == 0)
- {
- return std::make_unique<update>();
- }
- else if (strcmp(argv[1], "help") == 0)
- {
- return std::make_unique<help>();
- }
- throw command_exception(command_exception_t::unknown_command, { argv[1] });
- }
-}
diff --git a/src/command.h b/src/command.h
deleted file mode 100644
index b168f04..0000000
--- a/src/command.h
+++ /dev/null
@@ -1,56 +0,0 @@
-#pragma once
-
-#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;
- };
-
- class update 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);
-}
diff --git a/src/component.cpp b/src/component.cpp
deleted file mode 100644
index 9247a1d..0000000
--- a/src/component.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-#include <ftxui/component/screen_interactive.hpp>
-#include "component.h"
-
-namespace katja
-{
- PackageList::PackageList(const std::vector<std::string>& header, const std::vector<std::vector<std::string>>& data)
- : m_data(data), m_header(header)
- {
- }
-
- ftxui::Element PackageList::Render()
- {
- std::vector<std::vector<std::string>> data{ m_header };
-
- std::size_t dimy = ftxui::ScreenInteractive::Active()->dimy();
- if (dimy == 0)
- {
- dimy = ftxui::Terminal::Size().dimy;
- }
- if (dimy > 4) // 4 = headers and borders.
- {
- std::size_t row_count = std::min(m_data.size() - top_line, dimy - 4 + top_line);
-
- std::copy(m_data.cbegin() + top_line, m_data.cbegin() + row_count, std::back_inserter(data));
- }
- ftxui::Table table{ data };
- table.SelectAll().Border(ftxui::LIGHT);
-
- // Add border around the first column.
- table.SelectColumn(0).Border(ftxui::LIGHT);
-
- // Make first row bold with a double border.
- table.SelectRow(0).Decorate(ftxui::bold);
- table.SelectRow(0).SeparatorVertical(ftxui::LIGHT);
- table.SelectRow(0).Border(ftxui::DOUBLE);
-
- // Align right the "Release date" column.
- table.SelectColumn(2).DecorateCells(ftxui::align_right);
-
- // Select row from the second to the last.
- auto content = table.SelectRows(1, -1);
- // Alternate in between 3 colors.
- content.DecorateCellsAlternateRow(color(ftxui::Color::Blue), 3, 0);
- content.DecorateCellsAlternateRow(color(ftxui::Color::Cyan), 3, 1);
- content.DecorateCellsAlternateRow(color(ftxui::Color::White), 3, 2);
-
- return table.Render();
- }
-
- bool PackageList::OnEvent(ftxui::Event event)
- {
- if (event == ftxui::Event::Character('q') || event == ftxui::Event::Escape)
- {
- event.screen_->ExitLoopClosure()();
- }
- else if (event == ftxui::Event::Character('j') || event == ftxui::Event::ArrowDown)
- {
- if (m_data.size() > 0 && top_line < (m_data.size() - 1))
- {
- ++top_line;
- }
- }
- else if (event == ftxui::Event::Character('k') || event == ftxui::Event::ArrowUp)
- {
- if (top_line > 0)
- {
- --top_line;
- }
- }
- else
- {
- return false;
- }
- return true;
- }
-}
diff --git a/src/component.h b/src/component.h
deleted file mode 100644
index d1a587a..0000000
--- a/src/component.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#pragma once
-
-#include <ftxui/component/component.hpp>
-#include <ftxui/dom/table.hpp>
-
-namespace katja
-{
- class PackageList final : public ftxui::ComponentBase
- {
- std::vector<std::vector<std::string>> m_data;
- std::vector<std::string> m_header;
- std::size_t top_line{ 0 };
-
- public:
- PackageList(const std::vector<std::string>& header, const std::vector<std::vector<std::string>>& data);
-
- virtual ftxui::Element Render() override;
- virtual bool OnEvent(ftxui::Event event) override;
- };
-}
diff --git a/src/config.h b/src/config.h
deleted file mode 100644
index 5be3df7..0000000
--- a/src/config.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#pragma once
-
-#define WORKDIR "./var"
diff --git a/src/main.cpp b/src/main.cpp
deleted file mode 100644
index ef8dfcd..0000000
--- a/src/main.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#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;
-}
diff --git a/src/package.cpp b/src/package.cpp
deleted file mode 100644
index 9fc99e4..0000000
--- a/src/package.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-#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;
- }
-
- package_exception::package_exception(const std::string& package_name, const std::string& reason) noexcept
- : m_message(package_name)
- {
- m_message.reserve(m_message.size() + 2 + reason.size());
- m_message += ": " + reason;
- }
-
- const std::string_view package_exception::package_name() const noexcept
- {
- std::size_t colon_position = m_message.find(':');
-
- if (colon_position == std::string::npos)
- {
- return std::string_view(m_message);
- }
- else if (colon_position == 0)
- {
- return std::string_view("");
- }
- else
- {
- return std::string_view(m_message.c_str(), colon_position - 1);
- }
- }
-
- const char *package_exception::what() const noexcept
- {
- return m_message.c_str();
- }
-}
diff --git a/src/package.h b/src/package.h
deleted file mode 100644
index 109f065..0000000
--- a/src/package.h
+++ /dev/null
@@ -1,50 +0,0 @@
-#pragma once
-
-#include <string>
-#include <optional>
-#include <unordered_map>
-#include <set>
-#include <forward_list>
-
-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;
- };
-
- class repository
- {
- public:
- virtual std::unordered_map<std::string, package> list(const std::set<std::string>& package_names) = 0;
- virtual void refresh() = 0;
- virtual std::forward_list<std::string> check_dependencies(const std::string& package_name) = 0;
- };
-
- std::unordered_map<std::string, package> read_package_database();
-
- class package_exception : public std::exception
- {
- std::string m_message;
-
- public:
- explicit package_exception(const std::string& package_name, const std::string& reason) noexcept;
-
- const std::string_view package_name() const noexcept;
- const char *what() const noexcept override;
- };
-}
diff --git a/src/sbo.cpp b/src/sbo.cpp
deleted file mode 100644
index 086ba79..0000000
--- a/src/sbo.cpp
+++ /dev/null
@@ -1,232 +0,0 @@
-#include "config.h"
-#include "sbo.h"
-#include <algorithm>
-#include <fstream>
-#include <vector>
-
-namespace katja
-{
- sbo::sbo()
- : git_binary(boost::process::search_path("git"))
- , cache_path(std::filesystem::path{ WORKDIR } / "sbo/repository")
- {
- }
-
- info sbo::parse_info_file(
- const std::filesystem::path& package_directory) const
- {
- std::map<std::string, std::vector<std::string>> results;
- std::filesystem::path info_path = cache_path
- / package_directory
- / package_directory.filename().replace_extension(".info");
-
- if (!std::filesystem::exists(info_path))
- {
- throw package_exception(package_directory.filename().string(), "Package doesn't exist.");
- }
- // Parse the info file.
- std::ifstream info_file{ info_path, std::ios::in };
- if (!info_file.is_open())
- {
- throw package_exception(package_directory.filename().string(), "Unable to open the .info file.");
- }
- std::string line;
- std::string variable_name;
- std::vector<std::string> variable_values;
-
- while (std::getline(info_file, line))
- {
- std::string::const_iterator current_char = line.cbegin();
-
- if (variable_name.empty())
- {
- current_char = std::find(current_char, line.cend(), '=');
- if (current_char == line.cbegin() || current_char == line.cend())
- {
- break; // Expected 'variable name' or '='.
- }
- ++current_char;
- if (current_char == line.cend() || *current_char != '"')
- {
- break; // Expected '"'.
- }
- variable_name = std::string(line.cbegin(), current_char - 1);
-
- variable_values.push_back("");
- }
-
- for (current_char += 1; current_char != line.end(); ++current_char)
- {
- if (*current_char == ' ')
- {
- if (!variable_values.back().empty())
- {
- variable_values.push_back("");
- }
- }
- else if (*current_char == '"')
- {
- if (variable_values.back().empty())
- {
- variable_values.pop_back();
- }
- results.insert_or_assign(variable_name, variable_values);
- variable_name = "";
- variable_values.clear();
- break;
- }
- else if (*current_char == '\\')
- {
- break;
- }
- else
- {
- variable_values.back().push_back(*current_char);
- }
- }
- if (current_char == line.cend())
- {
- break; // Expected '\' or '"'.
- }
- }
- info _info;
-
- _info.prgnam = results["PRGNAM"][0];
- _info.version = results["VERSION"][0];
- _info.homepage = results["HOMEPAGE"].size() == 0 ? "" : results["HOMEPAGE"][0];
- _info.download = results["DOWNLOAD"];
- _info.md5sum = results["DOWNLOAD"];
- _info.download_x86_64 = results["DOWNLOAD_X86_64"];
- _info.md5sum_x86_64 = results["MD5SUM_X86_64"];
- _info.requires = results["REQUIRES"];
- _info.maintainer = results["MAINTAINER"][0];
- _info.email = results["EMAIL"][0];
-
- return _info;
- }
-
- std::unordered_map<std::string, std::filesystem::path> sbo::collect_packages() const
- {
- std::unordered_map<std::string, std::filesystem::path> results;
-
- for (const auto& category_directory : std::filesystem::directory_iterator(cache_path))
- {
- if (!category_directory.is_directory())
- {
- continue;
- }
- for (const auto& package_directory : std::filesystem::directory_iterator(category_directory.path()))
- {
- results.insert({ package_directory.path().filename().string(),
- category_directory.path().filename() });
- }
- }
- return results;
- }
-
- std::unordered_map<std::string, package> sbo::list(const std::set<std::string>& package_names)
- {
- std::string line;
- std::unordered_map<std::string, package> packages;
- boost::process::environment slackbuild_environment;
- slackbuild_environment["PRINT_PACKAGE_NAME"] = "y";
-
- std::unordered_map<std::string, std::filesystem::path> package_categories = collect_packages();
-
- for (const std::string& package_name : package_names)
- {
- std::unordered_map<std::string, std::filesystem::path>::iterator package_category =
- package_categories.find(package_name);
-
- if (package_category == package_categories.cend())
- {
- continue;
- }
- std::filesystem::path package_directory_name{ package_category->first };
- std::filesystem::path slackbuild_cwd = cache_path
- / package_category->second / package_directory_name;
-
- // Execute the SlackBuild to get package information.
- std::filesystem::path slackbuild_file_name =
- package_directory_name.replace_extension(".SlackBuild");
- boost::process::ipstream slackbuild_output;
-
- boost::process::child slackbuild_process("/bin/bash", slackbuild_file_name.native(),
- slackbuild_environment,
- boost::process::start_dir(slackbuild_cwd.native()),
- boost::process::std_out > slackbuild_output,
- boost::process::std_in.close(),
- boost::process::std_err > boost::process::null);
-
- std::optional<package> maybe_package;
- if (slackbuild_process.running() && std::getline(slackbuild_output, line) && !line.empty())
- {
- maybe_package = package::parse(std::filesystem::path(line).replace_extension(""));
- }
- slackbuild_process.terminate();
-
- if (maybe_package.has_value())
- {
- packages.insert({ maybe_package.value().name(), maybe_package.value() });
- }
- }
- return packages;
- }
-
- void sbo::refresh()
- {
- std::filesystem::file_status repository_status = std::filesystem::status(cache_path);
-
- if (std::filesystem::exists(repository_status)
- && !std::filesystem::is_directory(repository_status))
- {
- throw std::runtime_error("The working directory path \""
- + cache_path.string() + "\" exists, but it isn't a directory.");
- }
- else if (!std::filesystem::exists(repository_status))
- {
- git("clone", std::filesystem::path(),
- "git://git.slackbuilds.org/slackbuilds.git", cache_path.native());
- }
- git("remote", cache_path.native(), "update", "--prune");
- git("reset", cache_path.native(), "--hard", "origin/master");
- }
-
- std::forward_list<std::string> sbo::check_dependencies(const std::string& package_name)
- {
- std::unordered_map<std::string, std::filesystem::path> package_categories = collect_packages();
- ordered_set resolved;
-
- resolve_dependencies(package_name, package_categories, resolved);
- std::forward_list<std::string> results;
-
- for (const auto& dependency : resolved.get<1>())
- {
- results.push_front(dependency);
- }
- return results;
- }
-
- void sbo::resolve_dependencies(const std::string& package_name,
- const std::unordered_map<std::string, std::filesystem::path>& package_categories,
- ordered_set& resolved) const
- {
- std::unordered_map<std::string, std::filesystem::path>::const_iterator package_category =
- package_categories.find(package_name);
-
- if (package_category == package_categories.cend())
- {
- throw package_exception(package_name, "Package not found.");
- }
- info info_file = parse_info_file(package_category->second / package_category->first);
-
- for (const auto& package_dependency : info_file.requires)
- {
- if (resolved.find(package_dependency) == resolved.cend())
- {
- resolve_dependencies(package_dependency, package_categories, resolved);
- }
- }
- resolved.insert(package_name);
- }
-}
diff --git a/src/sbo.h b/src/sbo.h
deleted file mode 100644
index 95a1c53..0000000
--- a/src/sbo.h
+++ /dev/null
@@ -1,73 +0,0 @@
-#pragma once
-
-#include "package.h"
-#include <boost/process.hpp>
-#include <filesystem>
-#include <map>
-#include <boost/multi_index_container.hpp>
-#include <boost/multi_index/ordered_index.hpp>
-#include <boost/multi_index/sequenced_index.hpp>
-
-namespace katja
-{
- struct info
- {
- std::string prgnam;
- std::string version;
- std::string homepage;
- std::vector<std::string> download;
- std::vector<std::string> md5sum;
- std::vector<std::string> download_x86_64;
- std::vector<std::string> md5sum_x86_64;
- std::vector<std::string> requires;
- std::string maintainer;
- std::string email;
- };
-
- class sbo : public repository
- {
- using ordered_set = boost::multi_index_container<
- std::string,
- boost::multi_index::indexed_by<
- boost::multi_index::ordered_unique<boost::multi_index::identity<std::string>>,
- boost::multi_index::sequenced<>
- >
- >;
- boost::filesystem::path git_binary;
- std::filesystem::path cache_path;
-
- template<typename... Args>
- void git(const std::string& command, const std::filesystem::path& cwd, const Args&... args) const
- {
- if (cwd.empty())
- {
- boost::process::system(git_binary, command, args...);
- }
- else
- {
- boost::process::system(git_binary, "-C", cwd.native(), command, args...);
- }
- }
-
- info parse_info_file(const std::filesystem::path& package_directory) const;
-
- /**
- * Returns the list of packages in the repository.
- *
- * @return A map containing package names as key, and its category
- * directory name as value.
- */
- std::unordered_map<std::string, std::filesystem::path> collect_packages() const;
-
- void resolve_dependencies(const std::string& package_name,
- const std::unordered_map<std::string, std::filesystem::path>& package_categories,
- ordered_set& resolved) const;
-
- public:
- explicit sbo();
-
- virtual std::unordered_map<std::string, package> list(const std::set<std::string>& package_names) override;
- virtual void refresh() override;
- virtual std::forward_list<std::string> check_dependencies(const std::string& package_name) override;
- };
-}