Skip to content

Commit ac07204

Browse files
authored
internal/devbox: handle whitespace in paths (#2292)
1 parent f8f5511 commit ac07204

File tree

8 files changed

+47
-11
lines changed

8 files changed

+47
-11
lines changed

internal/devbox/devbox.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -270,15 +270,25 @@ func (d *Devbox) RunScript(ctx context.Context, envOpts devopt.EnvOptions, cmdNa
270270
// better alternative since devbox run and devbox shell are not the same.
271271
env["DEVBOX_SHELL_ENABLED"] = "1"
272272

273-
// wrap the arg in double-quotes, and escape any double-quotes inside it
273+
// wrap the arg in double-quotes, and escape any double-quotes inside it.
274+
//
275+
// TODO(gcurtis): this breaks quote-removal in parameter expansion,
276+
// command substitution, and arithmetic expansion:
277+
//
278+
// $ unset x
279+
// $ echo ${x:-"my file"}
280+
// my file
281+
// $ devbox run -- echo '${x:-"my file"}'
282+
// "my file"
274283
for idx, arg := range cmdArgs {
275284
cmdArgs[idx] = strconv.Quote(arg)
276285
}
277286

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

internal/devbox/shellrc.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ working_dir="$(pwd)"
5656
cd "{{ .ProjectDir }}" || exit
5757

5858
# Source the hooks file, which contains the project's init hooks and plugin hooks.
59-
. {{ .HooksFilePath }}
59+
. "{{ .HooksFilePath }}"
6060

6161
cd "$working_dir" || exit
6262

internal/devbox/shellrc_fish.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ set workingDir (pwd)
5959
cd "{{ .ProjectDir }}" || exit
6060

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

6464
cd "$workingDir" || exit
6565

internal/devbox/testdata/shellrc/basic/shellrc.golden

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ working_dir="$(pwd)"
2121
cd "/path/to/projectDir" || exit
2222

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

2626
cd "$working_dir" || exit
2727

internal/devbox/testdata/shellrc/noshellrc/shellrc.golden

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ working_dir="$(pwd)"
1515
cd "/path/to/projectDir" || exit
1616

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

2020
cd "$working_dir" || exit
2121

internal/nix/nix.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"go.jetpack.io/devbox/internal/boxcli/featureflag"
2424
"go.jetpack.io/devbox/internal/boxcli/usererr"
2525
"go.jetpack.io/devbox/internal/redact"
26+
"go.jetpack.io/devbox/nix/flake"
2627
"golang.org/x/mod/semver"
2728

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

7779
if len(data) == 0 {
7880
cmd := command("print-dev-env", "--json")
7981
if featureflag.ImpurePrintDevEnv.Enabled() {
8082
cmd.Args = append(cmd.Args, "--impure")
8183
}
82-
cmd.Args = append(cmd.Args, "path:"+flakeDirResolved)
84+
cmd.Args = append(cmd.Args, ref)
8385
slog.Debug("running print-dev-env cmd", "cmd", cmd)
8486
data, err = cmd.Output(ctx)
8587
if insecure, insecureErr := IsExitErrorInsecurePackage(err, "" /*pkgName*/, "" /*installable*/); insecure {
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
{{/*
2-
This wraps user scripts in devbox.json. The idea is to only run the init
1+
{{/*
2+
This wraps user scripts in devbox.json. The idea is to only run the init
33
hooks once, even if the init hook calls devbox run again. This will also
44
protect against using devbox service in the init hook.
55

@@ -8,7 +8,7 @@
88
*/ -}}
99

1010
if [ -z "${{ .SkipInitHookHash }}" ]; then
11-
. {{ .InitHookPath }}
11+
. "{{ .InitHookPath }}"
1212
fi
1313

1414
{{ .Body }}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Test that Devbox handles whitespace in project paths.
2+
3+
mkdir 'my project'
4+
cd 'my project'
5+
6+
exec devbox run -- hello
7+
stdout 'Hello, world!'
8+
9+
exec devbox run -- touch 'file1 with spaces'
10+
exists 'file1 with spaces'
11+
12+
exec devbox run test
13+
exists 'file2 with spaces'
14+
15+
-- my project/devbox.json --
16+
{
17+
"packages": ["hello@latest"],
18+
"shell": {
19+
"scripts": {
20+
"test": "touch 'file2 with spaces'"
21+
}
22+
}
23+
}

0 commit comments

Comments
 (0)