track installed packages
This commit is contained in:
@@ -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'
|
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'
|
||||||
@@ -6,8 +6,16 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|||||||
|
|
||||||
find_package(blake3 REQUIRED)
|
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)
|
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")
|
set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "-static")
|
||||||
38
src/db.h
Normal file
38
src/db.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <SQLiteCpp/SQLiteCpp.h>
|
||||||
|
|
||||||
|
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};
|
||||||
|
};
|
||||||
41
src/main.cc
41
src/main.cc
@@ -1,3 +1,4 @@
|
|||||||
|
#include "db.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -7,9 +8,9 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
static const std::string BUILD_PATH = "/tmp/shrap";
|
||||||
|
|
||||||
std::unordered_map<std::string, Expr> packages;
|
std::unordered_map<std::string, Expr> packages;
|
||||||
bool flag_raw = false;
|
|
||||||
bool flag_graph = false;
|
|
||||||
|
|
||||||
void load_packages() {
|
void load_packages() {
|
||||||
for (const auto &e : std::filesystem::directory_iterator("./packages/")) {
|
for (const auto &e : std::filesystem::directory_iterator("./packages/")) {
|
||||||
@@ -25,11 +26,15 @@ void load_packages() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string>
|
std::vector<std::string>
|
||||||
resolve_dependencies(const std::vector<std::string> &roots) {
|
resolve_dependencies(const std::vector<std::string> &roots, DB &db) {
|
||||||
std::unordered_map<std::string, int> state;
|
std::unordered_map<std::string, int> state;
|
||||||
std::vector<std::string> order;
|
std::vector<std::string> order;
|
||||||
|
|
||||||
std::function<void(const std::string &)> dfs = [&](const std::string &name) {
|
std::function<void(const std::string &)> dfs = [&](const std::string &name) {
|
||||||
|
if (db.is_installed(name)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int s = state[name];
|
int s = state[name];
|
||||||
if (s == 2) {
|
if (s == 2) {
|
||||||
return;
|
return;
|
||||||
@@ -63,7 +68,7 @@ resolve_dependencies(const std::vector<std::string> &roots) {
|
|||||||
return order;
|
return order;
|
||||||
}
|
}
|
||||||
|
|
||||||
void install_package(const std::string &name) {
|
void install_package(const std::string &name, DB &db) {
|
||||||
// TODO: track installed packages
|
// TODO: track installed packages
|
||||||
|
|
||||||
if (!packages.contains(name)) {
|
if (!packages.contains(name)) {
|
||||||
@@ -79,10 +84,10 @@ void install_package(const std::string &name) {
|
|||||||
Expr src = pkg.get_one("src");
|
Expr src = pkg.get_one("src");
|
||||||
std::string src_type = src.children[0].value;
|
std::string src_type = src.children[0].value;
|
||||||
std::string src_url = src.get_one("url").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") {
|
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;
|
std::string expected_hash = src.get_one("blake3").value;
|
||||||
|
|
||||||
bool needs_download = true;
|
bool needs_download = true;
|
||||||
@@ -110,7 +115,7 @@ void install_package(const std::string &name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "\n\tExtracting...\n";
|
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 {
|
} else {
|
||||||
throw std::runtime_error("unrecognized src type");
|
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");
|
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<std::string> &to_highlight) {
|
void generate_graph(const std::vector<std::string> &to_highlight) {
|
||||||
std::ofstream out("/tmp/shrap/graph.dot");
|
std::ofstream out(BUILD_PATH + "/graph.dot");
|
||||||
|
|
||||||
out << "digraph dependencies {\n";
|
out << "digraph dependencies {\n";
|
||||||
if (to_highlight.empty()) {
|
if (to_highlight.empty()) {
|
||||||
@@ -202,17 +209,25 @@ void generate_graph(const std::vector<std::string> &to_highlight) {
|
|||||||
out << "}\n";
|
out << "}\n";
|
||||||
out.close();
|
out.close();
|
||||||
|
|
||||||
Util::shell_command("dot -Tpng graph.dot > graph.png", "/tmp/shrap");
|
Util::shell_command("dot -Tpng graph.dot > graph.png", BUILD_PATH);
|
||||||
std::cout << "Graph saved to /tmp/shrap/graph.png\n";
|
std::cout << "Graph saved to " << BUILD_PATH << "/graph.png\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
auto args = std::span(argv, static_cast<size_t>(argc));
|
auto args = std::span(argv, static_cast<size_t>(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();
|
load_packages();
|
||||||
|
|
||||||
|
bool flag_raw = false;
|
||||||
|
bool flag_graph = false;
|
||||||
std::vector<std::string> to_install;
|
std::vector<std::string> to_install;
|
||||||
|
|
||||||
for (size_t i = 1; i < args.size(); ++i) {
|
for (size_t i = 1; i < args.size(); ++i) {
|
||||||
std::string arg = args[i];
|
std::string arg = args[i];
|
||||||
if (arg == "-r") {
|
if (arg == "-r") {
|
||||||
@@ -225,7 +240,7 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!flag_raw) {
|
if (!flag_raw) {
|
||||||
to_install = resolve_dependencies(to_install);
|
to_install = resolve_dependencies(to_install, db);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flag_graph) {
|
if (flag_graph) {
|
||||||
@@ -256,7 +271,7 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
for (const std::string &pkg : to_install) {
|
for (const std::string &pkg : to_install) {
|
||||||
try {
|
try {
|
||||||
install_package(pkg);
|
install_package(pkg, db);
|
||||||
} catch (std::exception &e) {
|
} catch (std::exception &e) {
|
||||||
std::cerr << "ERROR: " << e.what() << std::endl;
|
std::cerr << "ERROR: " << e.what() << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user