diff --git a/packages/autoconf.shrap b/packages/autoconf.shrap new file mode 100644 index 0000000..e652fa2 --- /dev/null +++ b/packages/autoconf.shrap @@ -0,0 +1,11 @@ +(package + (name "autoconf") + (version "2.72") + (homepage "https://www.gnu.org/software/autoconf/") + (dependencies m4 perl) + (src (tar + (url "https://ftp.gnu.org/gnu/autoconf/autoconf-2.72.tar.gz") + (dir "autoconf-2.72") + (blake3 "89aad7032c61efa3ea6cada364e20560c58441a92a7267db15e0fddff55638c7"))) + (build + (configure_make))) diff --git a/packages/automake.shrap b/packages/automake.shrap new file mode 100644 index 0000000..482450c --- /dev/null +++ b/packages/automake.shrap @@ -0,0 +1,11 @@ +(package + (name "automake") + (version "1.18") + (homepage "https://www.gnu.org/software/automake/") + (dependencies m4) + (src (tar + (url "https://ftp.gnu.org/gnu/automake/automake-1.18.tar.gz") + (dir "automake-1.18") + (blake3 "42458b6c690f6bf69d9dece26b023a7437830333e9149a13ab165f34ecbe90a3"))) + (build + (configure_make))) diff --git a/packages/bison.shrap b/packages/bison.shrap new file mode 100644 index 0000000..426c22c --- /dev/null +++ b/packages/bison.shrap @@ -0,0 +1,11 @@ +(package + (name "bison") + (version "3.8.2") + (homepage "https://www.gnu.org/software/bison/") + (dependencies m4) + (src (tar + (url "https://ftp.gnu.org/gnu/bison/bison-3.8.2.tar.gz") + (dir "bison-3.8.2") + (blake3 "9a529d3945d46103faa144ad1998b6c7dcf4653166fceee1ef59baef3c853c34"))) + (build + (configure_make))) diff --git a/packages/flex.shrap b/packages/flex.shrap new file mode 100644 index 0000000..018964e --- /dev/null +++ b/packages/flex.shrap @@ -0,0 +1,11 @@ +(package + (name "flex") + (version "2.6.4") + (homepage "https://github.com/westes/flex") + (dependencies m4) + (src (tar + (url "https://github.com/westes/flex/releases/download/v2.6.4/flex-2.6.4.tar.gz") + (dir "flex-2.6.4") + (blake3 "d78b714ac38bd9de7f9b44a078efed82e96ed43e7cf9cd33944a7f379a2d09a4"))) + (build + (configure_make))) diff --git a/packages/libglib.shrap b/packages/libglib.shrap index 931e266..b7dd711 100644 --- a/packages/libglib.shrap +++ b/packages/libglib.shrap @@ -1,5 +1,5 @@ (package - (name "glib") + (name "libglib") (version "2.86.4") (homepage "https://www.gtk.org/") (dependencies meson ninja git libffi pkg-config slang) diff --git a/packages/libreadline.shrap b/packages/libreadline.shrap new file mode 100644 index 0000000..e1fd355 --- /dev/null +++ b/packages/libreadline.shrap @@ -0,0 +1,12 @@ +(package + (name "libreadline") + (version "8.3") + (homepage "https://tiswww.cwru.edu/php/chet/readline/rltop.html") + (dependencies libncurses) + (src (tar + (url "https://ftp.gnu.org/gnu/readline/readline-8.3.tar.gz") + (dir "readline-8.3") + (blake3 "7109f094062bda387a0c16b4875375b96e36437bebbbd8d8f91bb27ba01d687f"))) + (build + (configure_make + (configure_flags "--disable-shared")))) diff --git a/packages/pkg-config.shrap b/packages/pkg-config.shrap index 36e2124..2044fe1 100644 --- a/packages/pkg-config.shrap +++ b/packages/pkg-config.shrap @@ -2,6 +2,7 @@ (name "pkg-config") (version "2.5.1") (homepage "https://github.com/pkgconf/pkgconf") + (dependencies xz) (src (tar (url "https://distfiles.ariadne.space/pkgconf/pkgconf-2.5.1.tar.xz") (dir "pkgconf-2.5.1") diff --git a/packages/postgresql.shrap b/packages/postgresql.shrap new file mode 100644 index 0000000..fe63309 --- /dev/null +++ b/packages/postgresql.shrap @@ -0,0 +1,12 @@ +(package + (name "postgresql") + (version "18.2") + (homepage "https://www.postgresql.org/") + (dependencies pkg-config bison flex perl libreadline zlib) + (src (tar + (url "https://ftp.postgresql.org/pub/source/v18.2/postgresql-18.2.tar.gz") + (dir "postgresql-18.2") + (blake3 "ae352f4fecabf9ada3fe22e46f952507d6970864b6f9494d7a7e3b65bd009463"))) + (build + (configure_make + (configure_flags "--without-icu")))) diff --git a/packages/psmisc.shrap b/packages/psmisc.shrap new file mode 100644 index 0000000..6067dce --- /dev/null +++ b/packages/psmisc.shrap @@ -0,0 +1,12 @@ +(package + (name "psmisc") + (version "23.7") + (homepage "https://gitlab.com/psmisc/psmisc") + (dependencies autoconf automake gettext libncurses) + (src (tar + (url "https://gitlab.com/psmisc/psmisc/-/archive/v23.7/psmisc-v23.7.tar.gz") + (dir "psmisc-v23.7") + (blake3 "3e213023c51dfcbbad4f51af77c8488d5ff5ee6f8bd08fa1ede77ae6ac56f7a5"))) + (build + (shell "./autogen.sh") + (configure_make))) diff --git a/packages/python.shrap b/packages/python.shrap index 8f9a38a..2f26cb4 100644 --- a/packages/python.shrap +++ b/packages/python.shrap @@ -1,5 +1,5 @@ (package - (name "python3") + (name "python") (version "3.14.3") (homepage "https://www.python.org/") (dependencies zlib libopenssl bzip2) diff --git a/src/main.cc b/src/main.cc index afd3536..64767d6 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,31 +1,76 @@ #include "parser.h" #include "util.h" +#include +#include #include #include #include +#include -static bool flag_raw = false; +std::unordered_map packages; +bool flag_raw = false; -void install_package(const std::string &name) { - // TODO: get this by the name field not filename - // TODO: actually resolve dependency tree - // TODO: track installed packages - std::ifstream file("packages/" + name + ".shrap"); - if (!file) { - std::cerr << "Package " << name << "not found.\n"; - std::exit(1); +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::exit(1); + } + + Expr pkg = Expr::parse(file); + packages[pkg.get_one("name").value] = pkg; } +} - Expr pkg = Expr::parse(file); +std::vector +resolve_dependencies(const std::vector &roots) { + std::unordered_map state; + std::vector order; + + std::function dfs = [&](const std::string &name) { + int s = state[name]; + if (s == 2) { + return; + } + if (s == 1) { + throw std::runtime_error("dependency cycle detected"); + } + + if (!packages.contains(name)) { + std::cerr << "Package not found: " << name << "\n"; + std::exit(1); + } + + state[name] = 1; - if (!flag_raw) { try { + const Expr &pkg = packages.at(name); for (const auto &dep : pkg.get("dependencies").children) { - install_package(dep.value); + dfs(dep.value); } } catch (std::out_of_range &) { } + + state[name] = 2; + order.push_back(name); + }; + + for (const auto &r : roots) { + dfs(r); } + return order; +} + +void install_package(const std::string &name) { + // TODO: track installed packages + + if (!packages.contains(name)) { + std::cerr << "Package not found: " << name << "\n"; + std::exit(1); + } + + Expr pkg = packages[name]; std::cout << "\n\n\tInstalling " << pkg.get_one("name").value << " (" << pkg.get_one("version").value << ")...\n\n\n"; @@ -123,22 +168,34 @@ int main(int argc, char **argv) { } Util::shell_command("mkdir -p /tmp/shrap"); - std::vector packages; + load_packages(); + + std::vector to_install; for (size_t i = 1; i < args.size(); ++i) { std::string arg = args[i]; if (arg == "-r") { flag_raw = true; } else { - packages.push_back(arg); + to_install.push_back(arg); } } - if (packages.empty()) { + if (to_install.empty()) { std::cerr << "Usage: " << args[0] << " [-r] package1 [package2 ...]\n"; return 1; } - for (const auto &pkg : packages) { + if (!flag_raw) { + to_install = resolve_dependencies(to_install); + } + + std::cout << "\nFollowing packages will be installed:\n"; + for (const std::string &pkg : to_install) { + std::cout << " - " << pkg << std::endl; + } + std::cin.get(); + + for (const std::string &pkg : to_install) { try { install_package(pkg); } catch (std::exception &e) {