resolving dependencies

This commit is contained in:
2026-02-15 16:08:12 +01:00
parent a19e668908
commit 9dc1068034
11 changed files with 156 additions and 18 deletions

View File

@@ -1,31 +1,76 @@
#include "parser.h"
#include "util.h"
#include <filesystem>
#include <functional>
#include <span>
#include <sys/stat.h>
#include <thread>
#include <unordered_map>
static bool flag_raw = false;
std::unordered_map<std::string, Expr> 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<std::string>
resolve_dependencies(const std::vector<std::string> &roots) {
std::unordered_map<std::string, int> state;
std::vector<std::string> order;
std::function<void(const std::string &)> 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<std::string> packages;
load_packages();
std::vector<std::string> 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) {