resolving dependencies
This commit is contained in:
89
src/main.cc
89
src/main.cc
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user