memfs

package
v0.30.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 4, 2021 License: BSD-3-Clause Imports: 24 Imported by: 5

Documentation

Overview

Package memfs provide a library for mapping file system into memory and/or to embed it inside go source file.

Usage

The first step is to create new instance of memfs using `New()`. The following example embed all files inside directory named "include" or any files with extension ".css", ".html", and ".js"; but exclude any files inside directory named "exclude".

opts := &Options{
	Root: "./mydir",
	Includes: []string{
		`.*/include`,
		`.*\.(css|html|js)$`,
	},
	Excludes: []string{
		`.*/exclude`,
	},
}
mfs, err := memfs.New(opts)

By default only file with size less or equal to 5 MB will be included in memory. To increase the default size set the MaxFileSize (in bytes). For example, to set maximum file size to 10 MB,

opts.MaxFileSize = 1024 * 1024 * 10

Later, if we want to get the file from memory, call Get() which will return the node object with content can be accessed from field "V". Remember that if file size is larger that maximum, the content will need to be read manually,

node, err := mfs.Get("/")
if err != nil {
	// Handle file not exist
}
if node.mode.IsDir() {
	// Handle directory.
}
if node.V == nil {
	// Handle large file.
	node.V, err = ioutil.ReadFile(child.SysPath)
}
// Do something with content of file system.

Thats it!

Go embed

The memfs package also support embedding the files into Go generated source file. After we create memfs instance, we call GoGenerate() to dump all directory and files as Go source code.

First, define global variable as container for all files later in the same package as generated code,

package mypackage

var myFS *memfs.MemFS

Second, write the content of memfs instance as Go source code file,

mfs.GoGenerate("mypackage", "myFS", "mypackage/file.go", memfs.EncodingGzip)

The Go generated file will be defined with package named "mypackage" using global variable "myFS" as container stored in file "mypackage/file.go" with each content encoded (compressed) using gzip.

Index

Examples

Constants

View Source
const (
	DefaultGenPackageName = "main"
	DefaultGenVarName     = "memFS"
	DefaultGenGoFileName  = "memfs_generate.go"
)
View Source
const (
	EncodingGzip = "gzip"
)

List of valid content encoding for ContentEncode().

Variables

This section is empty.

Functions

This section is empty.

Types

type MemFS

type MemFS struct {
	http.FileSystem

	PathNodes *PathNode
	Root      *Node
	Opts      *Options
	// contains filtered or unexported fields
}

MemFS contains directory tree of file system in memory.

func Merge added in v0.27.0

func Merge(params ...*MemFS) (merged *MemFS)

Merge one or more instances of MemFS into single hierarchy.

If there are two instance of Node that have the same path, the last instance will be ignored.

func New

func New(opts *Options) (mfs *MemFS, err error)

New create and initialize new memory file system from directory Root using list of regular expresssion for Including or Excluding files.

Example
opts := &Options{
	Root: "./testdata",
	Includes: []string{
		`.*/include`,
		`.*\.(css|html|js)$`,
	},
	Excludes: []string{
		`.*/exclude`,
	},
}
mfs, err := New(opts)
if err != nil {
	log.Fatal(err)
}

node, err := mfs.Get("/index.html")
if err != nil {
	log.Fatal(err)
}

fmt.Printf("%s", node.V)
Output:

<html></html>

func (*MemFS) AddChild added in v0.6.0

func (mfs *MemFS) AddChild(parent *Node, fi os.FileInfo) (child *Node, err error)

AddChild add new child to parent node.

func (*MemFS) AddFile added in v0.10.1

func (mfs *MemFS) AddFile(internalPath, externalPath string) (*Node, error)

AddFile add the external file directly as internal file. If the internal file is already exist it will be replaced. Any directories in the internal path will be generated automatically if its not exist.

func (*MemFS) ContentEncode added in v0.10.1

func (mfs *MemFS) ContentEncode(encoding string) (err error)

ContentEncode encode each node's content into specific encoding, in other words this method can be used to compress the content of file in memory or before being served or written.

Only file with size greater than 0 will be encoded.

List of known encoding is "gzip".

func (*MemFS) Get

func (mfs *MemFS) Get(path string) (node *Node, err error)

Get the node representation of file in memory. If path is not exist it will return os.ErrNotExist.

func (*MemFS) GoGenerate

func (mfs *MemFS) GoGenerate(pkgName, varName, out, contentEncoding string) (err error)

