Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions internal/devbox/devbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,15 +270,25 @@ func (d *Devbox) RunScript(ctx context.Context, envOpts devopt.EnvOptions, cmdNa
// better alternative since devbox run and devbox shell are not the same.
env["DEVBOX_SHELL_ENABLED"] = "1"

// wrap the arg in double-quotes, and escape any double-quotes inside it
// wrap the arg in double-quotes, and escape any double-quotes inside it.
//
// TODO(gcurtis): this breaks quote-removal in parameter expansion,
// command substitution, and arithmetic expansion:
//
// $ unset x
// $ echo ${x:-"my file"}
// my file
// $ devbox run -- echo '${x:-"my file"}'
// "my file"
for idx, arg := range cmdArgs {
cmdArgs[idx] = strconv.Quote(arg)
}

var cmdWithArgs []string
if _, ok := d.cfg.Scripts()[cmdName]; ok {
// it's a script, so replace the command with the script file's path.
cmdWithArgs = append([]string{shellgen.ScriptPath(d.ProjectDir(), cmdName)}, cmdArgs...)
script := shellgen.ScriptPath(d.ProjectDir(), cmdName)
cmdWithArgs = append([]string{strconv.Quote(script)}, cmdArgs...)
} else {
// Arbitrary commands should also run the hooks, so we write them to a file as well. However, if the
// command args include env variable evaluations, then they'll be evaluated _before_ the hooks run,
Expand All @@ -293,7 +303,8 @@ func (d *Devbox) RunScript(ctx context.Context, envOpts devopt.EnvOptions, cmdNa
if err != nil {
return err
}
cmdWithArgs = []string{shellgen.ScriptPath(d.ProjectDir(), arbitraryCmdFilename)}
script := shellgen.ScriptPath(d.ProjectDir(), arbitraryCmdFilename)
cmdWithArgs = []string{strconv.Quote(script)}
env["DEVBOX_RUN_CMD"] = strings.Join(append([]string{cmdName}, cmdArgs...), " ")
}

Expand Down
2 changes: 1 addition & 1 deletion internal/devbox/shellrc.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ working_dir="$(pwd)"
cd "{{ .ProjectDir }}" || exit

# Source the hooks file, which contains the project's init hooks and plugin hooks.
. {{ .HooksFilePath }}
. "{{ .HooksFilePath }}"

cd "$working_dir" || exit

Expand Down
2 changes: 1 addition & 1 deletion internal/devbox/shellrc_fish.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ set workingDir (pwd)
cd "{{ .ProjectDir }}" || exit

# Source the hooks file, which contains the project's init hooks and plugin hooks.
source {{ .HooksFilePath }}
source "{{ .HooksFilePath }}"

cd "$workingDir" || exit

Expand Down
2 changes: 1 addition & 1 deletion internal/devbox/testdata/shellrc/basic/shellrc.golden
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ working_dir="$(pwd)"
cd "/path/to/projectDir" || exit

# Source the hooks file, which contains the project's init hooks and plugin hooks.
. /path/to/projectDir/.devbox/gen/scripts/.hooks.sh
. "/path/to/projectDir/.devbox/gen/scripts/.hooks.sh"

cd "$working_dir" || exit

Expand Down
2 changes: 1 addition & 1 deletion internal/devbox/testdata/shellrc/noshellrc/shellrc.golden
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ working_dir="$(pwd)"
cd "/path/to/projectDir" || exit

# Source the hooks file, which contains the project's init hooks and plugin hooks.
. /path/to/projectDir/.devbox/gen/scripts/.hooks.sh
. "/path/to/projectDir/.devbox/gen/scripts/.hooks.sh"

cd "$working_dir" || exit

Expand Down
4 changes: 3 additions & 1 deletion internal/nix/nix.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"go.jetpack.io/devbox/internal/boxcli/featureflag"
"go.jetpack.io/devbox/internal/boxcli/usererr"
"go.jetpack.io/devbox/internal/redact"
"go.jetpack.io/devbox/nix/flake"
"golang.org/x/mod/semver"

"go.jetpack.io/devbox/internal/debug"
Expand Down Expand Up @@ -73,13 +74,14 @@ func (*Nix) PrintDevEnv(ctx context.Context, args *PrintDevEnvArgs) (*PrintDevEn
if err != nil {
return nil, errors.WithStack(err)
}
ref := flake.Ref{Type: flake.TypePath, Path: flakeDirResolved}

if len(data) == 0 {
cmd := command("print-dev-env", "--json")
if featureflag.ImpurePrintDevEnv.Enabled() {
cmd.Args = append(cmd.Args, "--impure")
}
cmd.Args = append(cmd.Args, "path:"+flakeDirResolved)
cmd.Args = append(cmd.Args, ref)
slog.Debug("running print-dev-env cmd", "cmd", cmd)
data, err = cmd.Output(ctx)
if insecure, insecureErr := IsExitErrorInsecurePackage(err, "" /*pkgName*/, "" /*installable*/); insecure {
Expand Down
6 changes: 3 additions & 3 deletions internal/shellgen/tmpl/script-wrapper.tmpl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{{/*
This wraps user scripts in devbox.json. The idea is to only run the init
{{/*
This wraps user scripts in devbox.json. The idea is to only run the init
hooks once, even if the init hook calls devbox run again. This will also
protect against using devbox service in the init hook.

Expand All @@ -8,7 +8,7 @@
*/ -}}

if [ -z "${{ .SkipInitHookHash }}" ]; then
. {{ .InitHookPath }}
. "{{ .InitHookPath }}"
fi

{{ .Body }}
23 changes: 23 additions & 0 deletions testscripts/basic/path_whitespace.test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Test that Devbox handles whitespace in project paths.

mkdir 'my project'
cd 'my project'

exec devbox run -- hello
stdout 'Hello, world!'

exec devbox run -- touch 'file1 with spaces'
exists 'file1 with spaces'

exec devbox run test
exists 'file2 with spaces'

-- my project/devbox.json --
{
"packages": ["hello@latest"],
"shell": {
"scripts": {
"test": "touch 'file2 with spaces'"
}
}
}
Loading