@@ -49,7 +49,6 @@ type thread struct {
4949 // Attributes set when a thread is paused.
5050 cancel context.CancelCauseFunc // invoked when the thread is resumed
5151 rCtx * build.ResultHandle
52- curPos digest.Digest
5352 stackTrace []int32
5453}
5554
@@ -74,15 +73,16 @@ func (t *thread) Evaluate(ctx Context, c gateway.Client, headRef gateway.Referen
7473 }
7574
7675 var (
77- ref gateway.Reference
78- next = t .entrypoint
79- err error
76+ ref gateway.Reference
77+ mounts map [string ]gateway.Reference
78+ next = t .entrypoint
79+ err error
8080 )
8181 for next != nil {
8282 event := t .needsDebug (next , action , err )
8383 if event .Reason != "" {
8484 select {
85- case action = <- t .pause (ctx , ref , err , next , event ):
85+ case action = <- t .pause (ctx , ref , err , mounts , next , event ):
8686 // do nothing here
8787 case <- ctx .Done ():
8888 return context .Cause (ctx )
@@ -96,7 +96,7 @@ func (t *thread) Evaluate(ctx Context, c gateway.Client, headRef gateway.Referen
9696 if action == stepContinue {
9797 t .setBreakpoints (ctx )
9898 }
99- ref , next , err = t .seekNext (ctx , next , action )
99+ ref , next , mounts , err = t .seekNext (ctx , next , action )
100100 }
101101 return nil
102102}
@@ -285,26 +285,17 @@ func (t *thread) needsDebug(cur *step, step stepType, err error) (e dap.StoppedE
285285 return
286286}
287287
288- func (t * thread ) pause (c Context , ref gateway.Reference , err error , pos * step , event dap.StoppedEventBody ) <- chan stepType {
288+ func (t * thread ) pause (c Context , ref gateway.Reference , err error , mounts map [ string ]gateway. Reference , pos * step , event dap.StoppedEventBody ) <- chan stepType {
289289 t .mu .Lock ()
290290 defer t .mu .Unlock ()
291291
292292 if t .paused != nil {
293293 return t .paused
294294 }
295-
296295 t .paused = make (chan stepType , 1 )
297- if err != nil {
298- var solveErr * errdefs.SolveError
299- if errors .As (err , & solveErr ) {
300- if dt , err := solveErr .Op .MarshalVT (); err == nil {
301- t .curPos = digest .FromBytes (dt )
302- }
303- }
304- }
305296
306297 ctx , cancel := context .WithCancelCause (c )
307- t .collectStackTrace (ctx , pos , ref )
298+ t .collectStackTrace (ctx , pos , mounts )
308299 t .cancel = cancel
309300
310301 if ref != nil || err != nil {
@@ -435,7 +426,7 @@ func (t *thread) setBreakpoints(ctx Context) {
435426 t .bps = t .breakpointMap .Intersect (ctx , t .def .Source , t .sourcePath )
436427}
437428
438- func (t * thread ) seekNext (ctx Context , from * step , action stepType ) (gateway.Reference , * step , error ) {
429+ func (t * thread ) seekNext (ctx Context , from * step , action stepType ) (gateway.Reference , * step , map [ string ]gateway. Reference , error ) {
439430 // If we're at the end, return no digest to signal that
440431 // we should conclude debugging.
441432 var target * step
@@ -452,12 +443,12 @@ func (t *thread) seekNext(ctx Context, from *step, action stepType) (gateway.Ref
452443 return t .seek (ctx , target )
453444}
454445
455- func (t * thread ) seek (ctx Context , target * step ) (ref gateway.Reference , result * step , err error ) {
446+ func (t * thread ) seek (ctx Context , target * step ) (ref gateway.Reference , result * step , mounts map [ string ]gateway. Reference , err error ) {
456447 if target != nil {
457448 if target .dgst != "" {
458- ref , err = t .solve (ctx , target .dgst )
449+ ref , err = t .solve (ctx , target .dgst , 0 )
459450 if err != nil {
460- return ref , nil , err
451+ return ref , nil , nil , err
461452 }
462453 }
463454
@@ -468,31 +459,15 @@ func (t *thread) seek(ctx Context, target *step) (ref gateway.Reference, result
468459
469460 if ref != nil {
470461 if err = ref .Evaluate (ctx ); err != nil {
471- // If this is not a solve error, do not return the
472- // reference and target step.
473- var solveErr * errdefs.SolveError
474- if errors .As (err , & solveErr ) {
475- if dt , err := solveErr .Op .MarshalVT (); err == nil {
476- // Find the error digest.
477- errDgst := digest .FromBytes (dt )
478-
479- // Iterate from the first step to find the one
480- // we failed on.
481- result = t .entrypoint
482- for result != nil {
483- next := result .in
484- if next != nil && next .dgst == errDgst {
485- break
486- }
487- result = next
488- }
489- }
490- } else {
491- return nil , nil , err
462+ result , mounts = t .rewind (ctx , err )
463+ if result == nil {
464+ return nil , nil , nil , err
492465 }
466+ } else {
467+ mounts = map [string ]gateway.Reference {"/" : ref }
493468 }
494469 }
495- return ref , result , err
470+ return ref , result , mounts , err
496471}
497472
498473func (t * thread ) continueDigest (from * step ) * step {
@@ -523,13 +498,15 @@ func (t *thread) continueDigest(from *step) *step {
523498 return next (from )
524499}
525500
526- func (t * thread ) solve (ctx context.Context , target digest.Digest ) (gateway.Reference , error ) {
501+ func (t * thread ) solve (ctx context.Context , target digest.Digest , index int64 ) (gateway.Reference , error ) {
527502 if target == t .head {
528503 return t .ref , nil
529504 }
530505
531506 head := & pb.Op {
532- Inputs : []* pb.Input {{Digest : string (target )}},
507+ Inputs : []* pb.Input {
508+ {Digest : string (target ), Index : index },
509+ },
533510 }
534511 dt , err := head .MarshalVT ()
535512 if err != nil {
@@ -567,12 +544,12 @@ func (t *thread) releaseState() {
567544 t .variables .Reset ()
568545}
569546
570- func (t * thread ) collectStackTrace (ctx context.Context , pos * step , ref gateway.Reference ) {
547+ func (t * thread ) collectStackTrace (ctx context.Context , pos * step , mounts map [ string ] gateway.Reference ) {
571548 for pos != nil {
572549 frame := pos .frame
573- frame .ExportVars (ctx , ref , t .variables )
550+ frame .ExportVars (ctx , mounts , t .variables )
574551 t .stackTrace = append (t .stackTrace , int32 (frame .Id ))
575- pos , ref = pos .out , nil
552+ pos , mounts = pos .out , nil
576553 }
577554}
578555
@@ -587,3 +564,48 @@ func (t *thread) hasFrame(id int) bool {
587564 _ , ok := t .frames [int32 (id )]
588565 return ok
589566}
567+
568+ func (t * thread ) rewind (ctx context.Context , err error ) (result * step , mounts map [string ]gateway.Reference ) {
569+ var solveErr * errdefs.SolveError
570+ if ! errors .As (err , & solveErr ) {
571+ // If this is not a solve error, do not return the
572+ // reference and target step.
573+ return nil , nil
574+ }
575+
576+ dt , err := solveErr .Op .MarshalVT ()
577+ if err != nil {
578+ return nil , nil
579+ }
580+
581+ // Find the error digest.
582+ errDgst := digest .FromBytes (dt )
583+
584+ // Iterate from the first step to find the one
585+ // we failed on.
586+ result = t .entrypoint
587+ for result != nil {
588+ next := result .in
589+ if next != nil && next .dgst == errDgst {
590+ break
591+ }
592+ result = next
593+ }
594+
595+ if exec , ok := solveErr .Op .GetOp ().(* pb.Op_Exec ); ok {
596+ mounts = make (map [string ]gateway.Reference , len (exec .Exec .Mounts ))
597+ for _ , m := range exec .Exec .Mounts {
598+ if m .Input < 0 {
599+ continue
600+ }
601+
602+ // TODO: Use the correct input index for this.
603+ input := solveErr .Op .Inputs [m .Input ]
604+ target , index := digest .Digest (input .Digest ), input .Index
605+ if ref , err := t .solve (ctx , target , index ); err == nil {
606+ mounts [m .Dest ] = ref
607+ }
608+ }
609+ }
610+ return result , mounts
611+ }
0 commit comments