github.com/abergmeier/buildkit_ex@v0.0.0-20220613202848-1145f3866588/pkg/digest/digest.go (about)

     1  package digest
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"strings"
     8  	"sync"
     9  
    10  	"crypto/sha512"
    11  
    12  	"github.com/abergmeier/buildkit_ex/internal"
    13  	internalio "github.com/abergmeier/buildkit_ex/internal/io"
    14  	"github.com/abergmeier/buildkit_ex/pkg/digest/options"
    15  	"github.com/moby/buildkit/frontend/dockerfile/instructions"
    16  )
    17  
    18  type sourceContentWithIndex struct {
    19  	i  int
    20  	sc instructions.SourceContent
    21  }
    22  
    23  func DigestOfFileAndAllInputs(filename string, opts ...options.Option) ([sha512.Size]byte, error) {
    24  
    25  	digest := [sha512.Size]byte{}
    26  
    27  	dt, err := os.ReadFile(filename)
    28  	if err != nil {
    29  		return digest, fmt.Errorf("Reading Containerfile failed: %w", err)
    30  	}
    31  
    32  	filesToHash := make(chan internalio.OpenedFile, 1024)
    33  	var herr error
    34  	digestReady := sync.WaitGroup{}
    35  	digestReady.Add(1)
    36  	go func() {
    37  		defer digestReady.Done()
    38  		var h []byte
    39  		h, herr = hashFiles(filesToHash)
    40  		if herr != nil {
    41  			return
    42  		}
    43  		copy(digest[:], h)
    44  	}()
    45  
    46  	filesToHash <- internalio.OpenedFile{
    47  		LateReader: func() (io.ReadCloser, error) {
    48  			return io.NopCloser(strings.NewReader(string(dt))), nil
    49  		},
    50  		Filename: filename,
    51  	}
    52  
    53  	rf := &internal.ReferencedFiles{}
    54  
    55  	for _, opt := range opts {
    56  		opt.InitReferencedFiles(rf)
    57  	}
    58  
    59  	err = rf.CollectSortedFileHashes(dt, filesToHash)
    60  	if err != nil {
    61  		return digest, err
    62  	}
    63  
    64  	close(filesToHash)
    65  
    66  	digestReady.Wait()
    67  	return digest, herr
    68  }
    69  
    70  func hashFiles(files <-chan internalio.OpenedFile) (sum []byte, firstErr error) {
    71  	hash := sha512.New()
    72  
    73  	for f := range files {
    74  		reader, err := f.LateReader()
    75  		if err != nil {
    76  			break
    77  		}
    78  		_, err = io.Copy(hash, reader)
    79  		reader.Close()
    80  		if err != nil {
    81  			break
    82  		}
    83  	}
    84  
    85  	sum = hash.Sum(nil)
    86  	return
    87  }