File: diff.go

package info (click to toggle)
singularity-container 4.1.5%2Bds4-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 43,876 kB
  • sloc: asm: 14,840; sh: 3,190; ansic: 1,751; awk: 414; makefile: 413; python: 99
file content (123 lines) | stat: -rw-r--r-- 3,243 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package ops

import (
	"context"
	"encoding/json"

	"github.com/moby/buildkit/worker"
	"github.com/pkg/errors"

	"github.com/moby/buildkit/cache"
	"github.com/moby/buildkit/session"
	"github.com/moby/buildkit/solver"
	"github.com/moby/buildkit/solver/llbsolver/ops/opsutils"
	"github.com/moby/buildkit/solver/pb"
	digest "github.com/opencontainers/go-digest"
)

const diffCacheType = "buildkit.diff.v0"

type diffOp struct {
	op     *pb.DiffOp
	worker worker.Worker
	vtx    solver.Vertex
}

func NewDiffOp(v solver.Vertex, op *pb.Op_Diff, w worker.Worker) (solver.Op, error) {
	if err := opsutils.Validate(&pb.Op{Op: op}); err != nil {
		return nil, err
	}
	return &diffOp{
		op:     op.Diff,
		worker: w,
		vtx:    v,
	}, nil
}

func (d *diffOp) CacheMap(ctx context.Context, group session.Group, index int) (*solver.CacheMap, bool, error) {
	dt, err := json.Marshal(struct {
		Type string
		Diff *pb.DiffOp
	}{
		Type: diffCacheType,
		Diff: d.op,
	})
	if err != nil {
		return nil, false, err
	}

	var depCount int
	if d.op.Lower.Input != pb.Empty {
		depCount++
	}
	if d.op.Upper.Input != pb.Empty {
		depCount++
	}

	cm := &solver.CacheMap{
		Digest: digest.FromBytes(dt),
		Deps: make([]struct {
			Selector          digest.Digest
			ComputeDigestFunc solver.ResultBasedCacheFunc
			PreprocessFunc    solver.PreprocessFunc
		}, depCount),
	}

	return cm, true, nil
}

func (d *diffOp) Exec(ctx context.Context, g session.Group, inputs []solver.Result) ([]solver.Result, error) {
	var curInput int

	var lowerRef cache.ImmutableRef
	if d.op.Lower.Input != pb.Empty {
		if lowerInp := inputs[curInput]; lowerInp != nil {
			wref, ok := lowerInp.Sys().(*worker.WorkerRef)
			if !ok {
				return nil, errors.Errorf("invalid lower reference for diff op %T", lowerInp.Sys())
			}
			lowerRef = wref.ImmutableRef
		} else {
			return nil, errors.New("invalid nil lower input for diff op")
		}
		curInput++
	}

	var upperRef cache.ImmutableRef
	if d.op.Upper.Input != pb.Empty {
		if upperInp := inputs[curInput]; upperInp != nil {
			wref, ok := upperInp.Sys().(*worker.WorkerRef)
			if !ok {
				return nil, errors.Errorf("invalid upper reference for diff op %T", upperInp.Sys())
			}
			upperRef = wref.ImmutableRef
		} else {
			return nil, errors.New("invalid nil upper input for diff op")
		}
	}

	if lowerRef == nil {
		if upperRef == nil {
			// The diff of nothing and nothing is nothing. Just return an empty ref.
			return []solver.Result{worker.NewWorkerRefResult(nil, d.worker)}, nil
		}
		// The diff of nothing and upper is upper. Just return a clone of upper
		return []solver.Result{worker.NewWorkerRefResult(upperRef.Clone(), d.worker)}, nil
	}
	if upperRef != nil && lowerRef.ID() == upperRef.ID() {
		// The diff of a ref and itself is nothing, return an empty ref.
		return []solver.Result{worker.NewWorkerRefResult(nil, d.worker)}, nil
	}

	diffRef, err := d.worker.CacheManager().Diff(ctx, lowerRef, upperRef, solver.ProgressControllerFromContext(ctx),
		cache.WithDescription(d.vtx.Name()))
	if err != nil {
		return nil, err
	}

	return []solver.Result{worker.NewWorkerRefResult(diffRef, d.worker)}, nil
}

func (d *diffOp) Acquire(ctx context.Context) (release solver.ReleaseFunc, err error) {
	return func() {}, nil
}