@@ -171,7 +171,12 @@ func (t *thread) createBranch(last *step) (first *step) {
171171
172172 op := t .ops [first .dgst ]
173173 if len (op .Inputs ) > 0 {
174- for i := len (op .Inputs ) - 1 ; i > 0 ; i -- {
174+ parent := t .determineParent (op )
175+ for i := len (op .Inputs ) - 1 ; i >= 0 ; i -- {
176+ if i == parent {
177+ // Skip the direct parent.
178+ continue
179+ }
175180 inp := op .Inputs [i ]
176181
177182 // Create a pseudo-step that acts as an exit point for this
@@ -196,8 +201,10 @@ func (t *thread) createBranch(last *step) (first *step) {
196201 }
197202
198203 // Set the digest of the parent input on the first step associated
199- // with this step.
200- prev .dgst = digest .Digest (op .Inputs [0 ].Digest )
204+ // with this step if it exists.
205+ if parent >= 0 {
206+ prev .dgst = digest .Digest (op .Inputs [parent ].Digest )
207+ }
201208 }
202209
203210 // New first is the step we just created.
@@ -225,6 +232,40 @@ func (t *thread) getStackFrame(dgst digest.Digest) *frame {
225232 return f
226233}
227234
235+ func (t * thread ) determineParent (op * pb.Op ) int {
236+ // Another section should have already checked this but
237+ // double check here just in case we forget somewhere else.
238+ // The rest of this method assumes there's at least one parent
239+ // at index zero.
240+ n := len (op .Inputs )
241+ if n == 0 {
242+ return - 1
243+ }
244+
245+ switch op := op .Op .(type ) {
246+ case * pb.Op_Exec :
247+ for _ , m := range op .Exec .Mounts {
248+ if m .Dest == "/" {
249+ return int (m .Input )
250+ }
251+ }
252+ return - 1
253+ case * pb.Op_File :
254+ // Use the first input where the index is from one of the inputs.
255+ for _ , action := range op .File .Actions {
256+ if input := int (action .Input ); input >= 0 && input < n {
257+ return input
258+ }
259+ }
260+
261+ // Default to having no parent.
262+ return - 1
263+ default :
264+ // Default to index zero.
265+ return 0
266+ }
267+ }
268+
228269func (t * thread ) reset () {
229270 t .c = nil
230271 t .ref = nil
0 commit comments