GoGenerate write the tree nodes as Go generated source file.

If pkgName is not defined it will be default to "main".

varName is the global variable name with type *memfs.MemFS which will be initialize by generated Go source code on init(). The varName default to "memFS" if its empty.

If out is not defined it will be default to "memfs_generate.go" and saved in current directory from where its called.

If contentEncoding is not empty, it will encode the content of node and set the node ContentEncoding. List of available encoding is "gzip". For example, if contentEncoding is "gzip" it will compress the content of file using gzip and set Node.ContentEncoding to "gzip".

func (*MemFS) ListNames

func (mfs *MemFS) ListNames() (paths []string)

ListNames list all files in memory sorted by name.

func (*MemFS) MarshalJSON added in v0.29.1

func (mfs *MemFS) MarshalJSON() ([]byte, error)

MarshalJSON encode the MemFS object into JSON format.

The field that being encoded is the Root node.

func (*MemFS) MustGet added in v0.27.0

func (mfs *MemFS) MustGet(path string) (node *Node)

MustGet return the Node representation of file in memory by its path if its exist or nil the path is not exist.

func (*MemFS) Open added in v0.11.0

func (mfs *MemFS) Open(path string) (http.File, error)

Open the named file for reading. This is an alias to Get() method, to make it implement http.FileSystem.

func (*MemFS) RemoveChild added in v0.6.0

func (mfs *MemFS) RemoveChild(parent *Node, child *Node) (removed *Node)

RemoveChild remove a child on parent, including its map on PathNode. If child is not part if node's childrens it will return nil.

func (*MemFS) Search added in v0.10.1

func (mfs *MemFS) Search(words []string, snippetLen int) (results []SearchResult)

Search one or more strings in each content of files.

Example
opts := &Options{
	Root: "./testdata",
}
mfs, err := New(opts)
if err != nil {
	log.Fatal(err)
}

q := []string{"body"}
results := mfs.Search(q, 0)

for _, result := range results {
	fmt.Printf("Path: %s\n", result.Path)
	fmt.Printf("Snippets: %q\n", result.Snippets)
}
Output:

Path: /include/index.css
Snippets: ["body {\n}\n"]
Path: /exclude/index-link.css
Snippets: ["body {\n}\n"]
Path: /index.css
Snippets: ["body {\n}\n"]

func (*MemFS) Update added in v0.6.0

func (mfs *MemFS) Update(node *Node, newInfo os.FileInfo)

Update the node content and information in memory based on new file information. This method only check if the node name is equal with file name, but it's not checking whether the node is part of memfs (node is parent or have the same Root node).

type Node

type Node struct {
	os.FileInfo
	http.File

	SysPath string // The original file path in system.
	Path    string // Absolute file path in memory.

	ContentType     string // File type per MIME, for example "application/json".
	ContentEncoding string // File type encoding, for example "gzip".

	V      []byte  // Content of file.
	Parent *Node   // Pointer to parent directory.
	Childs []*Node // List of files in directory.

	GenFuncName string // The function name for generated Go code.
	// contains filtered or unexported fields
}

Node represent a single file.

func NewNode added in v0.6.0

func NewNode(parent *Node, fi os.FileInfo, maxFileSize int64) (node *Node, err error)

NewNode create a new node based on file information "fi".

The parent parameter is required to allow valid system path generated for new node.

If maxFileSize is greater than zero, the file content and its type will be saved in node as V and ContentType.

func (*Node) AddChild added in v0.16.0

func (leaf *Node) AddChild(child *Node)

AddChild add the other node as child of this node.

func (*Node) Close added in v0.11.0

func (leaf *Node) Close() error

Close reset the offset position back to zero.

func (*Node) Decode added in v0.10.1

func (leaf *Node) Decode() ([]byte, error)

Decode the contents of node (for example, uncompress with gzip) and return it.

func (*Node) Encode added in v0.29.2

func (leaf *Node) Encode(content []byte) (err error)

Encode compress and set the content of Node.

func (*Node) IsDir added in v0.11.0

func (leaf *Node) IsDir() bool

func (*Node) MarshalJSON added in v0.29.1

func (leaf *Node) MarshalJSON() ([]byte, error)

MarshalJSON encode the node into JSON format. If the node is a file it will return the content of file; otherwise it will return the node with list of childs, but not including childs of childs.

func (*Node) ModTime added in v0.6.0

