service/dap: use specified working directory for launch requests (#2360)

* service/dap: use specified working directory for launch requests

If a user specifies a working directory in the launch request,
then the process should use that working directory. This may
affect how the program runs and the user should be able to have
control over this.

* service/dap: add tests for launch with working dir

Added tests to make sure the working directory is set correctly.

* service/dap: fix TestWorkingDir on windows

* service/dap: use %q to print quoted string

* cmd/dlv: update dap warning about working dir

* service/dap: change the launch argument to be wd`

* update warning to specify only launch request
This commit is contained in:
Suzy Mueller
2021-03-22 23:06:09 -04:00
committed by GitHub
parent f5d2e132bc
commit 1c9a10529e
3 changed files with 55 additions and 1 deletions

View File

@ -422,7 +422,7 @@ func dapCmd(cmd *cobra.Command, args []string) {
fmt.Fprintf(os.Stderr, "Warning: build flags ignored with dap; specify via launch/attach request instead\n")
}
if workingDir != "" {
fmt.Fprintf(os.Stderr, "Warning: working directory ignored with dap; launch requests must specify full program path\n")
fmt.Fprintf(os.Stderr, "Warning: working directory ignored with dap: specify via launch request instead\n")
}
dlvArgs, targetArgs := splitArgs(cmd, args)
if len(dlvArgs) > 0 {

View File

@ -519,6 +519,19 @@ func (s *Server) onLaunchRequest(request *dap.LaunchRequest) {
s.config.ProcessArgs = append([]string{program}, targetArgs...)
s.config.Debugger.WorkingDir = filepath.Dir(program)
// Set the WorkingDir for this program to the one specified in the request arguments.
wd, ok := request.Arguments["wd"]
if ok {
wdParsed, ok := wd.(string)
if !ok {
s.sendErrorResponse(request.Request,
FailedToLaunch, "Failed to launch",
fmt.Sprintf("'wd' attribute '%v' in debug configuration is not a string.", wd))
return
}
s.config.Debugger.WorkingDir = wdParsed
}
var err error
if s.debugger, err = debugger.New(&s.config.Debugger, s.config.ProcessArgs); err != nil {
s.sendErrorResponse(request.Request,

View File

@ -3,6 +3,7 @@ package dap
import (
"bufio"
"flag"
"fmt"
"io"
"io/ioutil"
"net"
@ -1676,6 +1677,42 @@ func TestSetBreakpoint(t *testing.T) {
})
}
// TestWorkingDir executes to a breakpoint and tests that the specified
// working directory is the one used to run the program.
func TestWorkingDir(t *testing.T) {
runTest(t, "workdir", func(client *daptest.Client, fixture protest.Fixture) {
wd := os.TempDir()
// For Darwin `os.TempDir()` returns `/tmp` which is symlink to `/private/tmp`.
if runtime.GOOS == "darwin" {
wd = "/private/tmp"
}
runDebugSessionWithBPs(t, client, "launch",
// Launch
func() {
client.LaunchRequestWithArgs(map[string]interface{}{
"mode": "exec",
"program": fixture.Path,
"stopOnEntry": false,
"wd": wd,
})
},
// Set breakpoints
fixture.Source, []int{10}, // b main.main
[]onBreakpoint{{
execute: func() {
handleStop(t, client, 1, "main.main", 10)
client.VariablesRequest(1001) // Locals
locals := client.ExpectVariablesResponse(t)
expectChildren(t, locals, "Locals", 2)
expectVarExact(t, locals, 0, "pwd", "pwd", fmt.Sprintf("%q", wd), noChildren)
expectVarExact(t, locals, 1, "err", "err", "error nil", noChildren)
},
disconnect: false,
}})
})
}
// expectEval is a helper for verifying the values within an EvaluateResponse.
// value - the value of the evaluated expression
// hasRef - true if the evaluated expression should have children and therefore a non-0 variable reference
@ -2613,6 +2650,10 @@ func TestBadLaunchRequests(t *testing.T) {
expectFailedToLaunchWithMessage(client.ExpectErrorResponse(t),
"Failed to launch: 'buildFlags' attribute '123' in debug configuration is not a string.")
client.LaunchRequestWithArgs(map[string]interface{}{"mode": "debug", "program": fixture.Source, "wd": 123})
expectFailedToLaunchWithMessage(client.ExpectErrorResponse(t),
"Failed to launch: 'wd' attribute '123' in debug configuration is not a string.")
// Skip detailed message checks for potentially different OS-specific errors.
client.LaunchRequest("exec", fixture.Path+"_does_not_exist", stopOnEntry)
expectFailedToLaunch(client.ExpectErrorResponse(t)) // No such file or directory