diff --git a/src/cmd/remove/remove.go b/src/cmd/remove/remove.go index 5272b70..a8c807f 100644 --- a/src/cmd/remove/remove.go +++ b/src/cmd/remove/remove.go @@ -13,7 +13,9 @@ import ( // New creates a cobra command func New() *cobra.Command { - return &cobra.Command{ + var options options + + cmd := &cobra.Command{ Use: "remove", Aliases: []string{"rm"}, Short: "Removes context container", @@ -23,12 +25,20 @@ func New() *cobra.Command { if len(args) == 1 { name = args[0] } - return run(cmd.Context(), name) + return run(cmd.Context(), name, options) }, } + + cmd.Flags().BoolVarP(&options.force, "force", "f", false, "force removes container") + + return cmd } -func run(ctx context.Context, name string) error { +type options struct { + force bool +} + +func run(ctx context.Context, name string, options options) error { contexts, err := yey.LoadContexts() if err != nil { return err @@ -49,5 +59,10 @@ func run(ctx context.Context, name string) error { container := yey.ContainerName(contexts.Path, context) - return docker.Remove(ctx, container) + var removeOptions []docker.RemoveOption + if options.force { + removeOptions = append(removeOptions, docker.ForceRemove) + } + + return docker.Remove(ctx, container, removeOptions...) } diff --git a/src/cmd/tidy/tidy.go b/src/cmd/tidy/tidy.go index b7bea9b..6162ac3 100644 --- a/src/cmd/tidy/tidy.go +++ b/src/cmd/tidy/tidy.go @@ -12,17 +12,27 @@ import ( // New creates a cobra command func New() *cobra.Command { - return &cobra.Command{ + var options options + + cmd := &cobra.Command{ Use: "tidy", Short: "Removes unreferenced containers", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { - return run(cmd.Context()) + return run(cmd.Context(), options) }, } + + cmd.Flags().BoolVarP(&options.force, "force", "f", false, "removes containers forcibly") + + return cmd +} + +type options struct { + force bool } -func run(ctx context.Context) error { +func run(ctx context.Context, options options) error { contexts, err := yey.LoadContexts() if err != nil { return err @@ -44,6 +54,7 @@ func run(ctx context.Context) error { return err } + var unreferencedContainers []string for _, container := range names { if !strings.HasPrefix(container, prefix) { continue @@ -51,10 +62,13 @@ func run(ctx context.Context) error { if _, ok := validNames[container]; ok { continue } - if err := docker.Remove(ctx, container); err != nil { - return err - } + unreferencedContainers = append(unreferencedContainers, container) + } + + var removeOptions []docker.RemoveOption + if options.force { + removeOptions = append(removeOptions, docker.ForceRemove) } - return nil + return docker.RemoveMany(ctx, unreferencedContainers, removeOptions...) } diff --git a/src/internal/docker/cli.go b/src/internal/docker/cli.go index 3dcc8a2..7110ca1 100644 --- a/src/internal/docker/cli.go +++ b/src/internal/docker/cli.go @@ -34,7 +34,15 @@ func Start(ctx context.Context, yeyCtx yey.Context, containerName string) error } } -func Remove(ctx context.Context, containerName string) error { +type removeOption struct { + force bool +} + +type RemoveOption func(ro *removeOption) + +var ForceRemove RemoveOption = func(ro *removeOption) { ro.force = true } + +func Remove(ctx context.Context, containerName string, options ...RemoveOption) error { status, err := getContainerStatus(ctx, containerName) if err != nil { return err @@ -44,7 +52,26 @@ func Remove(ctx context.Context, containerName string) error { return nil } - return attachStdPipes(exec.CommandContext(ctx, "docker", "rm", "-v", containerName)).Run() + return RemoveMany(ctx, []string{containerName}, options...) +} + +func RemoveMany(ctx context.Context, containers []string, options ...RemoveOption) error { + if len(containers) == 0 { + return nil + } + + var opts removeOption + for _, opt := range options { + opt(&opts) + } + + args := []string{"rm", "-v"} + if opts.force { + args = append(args, "-f") + } + args = append(args, containers...) + + return attachStdPipes(exec.CommandContext(ctx, "docker", args...)).Run() } func Build(ctx context.Context, dockerPath string, imageTag string, buildArgs map[string]string, context string) error {