CLI: Add multiple image support to image delete (#40686)
David Bennett committed
Jun 2, 2026 at 15:19 UTC
58ad906d00997e10e827f8bfaa4832a236bcc053
4 files changed
+24
-7
src/windows/wslc/commands/ImageRemoveCommand.cpp
+2
-2
@@ -28,7 +28,7 @@ namespace wsl::windows::wslc {
28
std::vector<Argument> ImageRemoveCommand::GetArguments() const
29
{
30
return {
31
- Argument::Create(ArgType::ImageId, true),
31
+ Argument::Create(ArgType::ImageId, true, NO_LIMIT),
32
Argument::Create(ArgType::ImageForce),
33
Argument::Create(ArgType::NoPrune),
34
Argument::Create(ArgType::Session),
@@ -51,4 +51,4 @@ void ImageRemoveCommand::ExecuteInternal(CLIExecutionContext& context) const
51
<< CreateSession //
52
<< DeleteImage;
53
}
54
-} // namespace wsl::windows::wslc
\ No newline at end of file
54
+} // namespace wsl::windows::wslc
src/windows/wslc/tasks/ImageTasks.cpp
+5
-4
@@ -200,13 +200,14 @@ void PushImage(CLIExecutionContext& context)
200
void DeleteImage(CLIExecutionContext& context)
201
{
202
WI_ASSERT(context.Data.Contains(Data::Session));
203
- WI_ASSERT(context.Args.Contains(ArgType::ImageId));
203
auto& session = context.Data.Get<Data::Session>();
205
- auto& imageId = context.Args.Get<ArgType::ImageId>();
206
-
204
+ const auto& imageIds = context.Args.GetAll<ArgType::ImageId>();
205
bool force = context.Args.Contains(ArgType::ImageForce);
206
bool noPrune = context.Args.Contains(ArgType::NoPrune);
209
- services::ImageService::Delete(session, WideToMultiByte(imageId), force, noPrune);
207
+ for (const auto& id : imageIds)
208
+ {
209
+ services::ImageService::Delete(session, WideToMultiByte(id), force, noPrune);
210
+ }
211
}
212
213
void LoadImage(CLIExecutionContext& context)
test/windows/wslc/CommandLineTestCases.h
+2
@@ -214,6 +214,8 @@ COMMAND_LINE_TEST_CASE(L"image list --verbose", L"list", true)
214
COMMAND_LINE_TEST_CASE(L"image list -q", L"list", true)
215
COMMAND_LINE_TEST_CASE(L"image pull ubuntu", L"pull", true)
216
COMMAND_LINE_TEST_CASE(L"pull ubuntu", L"pull", true)
217
+COMMAND_LINE_TEST_CASE(L"image rm cont1 --force --no-prune", L"remove", true)
218
+COMMAND_LINE_TEST_CASE(L"image rm cont1 cont2 cont3 --force --no-prune", L"remove", true)
219
220
// Version command tests
221
COMMAND_LINE_TEST_CASE(L"version", L"version", true)
test/windows/wslc/e2e/WSLCE2EImageDeleteTests.cpp
+15
-1
@@ -27,6 +27,7 @@ class WSLCE2EImageDeleteTests
27
{
28
EnsureContainerDoesNotExist(WslcContainerName);
29
EnsureImageIsDeleted(DebianImage);
30
+ EnsureImageIsDeleted(AlpineImage);
31
return true;
32
}
33
@@ -34,6 +35,7 @@ class WSLCE2EImageDeleteTests
35
{
36
EnsureContainerDoesNotExist(WslcContainerName);
37
EnsureImageIsDeleted(DebianImage);
38
+ EnsureImageIsDeleted(AlpineImage);
39
return true;
40
}
41
@@ -65,6 +67,17 @@ class WSLCE2EImageDeleteTests
67
result.Verify({.Stdout = L"", .Stderr = L"", .ExitCode = 0});
68
}
69
70
+ WSLC_TEST_METHOD(WSLCE2E_Image_Delete_MultipleUnusedImages_Success)
71
+ {
72
+ EnsureImageIsLoaded(DebianImage);
73
+ EnsureImageIsLoaded(AlpineImage);
74
+ VerifyImageIsNotUsed(DebianImage);
75
+ VerifyImageIsNotUsed(AlpineImage);
76
+
77
+ auto result = RunWslc(std::format(L"image delete {} {}", DebianImage.Name, AlpineImage.Name));
78
+ result.Verify({.Stdout = L"", .Stderr = L"", .ExitCode = 0});
79
+ }
80
+
81
WSLC_TEST_METHOD(WSLCE2E_Image_Delete_UsedImage_Failure)
82
{
83
EnsureImageIsLoaded(DebianImage);
@@ -113,6 +126,7 @@ class WSLCE2EImageDeleteTests
126
private:
127
const std::wstring WslcContainerName = L"wslc-test-container";
128
const TestImage& DebianImage = DebianTestImage();
129
+ const TestImage& AlpineImage = AlpineTestImage();
130
const TestImage& InvalidImage = InvalidTestImage();
131
132
std::wstring GetHelpMessage() const
@@ -163,4 +177,4 @@ private:
177
return options.str();
178
}
179
};
166
-} // namespace WSLCE2ETests
\ No newline at end of file
180
+} // namespace WSLCE2ETests