fancy colors and emojis, nodejs, gnupg

This commit is contained in:
2026-02-22 12:09:04 +01:00
parent 2113e5155b
commit 3f2768ebf7
17 changed files with 190 additions and 35 deletions

11
packages/gnupg.shrap Normal file
View File

@@ -0,0 +1,11 @@
(package
(name "gnupg")
(version "2.5.17")
(homepage "https://www.gnupg.org/")
(dependencies libgnutls libksba libnpth libassuan libgcrypt)
(src (tar
(url "https://www.gnupg.org/ftp/gcrypt/gnupg/gnupg-2.5.17.tar.bz2")
(dir "gnupg-2.5.17")
(blake3 "174654d88ff05d2a6b3880ec81a684d23657da8d9518210862e659a9e7a6ee6c")))
(build
(configure_make)))

11
packages/graphviz.shrap Normal file
View File

@@ -0,0 +1,11 @@
(package
(name "graphviz")
(version "14.1.2")
(homepage "https://www.graphviz.org/")
(dependencies make)
(src (tar
(url "https://gitlab.com/api/v4/projects/4207231/packages/generic/graphviz-releases/14.1.2/graphviz-14.1.2.tar.gz")
(dir "graphviz-14.1.2")
(blake3 "38544ae9666532110752889a723c869576723114da9c56e6add264558ed007fe")))
(build
(configure_make)))

11
packages/libassuan.shrap Normal file
View File

@@ -0,0 +1,11 @@
(package
(name "libassuan")
(version "3.0.2")
(homepage "https://www.gnupg.org/software/libassuan/index.html")
(dependencies libgpg-error)
(src (tar
(url "https://www.gnupg.org/ftp/gcrypt/libassuan/libassuan-3.0.2.tar.bz2")
(dir "libassuan-3.0.2")
(blake3 "c96b4e82157b358d889159b335f6f674e3da0ce8d2b37775e306d6a2bb111897")))
(build
(configure_make)))

11
packages/libbrotli.shrap Normal file
View File

@@ -0,0 +1,11 @@
(package
(name "libbrotli")
(version "1.2.0")
(homepage "https://github.com/google/brotli")
(dependencies cmake)
(src (tar
(url "https://github.com/google/brotli/archive/refs/tags/v1.2.0.tar.gz")
(dir "brotli-1.2.0")
(blake3 "88a91819bc0e0b5bd27bd8c7d8ffddf132768851069f2cd5e905eac87e2860de")))
(build
(cmake)))

11
packages/libcares.shrap Normal file
View File

@@ -0,0 +1,11 @@
(package
(name "libcares")
(version "1.34.6")
(homepage "https://c-ares.org/")
(dependencies make)
(src (tar
(url "https://github.com/c-ares/c-ares/releases/download/v1.34.6/c-ares-1.34.6.tar.gz")
(dir "c-ares-1.34.6")
(blake3 "053dfcbc7754502c2df605d0989f978793cf714014b18dbbef030bef405b1cc1")))
(build
(configure_make)))

11
packages/libgcrypt.shrap Normal file
View File

@@ -0,0 +1,11 @@
(package
(name "libgcrypt")
(version "1.12.1")
(homepage "https://www.gnupg.org/software/libgcrypt/index.html")
(dependencies libgpg-error)
(src (tar
(url "https://www.gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-1.12.1.tar.bz2")
(dir "libgcrypt-1.12.1")
(blake3 "347bad07fd9b084e20cbfcafc3fe4f959610d8a7109632d6f15cdef373f744d6")))
(build
(configure_make)))

View File

@@ -0,0 +1,11 @@
(package
(name "libgpg-error")
(version "1.59")
(homepage "https://www.gnupg.org/software/libgpg-error/index.html")
(dependencies bzip2)
(src (tar
(url "https://www.gnupg.org/ftp/gcrypt/libgpg-error/libgpg-error-1.59.tar.bz2")
(dir "libgpg-error-1.59")
(blake3 "e087c22deda3f6f5d6fd98dc14c2f9649d70c12e653979f229d0878cea0a60bf")))
(build
(configure_make)))

View File

