Skip to content

Commit

Permalink
testscript: Add Chdir method to change directory
Browse files Browse the repository at this point in the history
It is not currently possible for a custom testscript command
to change the working directory of that script run.
`TestScript.Exec` runs the command in a subprocess,
so one cannot do `ts.Exec("cd", dir)`.

This change adds a `Chdir` method to `TestScript`
that allows changing the working directory of the script.
The implementation is the same as the "cd" command,
which now relies on `Chdir`.

The availability of this function matches similar functionality in the
[`State.Chdir` method of rsc.io/script][1].
(I ported some tests from rsc.io/script to testscript.)

  [1]: https://pkg.go.dev/rsc.io/script#State.Chdir
  • Loading branch information
abhinav authored and mvdan committed Apr 11, 2024
1 parent 9d241da commit 31b9365
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 8 deletions.
9 changes: 1 addition & 8 deletions testscript/cmd.go
Expand Up @@ -61,18 +61,11 @@ func (ts *TestScript) cmdCd(neg bool, args []string) {
}

dir := args[0]
if !filepath.IsAbs(dir) {
dir = filepath.Join(ts.cd, dir)
}
info, err := os.Stat(dir)
err := ts.Chdir(dir)
if os.IsNotExist(err) {
ts.Fatalf("directory %s does not exist", dir)
}
ts.Check(err)
if !info.IsDir() {
ts.Fatalf("%s is not a directory", dir)
}
ts.cd = dir
ts.Logf("%s\n", ts.cd)
}

Expand Down
7 changes: 7 additions & 0 deletions testscript/testdata/custom_cd.txt
@@ -0,0 +1,7 @@
# Verify that a custom command can chdir.

mkChdir foo
exists $WORK/foo

# Current directory is not $WORK.
! exists foo
18 changes: 18 additions & 0 deletions testscript/testscript.go
Expand Up @@ -1043,6 +1043,24 @@ func (ts *TestScript) BackgroundCmds() []*exec.Cmd {
return cmds
}

// Chdir changes the current directory of the script.
// The path may be relative to the current directory.
func (ts *TestScript) Chdir(dir string) error {
if !filepath.IsAbs(dir) {
dir = filepath.Join(ts.cd, dir)
}
info, err := os.Stat(dir)
if err != nil {
return err
}
if !info.IsDir() {
return fmt.Errorf("%s is not a directory", dir)
}

ts.cd = dir
return nil
}

// waitOrStop waits for the already-started command cmd by calling its Wait method.
//
// If cmd does not return before ctx is done, waitOrStop sends it an interrupt
Expand Down
21 changes: 21 additions & 0 deletions testscript/testscript_test.go
Expand Up @@ -263,6 +263,27 @@ func TestScripts(t *testing.T) {
}
},
"echoandexit": echoandexit,
"mkChdir": func(ts *TestScript, neg bool, args []string) {
if neg {
ts.Fatalf("unsupported: ! mkChdir")
}
if len(args) != 1 {
ts.Fatalf("usage: mkChdir dir")
}

dir := args[0]
if !filepath.IsAbs(dir) {
dir = ts.MkAbs(dir)
}

if err := os.MkdirAll(dir, 0o777); err != nil {
ts.Fatalf("cannot create dir: %v", err)
}

if err := ts.Chdir(dir); err != nil {
ts.Fatalf("cannot chdir: %v", err)
}
},
},
Setup: func(env *Env) error {
infos, err := os.ReadDir(env.WorkDir)
Expand Down

0 comments on commit 31b9365

Please sign in to comment.