mirror of
https://github.com/89luca89/distrobox.git
synced 2026-11-02 20:30:16 -06:00
fix(rm): honor --rm-home and gate the custom-home prompt on it
Thread RemoveHome into removeContainer; only prompt to delete the custom home when --rm-home is set, interactive, and it differs from the host home matching the shell. Without the flag the home is never touched. Signed-off-by: Luca Di Maio <luca.dimaio1@gmail.com>
This commit is contained in:
2 files changed
+91
-4
No files matched your search
+4
-4
@@ -69,7 +69,7 @@ func (c *RmCommand) Execute(ctx context.Context, options RmOptions) (*RmResult,
|
||||
|
||||
var removedDistroboxes []containermanager.Container
|
||||
for _, currentDistrobox := range distroboxesToRemove {
|
||||
err := c.removeContainer(ctx, currentDistrobox, options.Force, options.NoTTY, options.Verbose, userHome)
|
||||
err := c.removeContainer(ctx, currentDistrobox, options.Force, options.NoTTY, options.RemoveHome, options.Verbose, userHome)
|
||||
if err != nil {
|
||||
//nolint:forbidigo // waiting for the logger implementation
|
||||
fmt.Printf("error deleting %s: %s", currentDistrobox.Name, err)
|
||||
@@ -85,6 +85,7 @@ func (c *RmCommand) removeContainer(
|
||||
container containermanager.Container,
|
||||
force bool,
|
||||
noTTY bool,
|
||||
removeHomeRequested bool,
|
||||
verbose bool,
|
||||
userHome string,
|
||||
) error {
|
||||
@@ -103,14 +104,13 @@ func (c *RmCommand) removeContainer(
|
||||
}
|
||||
|
||||
removeHome := false
|
||||
if !noTTY && inspectOutput.ContainerHome != userHome {
|
||||
if removeHomeRequested && !noTTY && inspectOutput.ContainerHome != userHome {
|
||||
question := fmt.Sprintf(
|
||||
"Do you really want to remove custom home of container %s (%s)?",
|
||||
container.Name,
|
||||
inspectOutput.ContainerHome,
|
||||
)
|
||||
answer := c.prompter.Prompt(question, false)
|
||||
removeHome = answer
|
||||
removeHome = c.prompter.Prompt(question, false)
|
||||
}
|
||||
|
||||
cmOptions := containermanager.RmOptions{
|
||||
|
||||
@@ -24,6 +24,93 @@ func newTestRmCommand(mock *testutil.MockContainerManager) *commands.RmCommand {
|
||||
return commands.NewRmCommand(&config.Values{}, mock, prompter)
|
||||
}
|
||||
|
||||
func newTestRmCommandWithInput(mock *testutil.MockContainerManager, input string) *commands.RmCommand {
|
||||
prompter := ui.NewPrompter(*bufio.NewReader(strings.NewReader(input)), io.Discard)
|
||||
return commands.NewRmCommand(&config.Values{}, mock, prompter)
|
||||
}
|
||||
|
||||
// lastRemoveOptions returns the RmOptions passed to the most recent
|
||||
// containerManager.Remove call recorded by the mock.
|
||||
func lastRemoveOptions(t *testing.T, mock *testutil.MockContainerManager) containermanager.RmOptions {
|
||||
t.Helper()
|
||||
require.NotEmpty(t, mock.Spy.Remove, "expected containerManager.Remove to be called")
|
||||
last := mock.Spy.Remove[len(mock.Spy.Remove)-1]
|
||||
opts, ok := last[1].(containermanager.RmOptions)
|
||||
require.True(t, ok, "second Remove arg should be containermanager.RmOptions")
|
||||
return opts
|
||||
}
|
||||
|
||||
// `rm` without --rm-home must never remove the custom home, even
|
||||
// interactively with a custom home and a "yes" waiting on stdin (the shell only
|
||||
// ever prompts/removes when --rm-home is set, distrobox-rm:364-371).
|
||||
func TestRmCommand_RmHome_NotRequested_NeverPrompts(t *testing.T) {
|
||||
t.Setenv("HOME", t.TempDir())
|
||||
|
||||
containerName := "test-rm-no-flag"
|
||||
mock := &testutil.MockContainerManager{
|
||||
ListContainersResult: []containermanager.Container{
|
||||
{Name: containerName, Status: "Exited", Labels: map[string]string{"manager": "distrobox"}},
|
||||
},
|
||||
InspectContainerResult: &containermanager.InspectResult{ContainerHome: "/custom/home/dir"},
|
||||
}
|
||||
// Seed a "y" — if the prompt were (wrongly) shown, the home would be removed.
|
||||
cmd := newTestRmCommandWithInput(mock, "y\n")
|
||||
|
||||
_, err := cmd.Execute(context.Background(), commands.RmOptions{
|
||||
ContainerNames: []string{containerName},
|
||||
RemoveHome: false,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.False(t, lastRemoveOptions(t, mock).RemoveHome,
|
||||
"home must not be removed without --rm-home")
|
||||
}
|
||||
|
||||
// `rm --rm-home` interactively prompts; an explicit "yes" removes the home.
|
||||
func TestRmCommand_RmHome_Requested_ConfirmedRemoves(t *testing.T) {
|
||||
t.Setenv("HOME", t.TempDir())
|
||||
|
||||
containerName := "test-rm-flag-yes"
|
||||
mock := &testutil.MockContainerManager{
|
||||
ListContainersResult: []containermanager.Container{
|
||||
{Name: containerName, Status: "Exited", Labels: map[string]string{"manager": "distrobox"}},
|
||||
},
|
||||
InspectContainerResult: &containermanager.InspectResult{ContainerHome: "/custom/home/dir"},
|
||||
}
|
||||
cmd := newTestRmCommandWithInput(mock, "y\n")
|
||||
|
||||
_, err := cmd.Execute(context.Background(), commands.RmOptions{
|
||||
ContainerNames: []string{containerName},
|
||||
RemoveHome: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.True(t, lastRemoveOptions(t, mock).RemoveHome,
|
||||
"home should be removed with --rm-home and a confirmed prompt")
|
||||
}
|
||||
|
||||
// `rm --rm-home --yes` (non-interactive) never removes the home, matching
|
||||
// the shell which skips the prompt and defaults to "no" (distrobox-rm:365-366).
|
||||
func TestRmCommand_RmHome_Requested_NonInteractiveKeepsHome(t *testing.T) {
|
||||
t.Setenv("HOME", t.TempDir())
|
||||
|
||||
containerName := "test-rm-flag-yes-noninteractive"
|
||||
mock := &testutil.MockContainerManager{
|
||||
ListContainersResult: []containermanager.Container{
|
||||
{Name: containerName, Status: "Exited", Labels: map[string]string{"manager": "distrobox"}},
|
||||
},
|
||||
InspectContainerResult: &containermanager.InspectResult{ContainerHome: "/custom/home/dir"},
|
||||
}
|
||||
cmd := newTestRmCommand(mock)
|
||||
|
||||
_, err := cmd.Execute(context.Background(), commands.RmOptions{
|
||||
ContainerNames: []string{containerName},
|
||||
RemoveHome: true,
|
||||
NoTTY: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.False(t, lastRemoveOptions(t, mock).RemoveHome,
|
||||
"non-interactive rm must not remove the home even with --rm-home")
|
||||
}
|
||||
|
||||
// writeExportedDesktopApp writes a minimal desktop file that
|
||||
// findExportedDesktopApps will match for the given containerName (i.e.
|
||||
// the per-app desktop entries created by distrobox-export, not the
|
||||
|
||||
Reference in new issue
Block a user