44package impl
55
66import (
7- "encoding/json"
8- "fmt"
97 "os"
108 "path/filepath"
119 "strings"
12- "unicode"
1310
1411 "github.com/pkg/errors"
1512 "go.jetpack.io/devbox/internal/boxcli/usererr"
1613 "go.jetpack.io/devbox/internal/cuecfg"
1714 "go.jetpack.io/devbox/internal/debug"
15+ "go.jetpack.io/devbox/internal/impl/shellcmd"
1816 "go.jetpack.io/devbox/internal/planner/plansdk"
1917)
2018
@@ -36,8 +34,8 @@ type Config struct {
3634 // Shell configures the devbox shell environment.
3735 Shell struct {
3836 // InitHook contains commands that will run at shell startup.
39- InitHook ConfigShellCmds `json:"init_hook,omitempty"`
40- Scripts map [string ]* ConfigShellCmds `json:"scripts,omitempty"`
37+ InitHook shellcmd. Commands `json:"init_hook,omitempty"`
38+ Scripts map [string ]* shellcmd. Commands `json:"scripts,omitempty"`
4139 } `json:"shell,omitempty"`
4240
4341 // Nixpkgs specifies the repository to pull packages from
@@ -94,114 +92,6 @@ func WriteConfig(path string, cfg *Config) error {
9492 return cuecfg .WriteFile (path , cfg )
9593}
9694
97- // Formats for marshalling and unmarshalling a series of shell commands in a
98- // devbox config.
99- const (
100- // CmdArray formats shell commands as an array of of strings.
101- CmdArray CmdFormat = iota
102-
103- // CmdString formats shell commands as a single string.
104- CmdString
105- )
106-
107- // CmdFormat defines a way of formatting shell commands in a devbox config.
108- type CmdFormat int
109-
110- func (c CmdFormat ) String () string {
111- switch c {
112- case CmdArray :
113- return "array"
114- case CmdString :
115- return "string"
116- default :
117- return fmt .Sprintf ("invalid (%d)" , c )
118- }
119- }
120-
121- // ConfigShellCmds marshals and unmarshals shell commands from a devbox config
122- // as either a single string or an array of strings. It preserves the original
123- // value such that:
124- //
125- // data == marshal(unmarshal(data)))
126- type ConfigShellCmds struct {
127- // MarshalAs determines how MarshalJSON encodes the shell commands.
128- // UnmarshalJSON will set MarshalAs automatically so that commands
129- // marshal back to their original format. The default zero-value
130- // formats them as an array.
131- //
132- MarshalAs CmdFormat
133- Cmds []string
134- }
135-
136- // AppendScript appends each line of a script to s.Cmds. It also applies the
137- // following formatting rules:
138- //
139- // - Trim leading newlines from the script.
140- // - Trim trailing whitespace from the script.
141- // - If the first line of the script begins with one or more tabs ('\t'), then
142- // unindent each line by that same number of tabs.
143- // - Remove trailing whitespace from each line.
144- //
145- // Note that unindenting only happens when a line starts with at least as many
146- // tabs as the first line. If it starts with fewer tabs, then it is not
147- // unindented at all.
148- func (s * ConfigShellCmds ) AppendScript (script string ) {
149- script = strings .TrimLeft (script , "\r \n " )
150- script = strings .TrimRightFunc (script , unicode .IsSpace )
151- if len (script ) == 0 {
152- return
153- }
154- prefixLen := strings .IndexFunc (script , func (r rune ) bool { return r != '\t' })
155- prefix := strings .Repeat ("\t " , prefixLen )
156- for _ , line := range strings .Split (script , "\n " ) {
157- line = strings .TrimRightFunc (line , unicode .IsSpace )
158- line = strings .TrimPrefix (line , prefix )
159- s .Cmds = append (s .Cmds , line )
160- }
161- }
162-
163- // MarshalJSON marshals shell commands according to s.MarshalAs. It marshals
164- // commands to a string by joining s.Cmds with newlines.
165- func (s ConfigShellCmds ) MarshalJSON () ([]byte , error ) {
166- switch s .MarshalAs {
167- case CmdArray :
168- return json .Marshal (s .Cmds )
169- case CmdString :
170- return json .Marshal (s .String ())
171- default :
172- panic (fmt .Sprintf ("invalid command format: %s" , s .MarshalAs ))
173- }
174- }
175-
176- // UnmarshalJSON unmarshals shell commands from a string, an array of strings,
177- // or null. When the JSON value is a string, it unmarshals into the first index
178- // of s.Cmds.
179- func (s * ConfigShellCmds ) UnmarshalJSON (data []byte ) error {
180- if len (data ) == 0 || string (data ) == "null" {
181- s .MarshalAs = CmdArray
182- s .Cmds = nil
183- return nil
184- }
185-
186- switch data [0 ] {
187- case '"' :
188- s .MarshalAs = CmdString
189- s .Cmds = []string {"" }
190- return json .Unmarshal (data , & s .Cmds [0 ])
191-
192- case '[' :
193- s .MarshalAs = CmdArray
194- return json .Unmarshal (data , & s .Cmds )
195- default :
196- return nil
197- }
198- }
199-
200- // String formats the commands as a single string by joining them with newlines.
201- func (s * ConfigShellCmds ) String () string {
202- return strings .Join (s .Cmds , "\n " )
203- }
204-
20595// findConfigDir is a utility for using the path
20696func findConfigDir (path string ) (string , error ) {
20797 debug .Log ("findConfigDir: path is %s\n " , path )
0 commit comments