moth/pkg/transpile/basepath.go

70 lines
1.6 KiB
Go
Raw Normal View History

2020-09-08 17:49:02 -06:00
package transpile
2020-09-01 20:12:57 -06:00
import (
"os"
"path/filepath"
"runtime"
"strings"
"github.com/spf13/afero"
)
2020-09-04 13:00:23 -06:00
// RecursiveBasePathFs is an overloaded afero.BasePathFs that has a recursive RealPath().
type RecursiveBasePathFs struct {
2020-09-01 20:12:57 -06:00
afero.Fs
source afero.Fs
path string
}
2020-09-04 13:00:23 -06:00
// NewRecursiveBasePathFs returns a new RecursiveBasePathFs.
func NewRecursiveBasePathFs(source afero.Fs, path string) *RecursiveBasePathFs {
2020-09-14 13:40:55 -06:00
ret := &RecursiveBasePathFs{
2020-09-01 20:12:57 -06:00
source: source,
path: path,
}
2020-09-14 13:40:55 -06:00
if path == "" {
ret.Fs = source
} else {
ret.Fs = afero.NewBasePathFs(source, path)
}
return ret
2020-09-01 20:12:57 -06:00
}
2020-09-04 13:00:23 -06:00
// RealPath returns the real path to a file, "breaking out" of the RecursiveBasePathFs.
func (b *RecursiveBasePathFs) RealPath(name string) (path string, err error) {
2020-09-01 20:12:57 -06:00
if err := validateBasePathName(name); err != nil {
return name, err
}
bpath := filepath.Clean(b.path)
path = filepath.Clean(filepath.Join(bpath, name))
2020-09-04 13:00:23 -06:00
if parentRecursiveBasePathFs, ok := b.source.(*RecursiveBasePathFs); ok {
return parentRecursiveBasePathFs.RealPath(path)
} else if parentRecursiveBasePathFs, ok := b.source.(*afero.BasePathFs); ok {
return parentRecursiveBasePathFs.RealPath(path)
2020-09-01 20:12:57 -06:00
}
if !strings.HasPrefix(path, bpath) {
return name, os.ErrNotExist
}
return path, nil
}
func validateBasePathName(name string) error {
if runtime.GOOS != "windows" {
// Not much to do here;
// the virtual file paths all look absolute on *nix.
return nil
}
// On Windows a common mistake would be to provide an absolute OS path
// We could strip out the base part, but that would not be very portable.
if filepath.IsAbs(name) {
return os.ErrNotExist
}
return nil
}