diff --git a/src/main.cpp b/src/main.cpp index 43e396d..e41e856 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -53,6 +53,8 @@ Subcommands: list List installed packages rollback Show available generations index Build an index.kap from .kap files in a directory + add [v] Add a package to system config (optional version) + remove Remove a package from system config Options: -h, --help Show this help message @@ -218,7 +220,9 @@ int main(int argc, char* argv[]) { || (subcommand == "list") || (subcommand == "fetch-package") || (subcommand == "rollback") - || (subcommand == "index"); + || (subcommand == "index") + || (subcommand == "add") + || (subcommand == "remove"); if (!valid_subcommand) { std::cerr << "error: unknown subcommand '" << subcommand << "'\n\n"; @@ -227,6 +231,7 @@ int main(int argc, char* argv[]) { } const char* file_arg = nullptr; + const char* version_arg = nullptr; bool dry_run = false; for (int i = arg_start + 1; i < argc; ++i) { if (std::string_view(argv[i]) == "-h" @@ -254,8 +259,12 @@ int main(int argc, char* argv[]) { continue; } if (!is_flag(argv[i])) { - file_arg = argv[i]; - break; + if (file_arg == nullptr) { + file_arg = argv[i]; + } else if (version_arg == nullptr) { + version_arg = argv[i]; + break; + } } } @@ -320,6 +329,102 @@ int main(int argc, char* argv[]) { } } + if (subcommand == "add") { + if (file_arg == nullptr) { + std::cerr << "error: no package name specified\n"; + return 1; + } + try { + auto config_path = std::filesystem::path(paths::system_dir()) / "config.kap"; + dsl::SystemConfig cfg; + + if (std::filesystem::exists(config_path)) { + auto src = read_file(config_path.c_str()); + cfg = dsl::parse_system_config(src); + } + + bool found = false; + for (auto& p : cfg.packages) { + if (p.name == file_arg) { + found = true; + if (version_arg != nullptr) { + p.version = version_arg; + std::cout << "updated " << file_arg + << " → version " << version_arg << "\n"; + } else { + std::cout << file_arg << " already in packages\n"; + } + break; + } + } + + if (!found) { + dsl::PackageRef pref; + pref.name = file_arg; + if (version_arg != nullptr) { + pref.version = version_arg; + } + cfg.packages.push_back(std::move(pref)); + std::cout << "added " << file_arg; + if (version_arg != nullptr) { + std::cout << " " << version_arg; + } + std::cout << "\n"; + } + + std::error_code ec; + std::filesystem::create_directories(paths::system_dir(), ec); + std::ofstream out(config_path); + if (!out) { + std::cerr << "error: cannot write " << config_path.string() << "\n"; + return 1; + } + tools::format_config(out, cfg); + return 0; + } catch (const std::exception& e) { + std::cerr << "add error: " << e.what() << "\n"; + return 1; + } + } + + if (subcommand == "remove") { + if (file_arg == nullptr) { + std::cerr << "error: no package name specified\n"; + return 1; + } + try { + auto config_path = std::filesystem::path(paths::system_dir()) / "config.kap"; + if (!std::filesystem::exists(config_path)) { + std::cout << file_arg << " not found (no config)\n"; + return 0; + } + + auto src = read_file(config_path.c_str()); + auto cfg = dsl::parse_system_config(src); + + auto it = std::remove_if(cfg.packages.begin(), cfg.packages.end(), + [&](const dsl::PackageRef& p) { return p.name == file_arg; }); + + if (it == cfg.packages.end()) { + std::cout << file_arg << " not in packages\n"; + return 0; + } + cfg.packages.erase(it, cfg.packages.end()); + std::cout << "removed " << file_arg << "\n"; + + std::ofstream out(config_path); + if (!out) { + std::cerr << "error: cannot write " << config_path.string() << "\n"; + return 1; + } + tools::format_config(out, cfg); + return 0; + } catch (const std::exception& e) { + std::cerr << "remove error: " << e.what() << "\n"; + return 1; + } + } + if (subcommand == "fetch-package") { if (file_arg == nullptr) { std::cerr << "error: no package name specified\n";