+++ /dev/null
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package mapfs file provides an implementation of the FileSystem
-// interface based on the contents of a map[string]string.
-package mapfs // import "golang.org/x/tools/godoc/vfs/mapfs"
-
-import (
- "fmt"
- "io"
- "os"
- pathpkg "path"
- "sort"
- "strings"
- "time"
-
- "golang.org/x/tools/godoc/vfs"
-)
-
-// New returns a new FileSystem from the provided map.
-// Map keys must be forward slash-separated paths with
-// no leading slash, such as "file1.txt" or "dir/file2.txt".
-// New panics if any of the paths contain a leading slash.
-func New(m map[string]string) vfs.FileSystem {
- // Verify all provided paths are relative before proceeding.
- var pathsWithLeadingSlash []string
- for p := range m {
- if strings.HasPrefix(p, "/") {
- pathsWithLeadingSlash = append(pathsWithLeadingSlash, p)
- }
- }
- if len(pathsWithLeadingSlash) > 0 {
- panic(fmt.Errorf("mapfs.New: invalid paths with a leading slash: %q", pathsWithLeadingSlash))
- }
-
- return mapFS(m)
-}
-
-// mapFS is the map based implementation of FileSystem
-type mapFS map[string]string
-
-func (fs mapFS) String() string { return "mapfs" }
-
-func (fs mapFS) RootType(p string) vfs.RootType {
- return ""
-}
-
-func (fs mapFS) Close() error { return nil }
-
-func filename(p string) string {
- return strings.TrimPrefix(p, "/")
-}
-
-func (fs mapFS) Open(p string) (vfs.ReadSeekCloser, error) {
- b, ok := fs[filename(p)]
- if !ok {
- return nil, os.ErrNotExist
- }
- return nopCloser{strings.NewReader(b)}, nil
-}
-
-func fileInfo(name, contents string) os.FileInfo {
- return mapFI{name: pathpkg.Base(name), size: len(contents)}
-}
-
-func dirInfo(name string) os.FileInfo {
- return mapFI{name: pathpkg.Base(name), dir: true}
-}
-
-func (fs mapFS) Lstat(p string) (os.FileInfo, error) {
- b, ok := fs[filename(p)]
- if ok {
- return fileInfo(p, b), nil
- }
- ents, _ := fs.ReadDir(p)
- if len(ents) > 0 {
- return dirInfo(p), nil
- }
- return nil, os.ErrNotExist
-}
-
-func (fs mapFS) Stat(p string) (os.FileInfo, error) {
- return fs.Lstat(p)
-}
-
-// slashdir returns path.Dir(p), but special-cases paths not beginning
-// with a slash to be in the root.
-func slashdir(p string) string {
- d := pathpkg.Dir(p)
- if d == "." {
- return "/"
- }
- if strings.HasPrefix(p, "/") {
- return d
- }
- return "/" + d
-}
-
-func (fs mapFS) ReadDir(p string) ([]os.FileInfo, error) {
- p = pathpkg.Clean(p)
- var ents []string
- fim := make(map[string]os.FileInfo) // base -> fi
- for fn, b := range fs {
- dir := slashdir(fn)
- isFile := true
- var lastBase string
- for {
- if dir == p {
- base := lastBase
- if isFile {
- base = pathpkg.Base(fn)
- }
- if fim[base] == nil {
- var fi os.FileInfo
- if isFile {
- fi = fileInfo(fn, b)
- } else {
- fi = dirInfo(base)
- }
- ents = append(ents, base)
- fim[base] = fi
- }
- }
- if dir == "/" {
- break
- } else {
- isFile = false
- lastBase = pathpkg.Base(dir)
- dir = pathpkg.Dir(dir)
- }
- }
- }
- if len(ents) == 0 {
- return nil, os.ErrNotExist
- }
-
- sort.Strings(ents)
- var list []os.FileInfo
- for _, dir := range ents {
- list = append(list, fim[dir])
- }
- return list, nil
-}
-
-// mapFI is the map-based implementation of FileInfo.
-type mapFI struct {
- name string
- size int
- dir bool
-}
-
-func (fi mapFI) IsDir() bool { return fi.dir }
-func (fi mapFI) ModTime() time.Time { return time.Time{} }
-func (fi mapFI) Mode() os.FileMode {
- if fi.IsDir() {
- return 0755 | os.ModeDir
- }
- return 0444
-}
-func (fi mapFI) Name() string { return pathpkg.Base(fi.name) }
-func (fi mapFI) Size() int64 { return int64(fi.size) }
-func (fi mapFI) Sys() interface{} { return nil }
-
-type nopCloser struct {
- io.ReadSeeker
-}
-
-func (nc nopCloser) Close() error { return nil }