Skip to content

Commit 3ed922b

Browse files
authored
devbox run inside shell (#331)
## Summary Added support for running devbox run when inside a devbox shell ## How was it tested? - Compile devbox - `./devbox shell` - `./devbox run <script_name>` example output: devbox.json ```json { "packages": [ "python38" ], "shell": { "init_hook": null, "scripts": { "test": [ "echo helloworldtest", "ls -l" ] } }, "nixpkgs": { "commit": "af9e00071d0971eb292fd5abef334e66eda3cb69" } } ``` output: ```sh (devbox) ➜ sample1 ./devbox run test helloworldtest total 23700 -rwxr-xr-x 1 mohsenansari 21500226 Nov 30 18:41 devbox -rw-r--r-- 1 mohsenansari 250 Nov 30 22:26 devbox.json -rw-r--r-- 1 mohsenansari 0 Oct 5 18:27 requirements.txt -rw-r--r-- 1 mohsenansari 0 Oct 5 18:26 setup.py ```
1 parent 3793a2f commit 3ed922b

File tree

3 files changed

+55
-3
lines changed

3 files changed

+55
-3
lines changed

boxcli/run.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,11 @@ func runScriptCmd(args []string, flags runCmdFlags) error {
5757
}
5858

5959
if devbox.IsDevboxShellEnabled() {
60-
return errors.New("You are already in an active devbox shell.\nRun 'exit' before calling devbox run again. Shell inception is not supported yet.")
60+
err = box.RunScriptInShell(script)
61+
} else {
62+
err = box.RunScript(script)
6163
}
6264

63-
err = box.RunScript(script)
64-
6565
var exitErr *exec.ExitError
6666
if errors.As(err, &exitErr) {
6767
return nil

devbox.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,32 @@ func (d *Devbox) Shell() error {
265265
return shell.Run(nixShellFilePath)
266266
}
267267

268+
func (d *Devbox) RunScriptInShell(scriptName string) error {
269+
profileDir, err := d.profileDir()
270+
if err != nil {
271+
return err
272+
}
273+
274+
script := d.cfg.Shell.Scripts[scriptName]
275+
if script == nil {
276+
return errors.Errorf("unable to find a script with name %s", scriptName)
277+
}
278+
279+
shell, err := nix.DetectShell(
280+
nix.WithProfile(profileDir),
281+
nix.WithHistoryFile(filepath.Join(d.configDir, shellHistoryFile)),
282+
nix.WithUserScript(scriptName, script.String()),
283+
nix.WithConfigDir(d.configDir),
284+
)
285+
286+
if err != nil {
287+
fmt.Print(err)
288+
shell = &nix.Shell{}
289+
}
290+
291+
return shell.RunInShell()
292+
}
293+
268294
// TODO: consider unifying the implementations of RunScript and Shell.
269295
func (d *Devbox) RunScript(scriptName string) error {
270296
if err := d.ensurePackagesAreInstalled(install); err != nil {

nix/shell.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,32 @@ func (s *Shell) execCommand() string {
265265
return strings.Join(args, " ")
266266
}
267267

268+
func (s *Shell) RunInShell() error {
269+
env := append(
270+
os.Environ(),
271+
// Prevent the user's shellrc from re-sourcing nix-daemon.sh
272+
// inside the devbox shell.
273+
"__ETC_PROFILE_NIX_SOURCED=1",
274+
)
275+
debug.Log("Running inside devbox shell with environment: %v", env)
276+
cmd := exec.Command(s.execCommandInShell())
277+
cmd.Env = env
278+
cmd.Stdin = os.Stdin
279+
cmd.Stdout = os.Stdout
280+
cmd.Stderr = os.Stderr
281+
debug.Log("Executing command from inside devbox shell: %v", cmd.Args)
282+
return errors.WithStack(cmd.Run())
283+
}
284+
285+
func (s *Shell) execCommandInShell() (string, string, string) {
286+
args := []string{}
287+
288+
if s.ScriptCommand != "" {
289+
args = append(args, "-ic")
290+
}
291+
return s.binPath, strings.Join(args, " "), s.ScriptCommand
292+
}
293+
268294
func (s *Shell) writeDevboxShellrc() (path string, err error) {
269295
if s.userShellrcPath == "" {
270296
// If this happens, then there's a bug with how we detect shells

0 commit comments

Comments
 (0)