From 6559569986220e26532fbd9a9d0668720ce60174 Mon Sep 17 00:00:00 2001 From: Toni Date: Sat, 21 Feb 2026 10:30:44 +0100 Subject: [PATCH] track installed packages --- .clang-tidy | 2 +- CMakeLists.txt | 10 +++++++++- src/db.h | 38 ++++++++++++++++++++++++++++++++++++++ src/main.cc | 41 ++++++++++++++++++++++++++++------------- 4 files changed, 76 insertions(+), 15 deletions(-) create mode 100644 src/db.h diff --git a/.clang-tidy b/.clang-tidy index db16aa3..f90308a 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1 +1 @@ -Checks: '*,clang-analyzer-*,-llvmlibc-*,-fuchsia-*,-altera-*,-abseil-*,-android-*,-modernize-use-trailing-return-type,-readability-identifier-length,-*-readability-todo,-*-magic-numbers,-readability-function-cognitive-complexity,-*-easily-swappable-parameters,-*-non-private-member-variables-in-classes,-*-no-recursion,-concurrency-mt-unsafe,-*-runtime-int,-*-non-const-global-variables,-performance-inefficient-string-concatenation' \ No newline at end of file +Checks: '*,clang-analyzer-*,-llvmlibc-*,-fuchsia-*,-altera-*,-abseil-*,-android-*,-modernize-use-trailing-return-type,-readability-identifier-length,-*-readability-todo,-*-magic-numbers,-readability-function-cognitive-complexity,-*-easily-swappable-parameters,-*-non-private-member-variables-in-classes,-*-no-recursion,-concurrency-mt-unsafe,-*-runtime-int,-*-non-const-global-variables,-performance-inefficient-string-concatenation,-cert-err58-cpp,-*-signed-bitwise' \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index ed0eb81..22161ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,8 +6,16 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) find_package(blake3 REQUIRED) +include(FetchContent) +FetchContent_Declare( + SQLiteCpp + GIT_REPOSITORY https://github.com/SRombauts/SQLiteCpp + GIT_TAG 3.3.3 +) +FetchContent_MakeAvailable(SQLiteCpp) + add_executable(${PROJECT_NAME} src/main.cc) -target_link_libraries(${PROJECT_NAME} PRIVATE blake3) +target_link_libraries(${PROJECT_NAME} PRIVATE blake3 SQLiteCpp) set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "-static") \ No newline at end of file diff --git a/src/db.h b/src/db.h new file mode 100644 index 0000000..d3bc5a7 --- /dev/null +++ b/src/db.h @@ -0,0 +1,38 @@ +#pragma once +#include + +class DB { +public: + constexpr static const std::string DB_PATH = "/var/lib/shrap"; + + void init_db() { + m_db.exec(R"( + CREATE TABLE IF NOT EXISTS installed ( + name TEXT PRIMARY KEY, + version TEXT NOT NULL, + installed_at INTEGER NOT NULL + ); + )"); + } + + bool is_installed(const std::string &name) { + SQLite::Statement query(m_db, + "SELECT version FROM installed WHERE name = ?"); + query.bind(1, name); + return query.executeStep(); + } + + void mark_installed(const std::string &name, const std::string &version) { + SQLite::Statement insert( + m_db, "INSERT OR REPLACE INTO installed(name, version, " + "installed_at) VALUES (?, ?, strftime('%s','now'))"); + + insert.bind(1, name); + insert.bind(2, version); + insert.exec(); + } + +private: + SQLite::Database m_db{DB_PATH + "/shrap.db", + SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE}; +}; \ No newline at end of file diff --git a/src/main.cc b/src/main.cc index 58eea08..f00d56f 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,3 +1,4 @@ +#include "db.h" #include "parser.h" #include "util.h" #include @@ -7,9 +8,9 @@ #include #include +static const std::string BUILD_PATH = "/tmp/shrap"; + std::unordered_map packages; -bool flag_raw = false; -bool flag_graph = false; void load_packages() { for (const auto &e : std::filesystem::directory_iterator("./packages/")) { @@ -25,11 +26,15 @@ void load_packages() { } std::vector -resolve_dependencies(const std::vector &roots) { +resolve_dependencies(const std::vector &roots, DB &db) { std::unordered_map state; std::vector order; std::function dfs = [&](const std::string &name) { + if (db.is_installed(name)) { + return; + } + int s = state[name]; if (s == 2) { return; @@ -63,7 +68,7 @@ resolve_dependencies(const std::vector &roots) { return order; } -void install_package(const std::string &name) { +void install_package(const std::string &name, DB &db) { // TODO: track installed packages if (!packages.contains(name)) { @@ -79,10 +84,10 @@ void install_package(const std::string &name) { Expr src = pkg.get_one("src"); std::string src_type = src.children[0].value; std::string src_url = src.get_one("url").value; - std::string src_path = "/tmp/shrap/" + src.get_one("dir").value; + std::string src_path = BUILD_PATH + "/" + src.get_one("dir").value; if (src_type == "tar") { - std::string archive_path = "/tmp/shrap/" + Util::basename(src_url); + std::string archive_path = BUILD_PATH + "/" + Util::basename(src_url); std::string expected_hash = src.get_one("blake3").value; bool needs_download = true; @@ -110,7 +115,7 @@ void install_package(const std::string &name) { } std::cout << "\n\tExtracting...\n"; - Util::shell_command("tar xf " + archive_path + " -C /tmp/shrap/"); + Util::shell_command("tar xf " + archive_path + " -C " + BUILD_PATH); } else { throw std::runtime_error("unrecognized src type"); } @@ -176,10 +181,12 @@ void install_package(const std::string &name) { throw std::runtime_error("unrecognized step type"); } } + + db.mark_installed(pkg.get_one("name").value, pkg.get_one("version").value); } void generate_graph(const std::vector &to_highlight) { - std::ofstream out("/tmp/shrap/graph.dot"); + std::ofstream out(BUILD_PATH + "/graph.dot"); out << "digraph dependencies {\n"; if (to_highlight.empty()) { @@ -202,17 +209,25 @@ void generate_graph(const std::vector &to_highlight) { out << "}\n"; out.close(); - Util::shell_command("dot -Tpng graph.dot > graph.png", "/tmp/shrap"); - std::cout << "Graph saved to /tmp/shrap/graph.png\n"; + Util::shell_command("dot -Tpng graph.dot > graph.png", BUILD_PATH); + std::cout << "Graph saved to " << BUILD_PATH << "/graph.png\n"; } int main(int argc, char **argv) { auto args = std::span(argv, static_cast(argc)); - Util::shell_command("mkdir -p /tmp/shrap"); + + std::filesystem::create_directories(BUILD_PATH); + std::filesystem::create_directories(DB::DB_PATH); + + DB db; + db.init_db(); load_packages(); + bool flag_raw = false; + bool flag_graph = false; std::vector to_install; + for (size_t i = 1; i < args.size(); ++i) { std::string arg = args[i]; if (arg == "-r") { @@ -225,7 +240,7 @@ int main(int argc, char **argv) { } if (!flag_raw) { - to_install = resolve_dependencies(to_install); + to_install = resolve_dependencies(to_install, db); } if (flag_graph) { @@ -256,7 +271,7 @@ int main(int argc, char **argv) { for (const std::string &pkg : to_install) { try { - install_package(pkg); + install_package(pkg, db); } catch (std::exception &e) { std::cerr << "ERROR: " << e.what() << std::endl; return 1;