@@ -8,6 +8,4 @@
(dir "libjpeg-turbo-3.1.3")
(blake3 "fbcee6fae3d00fd550af865bec1af4d363f5e1feeaf85b60247ca6db1908b10e")))
(build
(cmake)
(shell "ln -sf /usr/lib/x86_64-linux-gnu/libjpeg.a /usr/lib/ || true")
(shell "ln -sf /usr/lib/x86_64-linux-gnu/pkgconfig/libjpeg.pc /usr/lib/pkgconfig/ || true")))
(cmake)))

11
packages/libksba.shrap Normal file
View File

@@ -0,0 +1,11 @@
(package
(name "libksba")
(version "1.6.7")
(homepage "https://www.gnupg.org/software/libksba/index.html")
(dependencies libgpg-error)
(src (tar
(url "https://www.gnupg.org/ftp/gcrypt/libksba/libksba-1.6.7.tar.bz2")
(dir "libksba-1.6.7")
(blake3 "cb5bafe9d11429796c31358d9b96695ceeab80e33da75991902075c597c708cf")))
(build
(configure_make)))

11
packages/libnpth.shrap Normal file
View File

@@ -0,0 +1,11 @@
(package
(name "libnpth")
(version "1.8")
(homepage "https://www.gnupg.org/software/npth/index.html")
(dependencies bzip2)
(src (tar
(url "https://www.gnupg.org/ftp/gcrypt/npth/npth-1.8.tar.bz2")
(dir "npth-1.8")
(blake3 "cac4aa343cb1d426a913b29cb1692b6145dd530c9e1896696cd6e85872b3df03")))
(build
(configure_make)))

12
packages/nodejs.shrap Normal file
View File

@@ -0,0 +1,12 @@
(package
(name "nodejs")
(version "24.13.1")
(homepage "https://nodejs.org/")
(dependencies python libicu pkg-config libuv libnghttp2 zstd libbrotli libcares)
(src (tar
(url "https://nodejs.org/dist/v24.13.1/node-v24.13.1.tar.gz")
(dir "node-v24.13.1")
(blake3 "ae264a6e61bde11d84e1ead672ce2d278e5e8f3cc55e7c7867525dfd646f3182")))
(build
(configure_make
(configure_flags "--shared-brotli --shared-cares --shared-libuv --shared-openssl --shared-nghttp2 --shared-zlib --shared-zstd --with-intl=system-icu"))))

View File

@@ -2,7 +2,7 @@
(name "python")
(version "3.14.3")
(homepage "https://www.python.org/")
(dependencies zlib libopenssl bzip2 libffi sqlite3 libdb libreadline)
(dependencies zlib libopenssl bzip2 libffi libreadline)
(src (tar
(url "https://www.python.org/ftp/python/3.14.3/Python-3.14.3.tgz")
(dir "Python-3.14.3")

View File

@@ -8,4 +8,5 @@
(dir "sqlite-autoconf-3510200")
(blake3 "7ba8d2c972fb11430e8ce3ca2b2b0c3d583be6da5c8faf7cba50a12eb699601e")))
(build
(configure_make)))
(configure_make
(configure_flags "--all"))))

View File

@@ -8,4 +8,5 @@
(dir "zstd-1.5.7")
(blake3 "730dca31244abd219e995f03a55d95b2cfb4b3e16cda055a79fa6f30a4f0e1db")))
(build
(make)))
(make
(install_flags "prefix=/usr"))))

View File

@@ -1,5 +1,6 @@
#pragma once
#include <SQLiteCpp/SQLiteCpp.h>
#include <vector>
class DB {
public:
@@ -32,6 +33,19 @@ public:
insert.exec();
}
auto get_installed() {
std::vector<std::pair<std::string, std::string>> installed;
SQLite::Statement query(m_db, "SELECT name, version FROM installed");
while (query.executeStep()) {
std::string name = query.getColumn(0).getString();
std::string version = query.getColumn(1).getString();
installed.emplace_back(name, version);
}
return installed;
}
private:
SQLite::Database m_db{DB_PATH + "/shrap.db",
SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE};

View File

