#include import cargoxx.cli; import cargoxx.linkdb; import cargoxx.manifest; import cargoxx.util; import std; using cargoxx::cli::cmd_add; using cargoxx::cli::cmd_new; using cargoxx::cli::cmd_remove; using cargoxx::linkdb::Database; using cargoxx::linkdb::Recipe; using cargoxx::util::ErrorCode; namespace manifest = cargoxx::manifest; namespace { // Disable the network resolver chains in cmd_add (which we use as a // fixture-builder). Per-version-resolution tests live elsewhere. struct DisableAutoResolveScope { DisableAutoResolveScope() { setenv("CARGOXX_NO_AUTORESOLVE", "1", 1); } }; const DisableAutoResolveScope autoresolve_disabled_; auto fresh_dir() -> std::filesystem::path { auto d = std::filesystem::temp_directory_path() / std::format("cargoxx-remove-test-{}", std::random_device{}()); std::filesystem::create_directories(d); return d; } auto overlay_path(const std::filesystem::path& dir) -> std::filesystem::path { return dir / "overlay.sqlite"; } auto scaffold(const std::filesystem::path& parent) -> std::filesystem::path { REQUIRE(cmd_new("app", false, parent).has_value()); return parent / "app"; } auto seed_recipe(const std::filesystem::path& overlay, const std::string& name, const std::string& nixpkgs_attr) { auto db = Database::open(overlay); REQUIRE(db.has_value()); REQUIRE(db->add_manual(name, "*", Recipe{ .nixpkgs_attr = nixpkgs_attr, .find_package = std::format("{} CONFIG REQUIRED", name), .targets = {std::format("{}::{}", name, name)}, .source = "manual", }) .has_value()); } } // namespace TEST_CASE("cmd_remove drops the dependency", "[cli][remove]") { auto parent = fresh_dir(); auto root = scaffold(parent); seed_recipe(overlay_path(parent), "fmt", "fmt_10"); REQUIRE(cmd_add(root, "fmt", "10.2.0", {}, overlay_path(parent)).has_value()); REQUIRE(cmd_remove(root, "fmt").has_value()); auto m = manifest::parse(root / "Cargoxx.toml"); REQUIRE(m.has_value()); REQUIRE(m->dependencies.empty()); } TEST_CASE("cmd_remove leaves other deps in place", "[cli][remove]") { auto parent = fresh_dir(); auto root = scaffold(parent); seed_recipe(overlay_path(parent), "fmt", "fmt_10"); seed_recipe(overlay_path(parent), "spdlog", "spdlog"); REQUIRE(cmd_add(root, "fmt", "10.2.0", {}, overlay_path(parent)).has_value()); REQUIRE(cmd_add(root, "spdlog", "1.13.0", {}, overlay_path(parent)).has_value()); REQUIRE(cmd_remove(root, "fmt").has_value()); auto m = manifest::parse(root / "Cargoxx.toml"); REQUIRE(m.has_value()); REQUIRE(m->dependencies.size() == 1); REQUIRE(m->dependencies[0].name == "spdlog"); } TEST_CASE("cmd_remove errors on unknown dep", "[cli][remove]") { auto parent = fresh_dir(); auto root = scaffold(parent); auto r = cmd_remove(root, "fmt"); REQUIRE_FALSE(r.has_value()); REQUIRE(r.error().code == ErrorCode::ManifestInvalidField); }