@@ -16,69 +16,84 @@ import (
1616
1717// DevcontainerCLI is an interface for the devcontainer CLI.
1818type DevcontainerCLI interface {
19- Up (ctx context.Context ,workspaceFolder ,configPath string ,opts ... DevcontainerCLIOptions ) (id string ,err error )
20- Exec (ctx context.Context ,workspaceFolder ,configPath string ,cmd string ,cmdArgs []string ,opts ... DevcontainerCLIOptions )error
19+ Up (ctx context.Context ,workspaceFolder ,configPath string ,opts ... DevcontainerCLIUpOptions ) (id string ,err error )
20+ Exec (ctx context.Context ,workspaceFolder ,configPath string ,cmd string ,cmdArgs []string ,opts ... DevcontainerCLIExecOptions )error
2121}
2222
23- // DevcontainerCLIOptions are options for the devcontainer CLI commands.
24- type DevcontainerCLIOptions func (* devcontainerCLIUpConfig )
23+ // DevcontainerCLIUpOptions are options for the devcontainer CLI Up
24+ // command.
25+ type DevcontainerCLIUpOptions func (* devcontainerCLIUpConfig )
26+
27+ type devcontainerCLIUpConfig struct {
28+ args []string // Additional arguments for the Up command.
29+ stdout io.Writer
30+ stderr io.Writer
31+ }
2532
2633// WithRemoveExistingContainer is an option to remove the existing
27- // container. Can only be used with the Up command.
28- func WithRemoveExistingContainer ()DevcontainerCLIOptions {
34+ // container.
35+ func WithRemoveExistingContainer ()DevcontainerCLIUpOptions {
2936return func (o * devcontainerCLIUpConfig ) {
30- if o .command != "up" {
31- panic ("developer error: WithRemoveExistingContainer can only be used with the Up command" )
32- }
3337o .args = append (o .args ,"--remove-existing-container" )
3438}
3539}
3640
37- // WithOutput sets additional stdout and stderr writers for logs.
38- func WithOutput (stdout ,stderr io.Writer )DevcontainerCLIOptions {
41+ // WithUpOutput sets additional stdout and stderr writers for logs
42+ // during Up operations.
43+ func WithUpOutput (stdout ,stderr io.Writer )DevcontainerCLIUpOptions {
3944return func (o * devcontainerCLIUpConfig ) {
4045o .stdout = stdout
4146o .stderr = stderr
4247}
4348}
4449
50+ // DevcontainerCLIExecOptions are options for the devcontainer CLI Exec
51+ // command.
52+ type DevcontainerCLIExecOptions func (* devcontainerCLIExecConfig )
53+
54+ type devcontainerCLIExecConfig struct {
55+ args []string // Additional arguments for the Exec command.
56+ stdout io.Writer
57+ stderr io.Writer
58+ }
59+
60+ // WithExecOutput sets additional stdout and stderr writers for logs
61+ // during Exec operations.
62+ func WithExecOutput (stdout ,stderr io.Writer )DevcontainerCLIExecOptions {
63+ return func (o * devcontainerCLIExecConfig ) {
64+ o .stdout = stdout
65+ o .stderr = stderr
66+ }
67+ }
68+
4569// WithContainerID sets the container ID to target a specific container.
46- // Can only be used with the Exec command.
47- func WithContainerID (id string )DevcontainerCLIOptions {
48- return func (o * devcontainerCLIUpConfig ) {
49- if o .command != "exec" {
50- panic ("developer error: WithContainerID can only be used with the Exec command" )
51- }
70+ func WithContainerID (id string )DevcontainerCLIExecOptions {
71+ return func (o * devcontainerCLIExecConfig ) {
5272o .args = append (o .args ,"--container-id" ,id )
5373}
5474}
5575
5676// WithRemoteEnv sets environment variables for the Exec command.
57- // Can only be used with the Exec command.
58- func WithRemoteEnv (env ... string )DevcontainerCLIOptions {
59- return func (o * devcontainerCLIUpConfig ) {
60- if o .command != "exec" {
61- panic ("developer error: WithRemoteEnv can only be used with the Exec command" )
62- }
77+ func WithRemoteEnv (env ... string )DevcontainerCLIExecOptions {
78+ return func (o * devcontainerCLIExecConfig ) {
6379for _ ,e := range env {
6480o .args = append (o .args ,"--remote-env" ,e )
6581}
6682}
6783}
6884
69- type devcontainerCLIUpConfig struct {
70- command string // The devcontainer CLI command to run, e.g. "up", "exec".
71- removeExistingContainer bool
72- args []string // Additional arguments for the command.
73- stdout io.Writer
74- stderr io.Writer
85+ func applyDevcontainerCLIUpOptions (opts []DevcontainerCLIUpOptions )devcontainerCLIUpConfig {
86+ conf := devcontainerCLIUpConfig {}
87+ for _ ,opt := range opts {
88+ if opt != nil {
89+ opt (& conf )
90+ }
91+ }
92+ return conf
7593}
7694
77- func applyDevcontainerCLIOptions (command string ,opts []DevcontainerCLIOptions )devcontainerCLIUpConfig {
78- conf := devcontainerCLIUpConfig {
79- command :command ,
80- removeExistingContainer :false ,
81- }
95+ func applyDevcontainerCLIExecOptions (opts []DevcontainerCLIExecOptions )devcontainerCLIExecConfig {
96+ conf := devcontainerCLIExecConfig {}
8297for _ ,opt := range opts {
8398if opt != nil {
8499opt (& conf )
@@ -101,9 +116,9 @@ func NewDevcontainerCLI(logger slog.Logger, execer agentexec.Execer) Devcontaine
101116}
102117}
103118
104- func (d * devcontainerCLI )Up (ctx context.Context ,workspaceFolder ,configPath string ,opts ... DevcontainerCLIOptions ) (string ,error ) {
105- conf := applyDevcontainerCLIOptions ( "up" , opts )
106- logger := d .logger .With (slog .F ("workspace_folder" ,workspaceFolder ),slog .F ("config_path" ,configPath ), slog . F ( "recreate" , conf . removeExistingContainer ) )
119+ func (d * devcontainerCLI )Up (ctx context.Context ,workspaceFolder ,configPath string ,opts ... DevcontainerCLIUpOptions ) (string ,error ) {
120+ conf := applyDevcontainerCLIUpOptions ( opts )
121+ logger := d .logger .With (slog .F ("workspace_folder" ,workspaceFolder ),slog .F ("config_path" ,configPath ))
107122
108123args := []string {
109124"up" ,
@@ -145,8 +160,8 @@ func (d *devcontainerCLI) Up(ctx context.Context, workspaceFolder, configPath st
145160return result .ContainerID ,nil
146161}
147162
148- func (d * devcontainerCLI )Exec (ctx context.Context ,workspaceFolder ,configPath string ,cmd string ,cmdArgs []string ,opts ... DevcontainerCLIOptions )error {
149- conf := applyDevcontainerCLIOptions ( "exec" , opts )
163+ func (d * devcontainerCLI )Exec (ctx context.Context ,workspaceFolder ,configPath string ,cmd string ,cmdArgs []string ,opts ... DevcontainerCLIExecOptions )error {
164+ conf := applyDevcontainerCLIExecOptions ( opts )
150165logger := d .logger .With (slog .F ("workspace_folder" ,workspaceFolder ),slog .F ("config_path" ,configPath ))
151166
152167args := []string {"exec" }