github.com/mgoltzsche/ctnr@v0.7.1-alpha/pkg/fs/source/sourcefile.go (about) 1 package source 2 3 import ( 4 "github.com/mgoltzsche/ctnr/pkg/fs" 5 "github.com/opencontainers/go-digest" 6 "github.com/pkg/errors" 7 ) 8 9 var _ fs.Source = &sourceFile{} 10 11 type sourceFile struct { 12 fs.Readable 13 attrs fs.NodeAttrs 14 } 15 16 func NewSourceFile(reader fs.Readable, attrs fs.FileAttrs) *sourceFile { 17 return NewSourceFileHashed(reader, attrs, "") 18 } 19 20 func NewSourceFileHashed(reader fs.Readable, attrs fs.FileAttrs, hash string) *sourceFile { 21 return &sourceFile{reader, fs.NodeAttrs{fs.NodeInfo{fs.TypeFile, attrs}, fs.DerivedAttrs{Hash: hash}}} 22 } 23 24 func (s *sourceFile) Attrs() fs.NodeInfo { 25 return s.attrs.NodeInfo 26 } 27 28 func (s *sourceFile) HashIfAvailable() string { 29 return s.attrs.Hash 30 } 31 32 func (s *sourceFile) Hash() (h string, err error) { 33 if s.attrs.Hash == "" { 34 f, err := s.Reader() 35 if err != nil { 36 return "", errors.Wrap(err, "hash") 37 } 38 defer func() { 39 if e := f.Close(); e != nil && err == nil { 40 err = e 41 } 42 }() 43 d, err := digest.FromReader(f) 44 if err != nil { 45 return "", errors.Errorf("hash %s: %s", s.Readable, err) 46 } 47 s.attrs.Hash = d.String() 48 } 49 return s.attrs.Hash, nil 50 } 51 52 func (s *sourceFile) DeriveAttrs() (fs.DerivedAttrs, error) { 53 _, err := s.Hash() 54 return s.attrs.DerivedAttrs, err 55 } 56 57 func (s *sourceFile) Write(path, name string, w fs.Writer, written map[fs.Source]string) (err error) { 58 if linkDest, ok := written[s]; ok { 59 err = w.Link(path, linkDest) 60 } else { 61 written[s] = path 62 _, err = w.File(path, s) 63 } 64 return err 65 } 66 67 func (s *sourceFile) Equal(o fs.Source) (bool, error) { 68 if !s.attrs.NodeInfo.Equal(o.Attrs()) { 69 return false, nil 70 } 71 oa, err := o.DeriveAttrs() 72 if err != nil { 73 return false, errors.Wrap(err, "equal") 74 } 75 a, err := s.DeriveAttrs() 76 return a.Equal(&oa), errors.Wrap(err, "equal") 77 }