@@ -8,15 +8,23 @@
#include <thread>
#include <unordered_map>
constexpr static const std::string BUILD_PATH = "/tmp/shrap";
constexpr const std::string BUILD_PATH = "/tmp/shrap";
constexpr const std::string CLR_RESET = "\033[0m";
constexpr const std::string CLR_RED = "\033[31m";
constexpr const std::string CLR_GREEN = "\033[32m";
constexpr const std::string CLR_YELLOW = "\033[33m";
constexpr const std::string CLR_BLUE = "\033[34m";
std::unordered_map<std::string, Expr> packages;
size_t to_install_count;
size_t current_package_index;
void load_packages() {
for (const auto &e : std::filesystem::directory_iterator("./packages/")) {
std::ifstream file(e.path());
if (!file) {
std::cerr << "Failed to open " << e.path() << "\n";
std::cerr << CLR_RED << "Failed to open " << e.path() << "\n"
<< CLR_RESET;
std::exit(1);
}
@@ -26,12 +34,12 @@ void load_packages() {
}
std::vector<std::string>
resolve_dependencies(const std::vector<std::string> &roots, DB &db) {
resolve_dependencies(const std::vector<std::string> &roots, DB *db) {
std::unordered_map<std::string, int> state;
std::vector<std::string> order;
std::function<void(const std::string &)> dfs = [&](const std::string &name) {
if (db.is_installed(name)) {
if (db != nullptr && db->is_installed(name)) {
return;
}
@@ -44,7 +52,8 @@ resolve_dependencies(const std::vector<std::string> &roots, DB &db) {
}
if (!packages.contains(name)) {
std::cerr << "Package not found: " << name << "\n";
std::cerr << CLR_RED << "Package not found: " << name << "\n"
<< CLR_RESET;
std::exit(1);
}
@@ -69,17 +78,18 @@ resolve_dependencies(const std::vector<std::string> &roots, DB &db) {
}
void install_package(const std::string &name, DB &db) {
// TODO: track installed packages
if (!packages.contains(name)) {
std::cerr << "Package not found: " << name << "\n";
std::cerr << CLR_RED << "Package not found: " << name << "\n" << CLR_RESET;
std::exit(1);
}
Expr pkg = packages[name];
std::cout << "\n\n\tInstalling " << pkg.get_one("name").value << " ("
<< pkg.get_one("version").value << ")...\n\n";
std::cout << CLR_BLUE << "\n\n 📦 Installing " << CLR_GREEN
<< pkg.get_one("name").value << CLR_BLUE << " (" << CLR_YELLOW
<< current_package_index << CLR_BLUE << " of " << CLR_YELLOW
<< to_install_count << CLR_BLUE << ")...\n\n"
<< CLR_RESET;
Expr src = pkg.get_one("src");
std::string src_type = src.children[0].value;
@@ -94,7 +104,7 @@ void install_package(const std::string &name, DB &db) {
// dont redownload if checksum matches
if (std::filesystem::exists(archive_path)) {
std::cout << "\tComputing checksum...\n";
std::cout << CLR_BLUE << " 🔍 Computing checksum...\n" << CLR_RESET;
std::string current_hash = Util::hash_file(archive_path);
if (current_hash == expected_hash) {
needs_download = false;
@@ -104,17 +114,17 @@ void install_package(const std::string &name, DB &db) {
if (needs_download) {
Util::shell_command("./curl -L -o " + archive_path + " " + src_url);
std::cout << "\n\tComputing checksum...\n";
std::cout << CLR_BLUE << "\n 🔍 Computing checksum...\n" << CLR_RESET;
std::string hash = Util::hash_file(archive_path);
if (expected_hash != hash) {
std::cerr << "Checksum check failed.\n";
std::cerr << CLR_RED << "Checksum check failed.\n";
std::cerr << "Expected: " << expected_hash << "\n";
std::cerr << "Got: " << hash << "\n";
std::cerr << "Got: " << hash << "\n" << CLR_RESET;
std::exit(1);
}
}
std::cout << "\n\tExtracting...\n";
std::cout << CLR_BLUE << "\n 📂 Extracting...\n" << CLR_RESET;
Util::shell_command("tar xf " + archive_path + " -C " + BUILD_PATH);
} else {
throw std::runtime_error("unrecognized src type");
@@ -122,7 +132,7 @@ void install_package(const std::string &name, DB &db) {
std::string jobs = std::to_string(std::thread::hardware_concurrency());
std::cout << "\n\tBuilding...\n\n";
std::cout << CLR_BLUE << "\n 🔨 Building...\n\n" << CLR_RESET;
for (const auto &step : pkg.get("build").children) {
std::string step_type = step.children[0].value;
@@ -179,9 +189,10 @@ void install_package(const std::string &name, DB &db) {
}
Util::shell_command("mkdir -p build", src_path);
Util::shell_command("cmake -DCMAKE_INSTALL_PREFIX=/usr " +
configure_flags + " ..",
src_path + "/build");
Util::shell_command(
"cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib " +
configure_flags + " ..",
src_path + "/build");
Util::shell_command("make -j" + jobs, src_path + "/build");
Util::shell_command("make install", src_path + "/build");
} else if (step_type == "meson") {
@@ -230,14 +241,16 @@ void generate_graph(const std::vector<std::string> &to_highlight) {
out.close();
Util::shell_command("dot -Tpng graph.dot > graph.png", BUILD_PATH);
std::cout << "Graph saved to " << BUILD_PATH << "/graph.png\n";
std::cout << CLR_GREEN << "Graph saved to " << BUILD_PATH << "/graph.png\n"
<< CLR_RESET;
}
int main(int argc, char **argv) {
auto args = std::span(argv, static_cast<size_t>(argc));
if (geteuid() != 0) {
std::cerr << "This program needs to be ran as root.\n";
std::cerr << CLR_RED << "This program needs to be ran as root.\n"
<< CLR_RESET;
return 1;
}
@@ -251,6 +264,7 @@ int main(int argc, char **argv) {
bool flag_raw = false;
bool flag_graph = false;
bool flag_list = false;
std::vector<std::string> to_install;
for (size_t i = 1; i < args.size(); ++i) {
@@ -259,41 +273,57 @@ int main(int argc, char **argv) {
flag_raw = true;
} else if (arg == "-g") {
flag_graph = true;
} else if (arg == "-l") {
flag_list = true;
} else {
to_install.push_back(arg);
}
}
if (flag_graph) {
generate_graph(to_install);
generate_graph(resolve_dependencies(to_install, nullptr));
return 0;
}
if (flag_list) {
for (const auto &[k, v] : db.get_installed()) {
std::cout << k << " (" << v << ")\n";
}
return 0;
}
if (to_install.empty()) {
std::cerr << "Usage: " << args[0] << " [-g] [-r] package1 [package2 ...]\n";
std::cerr << "Usage: " << args[0]
<< " [-g] [-r] [-l] package1 [package2 ...]\n";
return 1;
}
if (!flag_raw) {
to_install = resolve_dependencies(to_install, db);
to_install = resolve_dependencies(to_install, &db);
}
std::cout << "\nFollowing packages will be installed:\n";
std::cout << CLR_BLUE << "\nFollowing packages will be installed:\n"
<< CLR_RESET;
for (const std::string &pkg : to_install) {
if (!packages.contains(pkg)) {
std::cerr << "Package not found: " << pkg << "\n";
std::exit(1);
}
std::cout << " - " << pkg << " (" << packages[pkg].get_one("version").value
<< ")" << std::endl;
std::cout << " - " << CLR_YELLOW << pkg << CLR_RESET << " ("
<< packages[pkg].get_one("version").value << ")" << std::endl;
}
std::cout << CLR_BLUE << "\nPress ENTER to proceed..." << CLR_RESET;
std::cin.get();
to_install_count = to_install.size();
current_package_index = 1;
for (const std::string &pkg : to_install) {
try {
install_package(pkg, db);
current_package_index++;
} catch (std::exception &e) {
std::cerr << "ERROR: " << e.what() << std::endl;
std::cerr << CLR_RED << "ERROR: " << e.what() << "\n" << CLR_RESET;
return 1;
}
}

View File

@@ -27,7 +27,7 @@ static void shell_command(const std::string &cmd,
_exit(1);
}
std::cout << cmd << std::endl;
std::cout << "\n " << cmd << "\n\n";
execl("/bin/sh", "sh", "-c", cmd.c_str(), nullptr); // NOLINT(*-vararg)
perror("execl failed");