func (dir Dir) Exists(path string) (bool, error) {
	fpath, err := dir.fromSlash("check", path)
	if err != nil {
		return false, err
	}
	switch _, err := os.Stat(fpath); {
	case err == nil:
		return true, nil
	case os.IsNotExist(err):
		return false, nil
	default:
		return false, err
	}
}
Exists tests the existence of the given relative slash-separated path.
The path is interpreted relative to dir.
package filesystem
import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)
type Operation struct {
	code opCode
	name string
	arg  string
}
func Write(name, content string) Operation {
	return Operation{code: opWrite, name: name, arg: content}
}
func Mkdir(name string) Operation {
	return Operation{code: opMkdir, name: name}
}
func Remove(name string) Operation {
	return Operation{code: opRemove, name: name}
}
func Rename(old, new string) Operation {
	return Operation{code: opRename, name: new, arg: old}
}
func Symlink(old, new string) Operation {
	return Operation{code: opSymlink, name: new, arg: old}
}
func (o Operation) String() string {
	switch o.code {
	case nop:
		return nop.String()
	case opWrite:
		return fmt.Sprintf("write %q to %q", o.arg, o.name)
	case opRename:
		return fmt.Sprintf("rename %q to %q", o.arg, o.name)
	case opSymlink:
		return fmt.Sprintf("symlink %q as %q", o.arg, o.name)
	default:
		return fmt.Sprintf("%s %q", o.code, o.name)
	}
}
type opCode int
const (
	nop opCode = iota
	opWrite
	opMkdir
	opRemove
	opRename
	opSymlink
)
func (code opCode) String() string {
	switch code {
	case nop:
		return "no-op"
	case opWrite:
		return "write"
	case opMkdir:
		return "mkdir"
	case opRemove:
		return "remove"
	case opRename:
		return "rename"
	case opSymlink:
		return "symlink"
	default:
		return fmt.Sprintf("opCode(%d)", int(code))
	}
}
type Dir string
func (dir Dir) Apply(ops ...Operation) error {
	for _, o := range ops {
		p, err := dir.fromSlash(o.code.String(), o.name)
		if err != nil {
			return err
		}
		switch o.code {
		case nop:
		case opWrite:
			if err := os.MkdirAll(filepath.Dir(p), 0777); err != nil {
				return err
			}
			if err := ioutil.WriteFile(p, []byte(o.arg), 0666); err != nil {
				return err
			}
		case opMkdir:
			if err := os.MkdirAll(filepath.Dir(p), 0777); err != nil {
				return err
			}
			if err := os.Mkdir(p, 0777); err != nil {
				return err
			}
		case opRemove:
			if _, err := os.Lstat(p); os.IsNotExist(err) {
				return err
			}
			if err := os.RemoveAll(p); err != nil {
				return err
			}
		case opRename:
			oldPath, err := dir.fromSlash(o.code.String(), o.arg)
			if err != nil {
				return err
			}
			if err := os.Rename(oldPath, p); err != nil {
				return err
			}
		case opSymlink:
			if err := os.Symlink(filepath.FromSlash(o.arg), p); err != nil {
				return err
			}
		default:
			panic("invalid operation code")
		}
	}
	return nil
}
func (dir Dir) ReadFile(path string) (string, error) {
	fpath, err := dir.fromSlash("read", path)
	if err != nil {
		return "", err
	}
	f, err := os.Open(fpath)
	if err != nil {
		return "", err
	}
	sb := new(strings.Builder)
	_, cpErr := io.Copy(sb, f)
	closeErr := f.Close()
	if cpErr != nil {
		return "", cpErr
	}
	return sb.String(), closeErr
}