Skip to content

Commit 76d75a7

Browse files
mikeland73gcurtis
andauthored
[plugins] Add init hook to plugins. Add ruby gem bin to path DEV-1271 (#389)
## Summary * Adds init hooks to plugins using same structure as devbox.json * Ensures ruby gem bin path is in PATH. Adding in an init hook ensures we respect user provided `$GEM_HOME` (currently it's not possible to override plugin env vars, but once we allow env vars in `devbox.json` they will take precedence. cc: @mohsenari @Lagoja ## How was it tested? ``` devbox add ruby nginx devbox shell gem install rails which rails ``` Signed-off-by: Mike Landau <mikeland86@gmail.com> Co-authored-by: Greg Curtis <greg.curtis@jetpack.io>
1 parent 7878cd9 commit 76d75a7

File tree

14 files changed

+427
-376
lines changed

14 files changed

+427
-376
lines changed

internal/impl/config.go

+3-113
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,15 @@
44
package impl
55

66
import (
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
20696
func findConfigDir(path string) (string, error) {
20797
debug.Log("findConfigDir: path is %s\n", path)

0 commit comments

Comments
 (0)