dap: support stopOnEntry to configure behavior when starting the debugger
This will configure the default behavior when beginning to evaluate a build target. When `stopOnEntry` is used, it will default to `stepNext`. Otherwise, `stepContinue` will be used. Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
This commit is contained in:
+4
-15
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/docker/buildx/dap"
|
"github.com/docker/buildx/dap"
|
||||||
|
"github.com/docker/buildx/dap/common"
|
||||||
"github.com/docker/buildx/util/cobrautil"
|
"github.com/docker/buildx/util/cobrautil"
|
||||||
"github.com/docker/buildx/util/ioset"
|
"github.com/docker/buildx/util/ioset"
|
||||||
"github.com/docker/buildx/util/progress"
|
"github.com/docker/buildx/util/progress"
|
||||||
@@ -20,31 +21,18 @@ func dapCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
|
|||||||
}
|
}
|
||||||
cobrautil.MarkCommandExperimental(cmd)
|
cobrautil.MarkCommandExperimental(cmd)
|
||||||
|
|
||||||
flags := cmd.Flags()
|
|
||||||
flags.StringVar(&options.OnFlag, "on", "error", "When to pause the adapter ([always, error])")
|
|
||||||
|
|
||||||
cobrautil.MarkFlagsExperimental(flags, "on")
|
|
||||||
|
|
||||||
dapBuildCmd := buildCmd(dockerCli, rootOpts, &options)
|
dapBuildCmd := buildCmd(dockerCli, rootOpts, &options)
|
||||||
dapBuildCmd.Args = cobra.RangeArgs(0, 1)
|
dapBuildCmd.Args = cobra.RangeArgs(0, 1)
|
||||||
cmd.AddCommand(dapBuildCmd)
|
cmd.AddCommand(dapBuildCmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
type dapOptions struct {
|
type dapOptions struct{}
|
||||||
// OnFlag is a flag to configure the timing of launching the debugger.
|
|
||||||
OnFlag string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *dapOptions) New(in ioset.In) (debuggerInstance, error) {
|
func (d *dapOptions) New(in ioset.In) (debuggerInstance, error) {
|
||||||
invokeConfig, err := parseInvokeConfig("", d.OnFlag)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
conn := dap.NewConn(in.Stdin, in.Stdout)
|
conn := dap.NewConn(in.Stdin, in.Stdout)
|
||||||
return &adapterProtocolDebugger{
|
return &adapterProtocolDebugger{
|
||||||
Adapter: dap.New[LaunchConfig](invokeConfig),
|
Adapter: dap.New[LaunchConfig](),
|
||||||
conn: conn,
|
conn: conn,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@@ -53,6 +41,7 @@ type LaunchConfig struct {
|
|||||||
Dockerfile string `json:"dockerfile,omitempty"`
|
Dockerfile string `json:"dockerfile,omitempty"`
|
||||||
ContextPath string `json:"contextPath,omitempty"`
|
ContextPath string `json:"contextPath,omitempty"`
|
||||||
Target string `json:"target,omitempty"`
|
Target string `json:"target,omitempty"`
|
||||||
|
common.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
type adapterProtocolDebugger struct {
|
type adapterProtocolDebugger struct {
|
||||||
|
|||||||
+41
-42
@@ -11,19 +11,20 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/docker/buildx/build"
|
"github.com/docker/buildx/build"
|
||||||
|
"github.com/docker/buildx/dap/common"
|
||||||
"github.com/google/go-dap"
|
"github.com/google/go-dap"
|
||||||
gateway "github.com/moby/buildkit/frontend/gateway/client"
|
gateway "github.com/moby/buildkit/frontend/gateway/client"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Adapter[T any] struct {
|
type Adapter[C LaunchConfig] struct {
|
||||||
srv *Server
|
srv *Server
|
||||||
eg *errgroup.Group
|
eg *errgroup.Group
|
||||||
cfg build.InvokeConfig
|
cfg common.Config
|
||||||
|
|
||||||
initialized chan struct{}
|
initialized chan struct{}
|
||||||
started chan launchResponse[T]
|
started chan launchResponse[C]
|
||||||
configuration chan struct{}
|
configuration chan struct{}
|
||||||
|
|
||||||
evaluateReqCh chan *evaluateRequest
|
evaluateReqCh chan *evaluateRequest
|
||||||
@@ -36,24 +37,21 @@ type Adapter[T any] struct {
|
|||||||
idPool *idPool
|
idPool *idPool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New[T any](cfg *build.InvokeConfig) *Adapter[T] {
|
func New[C LaunchConfig]() *Adapter[C] {
|
||||||
d := &Adapter[T]{
|
d := &Adapter[C]{
|
||||||
initialized: make(chan struct{}),
|
initialized: make(chan struct{}),
|
||||||
started: make(chan launchResponse[T], 1),
|
started: make(chan launchResponse[C], 1),
|
||||||
configuration: make(chan struct{}),
|
configuration: make(chan struct{}),
|
||||||
evaluateReqCh: make(chan *evaluateRequest),
|
evaluateReqCh: make(chan *evaluateRequest),
|
||||||
threads: make(map[int]*thread),
|
threads: make(map[int]*thread),
|
||||||
nextThreadID: 1,
|
nextThreadID: 1,
|
||||||
idPool: new(idPool),
|
idPool: new(idPool),
|
||||||
}
|
}
|
||||||
if cfg != nil {
|
|
||||||
d.cfg = *cfg
|
|
||||||
}
|
|
||||||
d.srv = NewServer(d.dapHandler())
|
d.srv = NewServer(d.dapHandler())
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Adapter[T]) Start(ctx context.Context, conn Conn) (T, error) {
|
func (d *Adapter[C]) Start(ctx context.Context, conn Conn) (C, error) {
|
||||||
d.eg, _ = errgroup.WithContext(ctx)
|
d.eg, _ = errgroup.WithContext(ctx)
|
||||||
d.eg.Go(func() error {
|
d.eg.Go(func() error {
|
||||||
return d.srv.Serve(ctx, conn)
|
return d.srv.Serve(ctx, conn)
|
||||||
@@ -65,10 +63,11 @@ func (d *Adapter[T]) Start(ctx context.Context, conn Conn) (T, error) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
resp.Error = context.Canceled
|
resp.Error = context.Canceled
|
||||||
}
|
}
|
||||||
|
d.cfg = resp.Config.GetConfig()
|
||||||
return resp.Config, resp.Error
|
return resp.Config, resp.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Adapter[T]) Stop() error {
|
func (d *Adapter[C]) Stop() error {
|
||||||
if d.eg == nil {
|
if d.eg == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -96,7 +95,7 @@ func (d *Adapter[T]) Stop() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Adapter[T]) Initialize(c Context, req *dap.InitializeRequest, resp *dap.InitializeResponse) error {
|
func (d *Adapter[C]) Initialize(c Context, req *dap.InitializeRequest, resp *dap.InitializeResponse) error {
|
||||||
close(d.initialized)
|
close(d.initialized)
|
||||||
|
|
||||||
// Set capabilities.
|
// Set capabilities.
|
||||||
@@ -104,36 +103,36 @@ func (d *Adapter[T]) Initialize(c Context, req *dap.InitializeRequest, resp *dap
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type launchResponse[T any] struct {
|
type launchResponse[C any] struct {
|
||||||
Config T
|
Config C
|
||||||
Error error
|
Error error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Adapter[T]) Launch(c Context, req *dap.LaunchRequest, resp *dap.LaunchResponse) error {
|
func (d *Adapter[C]) Launch(c Context, req *dap.LaunchRequest, resp *dap.LaunchResponse) error {
|
||||||
defer close(d.started)
|
defer close(d.started)
|
||||||
|
|
||||||
var cfg T
|
var cfg C
|
||||||
if err := json.Unmarshal(req.Arguments, &cfg); err != nil {
|
if err := json.Unmarshal(req.Arguments, &cfg); err != nil {
|
||||||
d.started <- launchResponse[T]{Error: err}
|
d.started <- launchResponse[C]{Error: err}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
d.start(c)
|
d.start(c)
|
||||||
|
|
||||||
d.started <- launchResponse[T]{Config: cfg}
|
d.started <- launchResponse[C]{Config: cfg}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Adapter[T]) Disconnect(c Context, req *dap.DisconnectRequest, resp *dap.DisconnectResponse) error {
|
func (d *Adapter[C]) Disconnect(c Context, req *dap.DisconnectRequest, resp *dap.DisconnectResponse) error {
|
||||||
close(d.evaluateReqCh)
|
close(d.evaluateReqCh)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Adapter[T]) start(c Context) {
|
func (d *Adapter[C]) start(c Context) {
|
||||||
c.Go(d.launch)
|
c.Go(d.launch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Adapter[T]) Continue(c Context, req *dap.ContinueRequest, resp *dap.ContinueResponse) error {
|
func (d *Adapter[C]) Continue(c Context, req *dap.ContinueRequest, resp *dap.ContinueResponse) error {
|
||||||
d.threadsMu.RLock()
|
d.threadsMu.RLock()
|
||||||
t := d.threads[req.Arguments.ThreadId]
|
t := d.threads[req.Arguments.ThreadId]
|
||||||
d.threadsMu.RUnlock()
|
d.threadsMu.RUnlock()
|
||||||
@@ -142,7 +141,7 @@ func (d *Adapter[T]) Continue(c Context, req *dap.ContinueRequest, resp *dap.Con
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Adapter[T]) Next(c Context, req *dap.NextRequest, resp *dap.NextResponse) error {
|
func (d *Adapter[C]) Next(c Context, req *dap.NextRequest, resp *dap.NextResponse) error {
|
||||||
d.threadsMu.RLock()
|
d.threadsMu.RLock()
|
||||||
t := d.threads[req.Arguments.ThreadId]
|
t := d.threads[req.Arguments.ThreadId]
|
||||||
d.threadsMu.RUnlock()
|
d.threadsMu.RUnlock()
|
||||||
@@ -151,7 +150,7 @@ func (d *Adapter[T]) Next(c Context, req *dap.NextRequest, resp *dap.NextRespons
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Adapter[T]) SetBreakpoints(c Context, req *dap.SetBreakpointsRequest, resp *dap.SetBreakpointsResponse) error {
|
func (d *Adapter[C]) SetBreakpoints(c Context, req *dap.SetBreakpointsRequest, resp *dap.SetBreakpointsResponse) error {
|
||||||
// TODO: implement breakpoints
|
// TODO: implement breakpoints
|
||||||
for range req.Arguments.Breakpoints {
|
for range req.Arguments.Breakpoints {
|
||||||
// Fail to create all breakpoints that were requested.
|
// Fail to create all breakpoints that were requested.
|
||||||
@@ -163,13 +162,13 @@ func (d *Adapter[T]) SetBreakpoints(c Context, req *dap.SetBreakpointsRequest, r
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Adapter[T]) ConfigurationDone(c Context, req *dap.ConfigurationDoneRequest, resp *dap.ConfigurationDoneResponse) error {
|
func (d *Adapter[C]) ConfigurationDone(c Context, req *dap.ConfigurationDoneRequest, resp *dap.ConfigurationDoneResponse) error {
|
||||||
d.configuration <- struct{}{}
|
d.configuration <- struct{}{}
|
||||||
close(d.configuration)
|
close(d.configuration)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Adapter[T]) launch(c Context) {
|
func (d *Adapter[C]) launch(c Context) {
|
||||||
// Send initialized event.
|
// Send initialized event.
|
||||||
c.C() <- &dap.InitializedEvent{
|
c.C() <- &dap.InitializedEvent{
|
||||||
Event: dap.Event{
|
Event: dap.Event{
|
||||||
@@ -198,7 +197,7 @@ func (d *Adapter[T]) launch(c Context) {
|
|||||||
started := c.Go(func(c Context) {
|
started := c.Go(func(c Context) {
|
||||||
defer d.deleteThread(c, t)
|
defer d.deleteThread(c, t)
|
||||||
defer close(req.errCh)
|
defer close(req.errCh)
|
||||||
req.errCh <- t.Evaluate(c, req.c, req.ref, req.meta, req.inputs)
|
req.errCh <- t.Evaluate(c, req.c, req.ref, req.meta, req.inputs, d.cfg)
|
||||||
})
|
})
|
||||||
|
|
||||||
if !started {
|
if !started {
|
||||||
@@ -209,7 +208,7 @@ func (d *Adapter[T]) launch(c Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Adapter[T]) newThread(ctx Context, name string) (t *thread) {
|
func (d *Adapter[C]) newThread(ctx Context, name string) (t *thread) {
|
||||||
d.threadsMu.Lock()
|
d.threadsMu.Lock()
|
||||||
id := d.nextThreadID
|
id := d.nextThreadID
|
||||||
t = &thread{
|
t = &thread{
|
||||||
@@ -232,14 +231,14 @@ func (d *Adapter[T]) newThread(ctx Context, name string) (t *thread) {
|
|||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Adapter[T]) getThread(id int) (t *thread) {
|
func (d *Adapter[C]) getThread(id int) (t *thread) {
|
||||||
d.threadsMu.Lock()
|
d.threadsMu.Lock()
|
||||||
t = d.threads[id]
|
t = d.threads[id]
|
||||||
d.threadsMu.Unlock()
|
d.threadsMu.Unlock()
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Adapter[T]) deleteThread(ctx Context, t *thread) {
|
func (d *Adapter[C]) deleteThread(ctx Context, t *thread) {
|
||||||
d.threadsMu.Lock()
|
d.threadsMu.Lock()
|
||||||
delete(d.threads, t.id)
|
delete(d.threads, t.id)
|
||||||
d.threadsMu.Unlock()
|
d.threadsMu.Unlock()
|
||||||
@@ -262,7 +261,7 @@ type evaluateRequest struct {
|
|||||||
errCh chan<- error
|
errCh chan<- error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Adapter[T]) EvaluateResult(ctx context.Context, name string, c gateway.Client, res *gateway.Result, inputs build.Inputs) error {
|
func (d *Adapter[C]) EvaluateResult(ctx context.Context, name string, c gateway.Client, res *gateway.Result, inputs build.Inputs) error {
|
||||||
eg, _ := errgroup.WithContext(ctx)
|
eg, _ := errgroup.WithContext(ctx)
|
||||||
if res.Ref != nil {
|
if res.Ref != nil {
|
||||||
eg.Go(func() error {
|
eg.Go(func() error {
|
||||||
@@ -279,7 +278,7 @@ func (d *Adapter[T]) EvaluateResult(ctx context.Context, name string, c gateway.
|
|||||||
return eg.Wait()
|
return eg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Adapter[T]) evaluateRef(ctx context.Context, name string, c gateway.Client, ref gateway.Reference, meta map[string][]byte, inputs build.Inputs) error {
|
func (d *Adapter[C]) evaluateRef(ctx context.Context, name string, c gateway.Client, ref gateway.Reference, meta map[string][]byte, inputs build.Inputs) error {
|
||||||
errCh := make(chan error, 1)
|
errCh := make(chan error, 1)
|
||||||
|
|
||||||
// Send a solve request to the launch routine
|
// Send a solve request to the launch routine
|
||||||
@@ -307,7 +306,7 @@ func (d *Adapter[T]) evaluateRef(ctx context.Context, name string, c gateway.Cli
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Adapter[T]) Threads(c Context, req *dap.ThreadsRequest, resp *dap.ThreadsResponse) error {
|
func (d *Adapter[C]) Threads(c Context, req *dap.ThreadsRequest, resp *dap.ThreadsResponse) error {
|
||||||
d.threadsMu.RLock()
|
d.threadsMu.RLock()
|
||||||
defer d.threadsMu.RUnlock()
|
defer d.threadsMu.RUnlock()
|
||||||
|
|
||||||
@@ -321,7 +320,7 @@ func (d *Adapter[T]) Threads(c Context, req *dap.ThreadsRequest, resp *dap.Threa
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Adapter[T]) StackTrace(c Context, req *dap.StackTraceRequest, resp *dap.StackTraceResponse) error {
|
func (d *Adapter[C]) StackTrace(c Context, req *dap.StackTraceRequest, resp *dap.StackTraceResponse) error {
|
||||||
t := d.getThread(req.Arguments.ThreadId)
|
t := d.getThread(req.Arguments.ThreadId)
|
||||||
if t == nil {
|
if t == nil {
|
||||||
return errors.Errorf("no such thread: %d", req.Arguments.ThreadId)
|
return errors.Errorf("no such thread: %d", req.Arguments.ThreadId)
|
||||||
@@ -331,7 +330,7 @@ func (d *Adapter[T]) StackTrace(c Context, req *dap.StackTraceRequest, resp *dap
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Adapter[T]) Source(c Context, req *dap.SourceRequest, resp *dap.SourceResponse) error {
|
func (d *Adapter[C]) Source(c Context, req *dap.SourceRequest, resp *dap.SourceResponse) error {
|
||||||
fname := req.Arguments.Source.Path
|
fname := req.Arguments.Source.Path
|
||||||
|
|
||||||
dt, ok := d.sourceMap.Get(fname)
|
dt, ok := d.sourceMap.Get(fname)
|
||||||
@@ -343,7 +342,7 @@ func (d *Adapter[T]) Source(c Context, req *dap.SourceRequest, resp *dap.SourceR
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Adapter[T]) evaluate(ctx context.Context, name string, c gateway.Client, res *gateway.Result, opt build.Options) error {
|
func (d *Adapter[C]) evaluate(ctx context.Context, name string, c gateway.Client, res *gateway.Result, opt build.Options) error {
|
||||||
errCh := make(chan error, 1)
|
errCh := make(chan error, 1)
|
||||||
|
|
||||||
started := d.srv.Go(func(ctx Context) {
|
started := d.srv.Go(func(ctx Context) {
|
||||||
@@ -362,13 +361,13 @@ func (d *Adapter[T]) evaluate(ctx context.Context, name string, c gateway.Client
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Adapter[T]) Handler() build.Handler {
|
func (d *Adapter[C]) Handler() build.Handler {
|
||||||
return build.Handler{
|
return build.Handler{
|
||||||
Evaluate: d.evaluate,
|
Evaluate: d.evaluate,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Adapter[T]) dapHandler() Handler {
|
func (d *Adapter[C]) dapHandler() Handler {
|
||||||
return Handler{
|
return Handler{
|
||||||
Initialize: d.Initialize,
|
Initialize: d.Initialize,
|
||||||
Launch: d.Launch,
|
Launch: d.Launch,
|
||||||
@@ -383,15 +382,15 @@ func (d *Adapter[T]) dapHandler() Handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Adapter[T]) Out() io.Writer {
|
func (d *Adapter[C]) Out() io.Writer {
|
||||||
return &adapterWriter[T]{d}
|
return &adapterWriter[C]{d}
|
||||||
}
|
}
|
||||||
|
|
||||||
type adapterWriter[T any] struct {
|
type adapterWriter[C LaunchConfig] struct {
|
||||||
*Adapter[T]
|
*Adapter[C]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *adapterWriter[T]) Write(p []byte) (n int, err error) {
|
func (d *adapterWriter[C]) Write(p []byte) (n int, err error) {
|
||||||
started := d.srv.Go(func(c Context) {
|
started := d.srv.Go(func(c Context) {
|
||||||
<-d.initialized
|
<-d.initialized
|
||||||
|
|
||||||
|
|||||||
+4
-3
@@ -7,13 +7,14 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/docker/buildx/dap/common"
|
||||||
"github.com/google/go-dap"
|
"github.com/google/go-dap"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLaunch(t *testing.T) {
|
func TestLaunch(t *testing.T) {
|
||||||
adapter, conn, client := NewTestAdapter[any](t)
|
adapter, conn, client := NewTestAdapter[common.Config](t)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeoutCause(context.Background(), 10*time.Second, context.DeadlineExceeded)
|
ctx, cancel := context.WithTimeoutCause(context.Background(), 10*time.Second, context.DeadlineExceeded)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@@ -68,7 +69,7 @@ func TestLaunch(t *testing.T) {
|
|||||||
eg.Wait()
|
eg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTestAdapter[T any](t *testing.T) (*Adapter[T], Conn, *Client) {
|
func NewTestAdapter[C LaunchConfig](t *testing.T) (*Adapter[C], Conn, *Client) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
rd1, wr1 := io.Pipe()
|
rd1, wr1 := io.Pipe()
|
||||||
@@ -84,7 +85,7 @@ func NewTestAdapter[T any](t *testing.T) (*Adapter[T], Conn, *Client) {
|
|||||||
clientConn.Close()
|
clientConn.Close()
|
||||||
})
|
})
|
||||||
|
|
||||||
adapter := New[T](nil)
|
adapter := New[C]()
|
||||||
t.Cleanup(func() { adapter.Stop() })
|
t.Cleanup(func() { adapter.Stop() })
|
||||||
|
|
||||||
client := NewClient(clientConn)
|
client := NewClient(clientConn)
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
StopOnEntry bool `json:"stopOnEntry,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Config) GetConfig() Config {
|
||||||
|
return c
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package dap
|
||||||
|
|
||||||
|
import "github.com/docker/buildx/dap/common"
|
||||||
|
|
||||||
|
type LaunchConfig interface {
|
||||||
|
GetConfig() common.Config
|
||||||
|
}
|
||||||
+7
-2
@@ -7,6 +7,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/docker/buildx/build"
|
"github.com/docker/buildx/build"
|
||||||
|
"github.com/docker/buildx/dap/common"
|
||||||
"github.com/google/go-dap"
|
"github.com/google/go-dap"
|
||||||
"github.com/moby/buildkit/client/llb"
|
"github.com/moby/buildkit/client/llb"
|
||||||
gateway "github.com/moby/buildkit/frontend/gateway/client"
|
gateway "github.com/moby/buildkit/frontend/gateway/client"
|
||||||
@@ -67,13 +68,17 @@ const (
|
|||||||
stepNext
|
stepNext
|
||||||
)
|
)
|
||||||
|
|
||||||
func (t *thread) Evaluate(ctx Context, c gateway.Client, ref gateway.Reference, meta map[string][]byte, inputs build.Inputs) error {
|
func (t *thread) Evaluate(ctx Context, c gateway.Client, ref gateway.Reference, meta map[string][]byte, inputs build.Inputs, cfg common.Config) error {
|
||||||
if err := t.init(ctx, c, ref, meta, inputs); err != nil {
|
if err := t.init(ctx, c, ref, meta, inputs); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer t.reset()
|
defer t.reset()
|
||||||
|
|
||||||
step := stepNext
|
step := stepContinue
|
||||||
|
if cfg.StopOnEntry {
|
||||||
|
step = stepNext
|
||||||
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
pos, err := t.seekNext(ctx, step)
|
pos, err := t.seekNext(ctx, step)
|
||||||
|
|
||||||
|
|||||||
@@ -12,11 +12,10 @@ Start debug adapter protocol compatible debugger (EXPERIMENTAL)
|
|||||||
|
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
| Name | Type | Default | Description |
|
| Name | Type | Default | Description |
|
||||||
|:----------------|:---------|:--------|:-----------------------------------------------------------|
|
|:----------------|:---------|:--------|:-----------------------------------------|
|
||||||
| `--builder` | `string` | | Override the configured builder instance |
|
| `--builder` | `string` | | Override the configured builder instance |
|
||||||
| `-D`, `--debug` | `bool` | | Enable debug logging |
|
| `-D`, `--debug` | `bool` | | Enable debug logging |
|
||||||
| `--on` | `string` | `error` | When to pause the adapter ([always, error]) (EXPERIMENTAL) |
|
|
||||||
|
|
||||||
|
|
||||||
<!---MARKER_GEN_END-->
|
<!---MARKER_GEN_END-->
|
||||||
|
|||||||
Reference in New Issue
Block a user