diff --git a/checks/imperative-management.nix b/checks/imperative-management.nix index 0c28f3a..d638716 100644 --- a/checks/imperative-management.nix +++ b/checks/imperative-management.nix @@ -59,6 +59,45 @@ lib.optionalAttrs stdenv.isLinux { ''; }; + install_dummy_force = mkTest { + name = "miniguest-install-dummy-force"; + testScript = '' + machine.succeed(""" + miniguest install -f /tmp/flake1#dummy + """) + assert "foo" in machine.succeed(""" + cat /etc/miniguests/dummy/boot/init + """) + ''; + }; + + install_dummy_twice = mkTest { + name = "miniguest-install-dummy-twice"; + testScript = '' + machine.succeed(""" + miniguest install /tmp/flake1#dummy + """) + assert "--force" in machine.fail(""" + miniguest install /tmp/flake1#dummy 2>&1 + """) + ''; + }; + + install_dummy_twice_force = mkTest { + name = "miniguest-install-dummy-twice-force"; + testScript = '' + machine.succeed(""" + miniguest install /tmp/flake1#dummy + """) + machine.succeed(""" + miniguest install --force /tmp/flake1#dummy + """) + assert "foo" in machine.succeed(""" + cat /etc/miniguests/dummy/boot/init + """) + ''; + }; + install_rename = mkTest { name = "miniguest-install-rename"; testScript = '' diff --git a/tool/install.cpp b/tool/install.cpp index d026f69..172f5b6 100644 --- a/tool/install.cpp +++ b/tool/install.cpp @@ -34,8 +34,15 @@ namespace miniguest { struct CmdInstall : virtual InstallableCommand, virtual MixProfile { std::optional guest_name; + bool force; CmdInstall() { + addFlag({ + .longName = "force", + .shortName = 'f', + .description = "Override an existing guest", + .handler = {&force, true}, + }); addFlag({ .longName = "name", .shortName = 'n', @@ -52,6 +59,7 @@ struct CmdInstall : virtual InstallableCommand, virtual MixProfile { std::string doc() override { return R""(miniguest install [-n|--name ] : guest to build + -f, --force: override an existing guest -n, --name: name of the profile (no default))""; } @@ -75,6 +83,11 @@ struct CmdInstall : virtual InstallableCommand, virtual MixProfile { Context ctx = bld.build(); profile = ctx.profile_path.native(); + ProfileManifest manifest(*getEvalState(), *profile); + + if (!manifest.elements.empty() && !force) + throw Error("A guest named “" + *guest_name + + "” is already installed! use --force to replace it"); auto installableFlake = std::static_pointer_cast(installable); @@ -85,7 +98,6 @@ struct CmdInstall : virtual InstallableCommand, virtual MixProfile { auto [attrPath, resolvedRef, drv] = installableFlake->toDerivation(); - ProfileManifest manifest(*getEvalState(), *profile); ProfileElement element; element.source = {installableFlake->flakeRef, resolvedRef, attrPath}; element.updateStorePaths(getEvalStore(), store, result);