@@ -12,6 +12,8 @@ import (
12
12
"os"
13
13
"path/filepath"
14
14
"strings"
15
+
16
+ "go.jetpack.io/devbox/debug"
15
17
)
16
18
17
19
type name string
@@ -30,6 +32,22 @@ type Shell struct {
30
32
path string
31
33
initFile string
32
34
devboxInitFile string
35
+
36
+ // PreInitHook contains commands that will run before the user's init
37
+ // files at shell startup.
38
+ //
39
+ // The script's environment will contain an ORIGINAL_PATH environment
40
+ // variable, which will bet set to the PATH before the shell's init
41
+ // files have had a chance to modify it.
42
+ PreInitHook string
43
+
44
+ // PostInitHook contains commands that will run after the user's init
45
+ // files at shell startup.
46
+ //
47
+ // The script's environment will contain an ORIGINAL_PATH environment
48
+ // variable, which will bet set to the PATH before the shell's init
49
+ // files have had a chance to modify it.
50
+ PostInitHook string
33
51
}
34
52
35
53
// Detect attempts to determine the user's default shell.
@@ -67,6 +85,9 @@ func Detect() (*Shell, error) {
67
85
default :
68
86
sh .name = shUnknown
69
87
}
88
+ debug .Log ("Detected shell: %s" , sh .path )
89
+ debug .Log ("Recognized shell as: %s" , sh .path )
90
+ debug .Log ("Looking for user's shell init file at: %s" , sh .initFile )
70
91
return sh , nil
71
92
}
72
93
@@ -80,33 +101,62 @@ func rcfilePath(basename string) string {
80
101
return filepath .Join (home , basename )
81
102
}
82
103
83
- // SetInit configures the shell to run a script at startup. The script runs
84
- // after the user's usual init files. The script's environment will contain an
85
- // ORIGINAL_PATH environment variable, which will bet set to the PATH before
86
- // the user's init files have had a chance to modify it.
87
- func (s * Shell ) SetInit (script string ) error {
88
- script = strings .TrimSpace (script )
89
- if script == "" {
90
- return nil
104
+ func (s * Shell ) buildInitFile () ([]byte , error ) {
105
+ prehook := strings .TrimSpace (s .PreInitHook )
106
+ posthook := strings .TrimSpace (s .PostInitHook )
107
+ if prehook == "" && posthook == "" {
108
+ return nil , nil
109
+ }
110
+
111
+ buf := bytes.Buffer {}
112
+ if prehook != "" {
113
+ buf .WriteString (`
114
+ # Begin Devbox Pre-init Hook
115
+
116
+ ` )
117
+ buf .WriteString (prehook )
118
+ buf .WriteString (`
119
+
120
+ # End Devbox Pre-init Hook
121
+
122
+ ` )
91
123
}
92
124
93
- initFile , _ := os .ReadFile (s .initFile )
125
+ initFile , err := os .ReadFile (s .initFile )
126
+ if err != nil {
127
+ return nil , err
128
+ }
94
129
initFile = bytes .TrimSpace (initFile )
95
130
if len (initFile ) > 0 {
96
- initFile = append (initFile , '\n' , '\n' )
131
+ buf . Write (initFile )
97
132
}
98
133
99
- buf := bytes . NewBuffer ( initFile )
100
- buf .WriteString (`
134
+ if posthook != "" {
135
+ buf .WriteString (`
101
136
102
- # Begin Devbox Shell Hook
137
+ # Begin Devbox Pre-init Hook
103
138
104
139
` )
105
- buf .WriteString (script )
106
- buf .WriteString (`
140
+ buf .WriteString (posthook )
141
+ buf .WriteString (`
107
142
108
- # End Devbox Shell Hook
109
- ` )
143
+ # End Devbox Post-init Hook` )
144
+ }
145
+
146
+ b := buf .Bytes ()
147
+ b = bytes .TrimSpace (b )
148
+ if len (b ) == 0 {
149
+ return nil , nil
150
+ }
151
+ b = append (b , '\n' )
152
+ return b , nil
153
+ }
154
+
155
+ func (s * Shell ) writeHooks () error {
156
+ initContents , err := s .buildInitFile ()
157
+ if err != nil {
158
+ return err
159
+ }
110
160
111
161
// We need a temp dir (as opposed to a temp file) because zsh uses
112
162
// ZDOTDIR to point to a new directory containing the .zshrc.
@@ -115,16 +165,20 @@ func (s *Shell) SetInit(script string) error {
115
165
return fmt .Errorf ("create temp dir for shell init file: %v" , err )
116
166
}
117
167
devboxInitFile := filepath .Join (tmp , filepath .Base (s .initFile ))
118
- if err := os .WriteFile (devboxInitFile , buf . Bytes () , 0600 ); err != nil {
168
+ if err := os .WriteFile (devboxInitFile , initContents , 0600 ); err != nil {
119
169
return fmt .Errorf ("write to shell init file: %v" , err )
120
170
}
121
171
s .devboxInitFile = devboxInitFile
172
+
173
+ debug .Log ("Wrote devbox shell init file to: %s" , s .devboxInitFile )
174
+ debug .Log ("--- Begin Devbox Shell Init Contents ---\n %s--- End Devbox Shell Init Contents ---" , initContents )
122
175
return nil
123
176
}
124
177
125
178
// ExecCommand is a command that replaces the current shell with s.
126
179
func (s * Shell ) ExecCommand () string {
127
- if s .devboxInitFile == "" {
180
+ if err := s .writeHooks (); err != nil || s .devboxInitFile == "" {
181
+ debug .Log ("Failed to write shell pre-init and post-init hooks: %v" , err )
128
182
return "exec " + s .path
129
183
}
130
184
0 commit comments