mirror of
				https://github.com/moby/moby.git
				synced 2022-11-09 12:21:53 -05:00 
			
		
		
		
	full diff: https://github.com/gotestyourself/gotest.tools/compare/v2.3.0...v3.0.1 Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
		
			
				
	
	
		
			139 lines
		
	
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			139 lines
		
	
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package fs
 | 
						|
 | 
						|
import (
 | 
						|
	"io"
 | 
						|
	"io/ioutil"
 | 
						|
	"os"
 | 
						|
	"path/filepath"
 | 
						|
 | 
						|
	"github.com/pkg/errors"
 | 
						|
	"gotest.tools/v3/assert"
 | 
						|
)
 | 
						|
 | 
						|
// Manifest stores the expected structure and properties of files and directories
 | 
						|
// in a filesystem.
 | 
						|
type Manifest struct {
 | 
						|
	root *directory
 | 
						|
}
 | 
						|
 | 
						|
type resource struct {
 | 
						|
	mode os.FileMode
 | 
						|
	uid  uint32
 | 
						|
	gid  uint32
 | 
						|
}
 | 
						|
 | 
						|
type file struct {
 | 
						|
	resource
 | 
						|
	content             io.ReadCloser
 | 
						|
	ignoreCariageReturn bool
 | 
						|
	compareContentFunc  func(b []byte) CompareResult
 | 
						|
}
 | 
						|
 | 
						|
func (f *file) Type() string {
 | 
						|
	return "file"
 | 
						|
}
 | 
						|
 | 
						|
type symlink struct {
 | 
						|
	resource
 | 
						|
	target string
 | 
						|
}
 | 
						|
 | 
						|
func (f *symlink) Type() string {
 | 
						|
	return "symlink"
 | 
						|
}
 | 
						|
 | 
						|
type directory struct {
 | 
						|
	resource
 | 
						|
	items         map[string]dirEntry
 | 
						|
	filepathGlobs map[string]*filePath
 | 
						|
}
 | 
						|
 | 
						|
func (f *directory) Type() string {
 | 
						|
	return "directory"
 | 
						|
}
 | 
						|
 | 
						|
type dirEntry interface {
 | 
						|
	Type() string
 | 
						|
}
 | 
						|
 | 
						|
// ManifestFromDir creates a Manifest by reading the directory at path. The
 | 
						|
// manifest stores the structure and properties of files in the directory.
 | 
						|
// ManifestFromDir can be used with Equal to compare two directories.
 | 
						|
func ManifestFromDir(t assert.TestingT, path string) Manifest {
 | 
						|
	if ht, ok := t.(helperT); ok {
 | 
						|
		ht.Helper()
 | 
						|
	}
 | 
						|
 | 
						|
	manifest, err := manifestFromDir(path)
 | 
						|
	assert.NilError(t, err)
 | 
						|
	return manifest
 | 
						|
}
 | 
						|
 | 
						|
func manifestFromDir(path string) (Manifest, error) {
 | 
						|
	info, err := os.Stat(path)
 | 
						|
	switch {
 | 
						|
	case err != nil:
 | 
						|
		return Manifest{}, err
 | 
						|
	case !info.IsDir():
 | 
						|
		return Manifest{}, errors.Errorf("path %s must be a directory", path)
 | 
						|
	}
 | 
						|
 | 
						|
	directory, err := newDirectory(path, info)
 | 
						|
	return Manifest{root: directory}, err
 | 
						|
}
 | 
						|
 | 
						|
func newDirectory(path string, info os.FileInfo) (*directory, error) {
 | 
						|
	items := make(map[string]dirEntry)
 | 
						|
	children, err := ioutil.ReadDir(path)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	for _, child := range children {
 | 
						|
		fullPath := filepath.Join(path, child.Name())
 | 
						|
		items[child.Name()], err = getTypedResource(fullPath, child)
 | 
						|
		if err != nil {
 | 
						|
			return nil, err
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return &directory{
 | 
						|
		resource:      newResourceFromInfo(info),
 | 
						|
		items:         items,
 | 
						|
		filepathGlobs: make(map[string]*filePath),
 | 
						|
	}, nil
 | 
						|
}
 | 
						|
 | 
						|
func getTypedResource(path string, info os.FileInfo) (dirEntry, error) {
 | 
						|
	switch {
 | 
						|
	case info.IsDir():
 | 
						|
		return newDirectory(path, info)
 | 
						|
	case info.Mode()&os.ModeSymlink != 0:
 | 
						|
		return newSymlink(path, info)
 | 
						|
	// TODO: devices, pipes?
 | 
						|
	default:
 | 
						|
		return newFile(path, info)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func newSymlink(path string, info os.FileInfo) (*symlink, error) {
 | 
						|
	target, err := os.Readlink(path)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	return &symlink{
 | 
						|
		resource: newResourceFromInfo(info),
 | 
						|
		target:   target,
 | 
						|
	}, err
 | 
						|
}
 | 
						|
 | 
						|
func newFile(path string, info os.FileInfo) (*file, error) {
 | 
						|
	// TODO: defer file opening to reduce number of open FDs?
 | 
						|
	readCloser, err := os.Open(path)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	return &file{
 | 
						|
		resource: newResourceFromInfo(info),
 | 
						|
		content:  readCloser,
 | 
						|
	}, err
 | 
						|
}
 |