func (c *noopCache) Get(path string) *Metadata {
	return Compute(path)
}
Get computes the metadata from the file contents.
If an error is returned, it will be in Metadata.Err of type *FileError.
package filemetadata
import (
	"os"
	"time"
	"github.com/bazelbuild/remote-apis-sdks/go/pkg/digest"
)
type SymlinkMetadata struct {
	Target     string
	IsDangling bool
}
type Metadata struct {
	Digest       digest.Digest
	IsExecutable bool
	IsDirectory  bool
	MTime        time.Time
	Err          error
	Symlink      *SymlinkMetadata
}
type FileError struct {
	IsNotFound bool
	Err        error
}
func (e *FileError) Error() string {
	return e.Err.Error()
}
func isSymlink(filename string) (bool, error) {
	file, err := os.Lstat(filename)
	if err != nil {
		return false, err
	}
	return file.Mode()&os.ModeSymlink != 0, nil
}
func Compute(filename string) *Metadata {
	md := &Metadata{Digest: digest.Empty}
	file, err := os.Stat(filename)
	if isSym, _ := isSymlink(filename); isSym {
		md.Symlink = &SymlinkMetadata{}
		dest, rlErr := os.Readlink(filename)
		if rlErr != nil {
			md.Err = &FileError{Err: rlErr}
			return md
		}
		md.Symlink.Target = dest
		if err != nil {
			md.Err = &FileError{Err: err}
			md.Symlink.IsDangling = true
			return md
		}
	}
	if err != nil {
		fe := &FileError{Err: err}
		if os.IsNotExist(err) {
			fe.IsNotFound = true
		}
		md.Err = fe
		return md
	}
	mode := file.Mode()
	md.MTime = file.ModTime()
	md.IsExecutable = (mode & 0100) != 0
	if mode.IsDir() {
		md.IsDirectory = true
		return md
	}
	md.Digest, md.Err = digest.NewFromFile(filename)
	return md
}
type Cache interface {
	Get(path string) *Metadata
	Delete(filename string) error
	Update(path string, cacheEntry *Metadata) error
	GetCacheHits() uint64
	GetCacheMisses() uint64
}
type noopCache struct{}