func (leaf *Node) ModTime() time.Time

func (*Node) Mode

func (leaf *Node) Mode() os.FileMode

func (*Node) Name

func (leaf *Node) Name() string

func (*Node) Read added in v0.11.0

func (leaf *Node) Read(p []byte) (n int, err error)

Read the content of node into p.

func (*Node) Readdir added in v0.11.0

func (leaf *Node) Readdir(count int) (fis []os.FileInfo, err error)

Readdir reads the contents of the directory associated with file and returns a slice of up to n FileInfo values, as would be returned by Lstat, in directory order. Subsequent calls on the same file will yield further FileInfos.

func (*Node) Save added in v0.29.2

func (leaf *Node) Save(content []byte) (err error)

Save the content to file system and update the content of Node.

func (*Node) Seek added in v0.11.0

func (leaf *Node) Seek(offset int64, whence int) (int64, error)

Seek sets the offset for the next Read offset, interpreted according to whence: SeekStart means relative to the start of the file, SeekCurrent means relative to the current offset, and SeekEnd means relative to the end. Seek returns the new offset relative to the start of the file and an error, if any.

func (*Node) SetModTime added in v0.11.0

func (leaf *Node) SetModTime(modTime time.Time)

SetModTime set the file modification time.

func (*Node) SetMode added in v0.11.0

func (leaf *Node) SetMode(mode os.FileMode)

SetMode set the mode of file.

func (*Node) SetName added in v0.11.0

func (leaf *Node) SetName(name string)

SetName set the name of file.

func (*Node) SetSize added in v0.11.0

func (leaf *Node) SetSize(size int64)

SetSize set the file size.

func (*Node) Size

func (leaf *Node) Size() int64

Size return the file size information.

func (*Node) Stat added in v0.11.0

func (leaf *Node) Stat() (os.FileInfo, error)

Stat return the file information.

func (*Node) Sys added in v0.11.0

func (leaf *Node) Sys() interface{}

Sys return the underlying data source (can return nil).

func (*Node) Update added in v0.30.0

func (leaf *Node) Update(newInfo os.FileInfo, maxFileSize int64) (err error)

Update the node metadata or content based on new file information.

The newInfo parameter is optional, if its nil, it will read the file information based on node's SysPath.

The maxFileSize parameter is also optional. If its negative, the node content will not be updated. If its zero, it will default to 5 MB.

There are two possible changes that will happen: its either change on mode or change on content (size and modtime). Change on mode will not affect the content of node.

type Options added in v0.23.0

type Options struct {
	// Root contains path to directory where its contents will be mapped
	// to memory.
	Root string

	// The includes and excludes pattern applied to path of file in file
	// system.
	Includes []string
	Excludes []string

	// MaxFileSize define maximum file size that can be stored on memory.
	// The default value is 5 MB.
	// If its value is negative, the content of file will not be mapped to
	// memory, the MemFS will behave as directory tree.
	MaxFileSize int64

	// Development define a flag to bypass file in memory.
	// If its true, any call to Get will result in direct read to file
	// system.
	Development bool
}

type PathNode added in v0.6.0

type PathNode struct {
	// contains filtered or unexported fields
}

PathNode contains a mapping between path and Node.

func NewPathNode added in v0.6.0

func NewPathNode() *PathNode

NewPathNode create and initialize new PathNode.

func (*PathNode) Delete added in v0.30.0

func (pn *PathNode) Delete(path string)

Delete the the node by its path.

func (*PathNode) Get added in v0.6.0

func (pn *PathNode) Get(path string) *Node

Get the node by path, or nil if path is not exist.

func (*PathNode) MarshalJSON added in v0.29.1

func (pn *PathNode) MarshalJSON() ([]byte, error)

func (*PathNode) Nodes added in v0.30.0

func (pn *PathNode) Nodes() (nodes []*Node)

Nodes return all the nodes.

func (*PathNode) Paths added in v0.30.0

func (pn *PathNode) Paths() (paths []string)

Paths return all the nodes keys as list of path.

func (*PathNode) Set added in v0.6.0

func (pn *PathNode) Set(path string, node *Node)

Set mapping of path to Node.

type SearchResult added in v0.10.1

type SearchResult struct {
	Path     string
	Snippets []string
}

SearchResult contains the result of searching where the Path will be filled with absolute path of file system in memory and the Snippet will filled with part of the text before and after the search string.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL