feat: add kappa add and kappa remove subcommands
- kappa add <pkg> [version] — adds/updates package in system config
packages{} block; creates config if it doesn't exist
- kappa remove <pkg> — removes package from config; idempotent
(no error if package isn't present)
- Supports --root flag for custom KAPPA_ROOT
- User workflow: kappa add make && kappa rebuild
No manual config editing needed.
This commit is contained in:
+106
-1
@@ -53,6 +53,8 @@ Subcommands:
|
|||||||
list List installed packages
|
list List installed packages
|
||||||
rollback Show available generations
|
rollback Show available generations
|
||||||
index <dir> Build an index.kap from .kap files in a directory
|
index <dir> Build an index.kap from .kap files in a directory
|
||||||
|
add <pkg> [v] Add a package to system config (optional version)
|
||||||
|
remove <pkg> Remove a package from system config
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
-h, --help Show this help message
|
-h, --help Show this help message
|
||||||
@@ -218,7 +220,9 @@ int main(int argc, char* argv[]) {
|
|||||||
|| (subcommand == "list")
|
|| (subcommand == "list")
|
||||||
|| (subcommand == "fetch-package")
|
|| (subcommand == "fetch-package")
|
||||||
|| (subcommand == "rollback")
|
|| (subcommand == "rollback")
|
||||||
|| (subcommand == "index");
|
|| (subcommand == "index")
|
||||||
|
|| (subcommand == "add")
|
||||||
|
|| (subcommand == "remove");
|
||||||
|
|
||||||
if (!valid_subcommand) {
|
if (!valid_subcommand) {
|
||||||
std::cerr << "error: unknown subcommand '" << subcommand << "'\n\n";
|
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* file_arg = nullptr;
|
||||||
|
const char* version_arg = nullptr;
|
||||||
bool dry_run = false;
|
bool dry_run = false;
|
||||||
for (int i = arg_start + 1; i < argc; ++i) {
|
for (int i = arg_start + 1; i < argc; ++i) {
|
||||||
if (std::string_view(argv[i]) == "-h"
|
if (std::string_view(argv[i]) == "-h"
|
||||||
@@ -254,10 +259,14 @@ int main(int argc, char* argv[]) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!is_flag(argv[i])) {
|
if (!is_flag(argv[i])) {
|
||||||
|
if (file_arg == nullptr) {
|
||||||
file_arg = argv[i];
|
file_arg = argv[i];
|
||||||
|
} else if (version_arg == nullptr) {
|
||||||
|
version_arg = argv[i];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (subcommand == "list") {
|
if (subcommand == "list") {
|
||||||
auto entries = install::read_installed();
|
auto entries = install::read_installed();
|
||||||
@@ -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 (subcommand == "fetch-package") {
|
||||||
if (file_arg == nullptr) {
|
if (file_arg == nullptr) {
|
||||||
std::cerr << "error: no package name specified\n";
|
std::cerr << "error: no package name specified\n";
|
||||||
|
|||||||
Reference in New Issue
Block a user