Skip to content

Commit 5ffc52e

Browse files
authored
Merge pull request #13 from terrastruct/tmpfs
tmpfs: Add
2 parents 06c6224 + c929d5a commit 5ffc52e

File tree

4 files changed

+95
-1
lines changed

4 files changed

+95
-1
lines changed

README.md

+7
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ own repo from this collection we will. Feel free to open an issue to request.
2727
- [./xexec](#xexec)
2828
- [./xhttp](#xhttp)
2929
- [./xmain](#xmain)
30+
- [./tmpfs](#tmpfs)
31+
32+
3033

3134
godoc is the canonical reference but we've provided this index as the godoc UI is frankly
3235
garbage after the move to pkg.go.dev. It's nowhere near as clear and responsive as the old
@@ -115,3 +118,7 @@ xhttp provides HTTP helpers.
115118
### [./xmain](./xmain)
116119

117120
xmain implements helpers for building CLI tools.
121+
122+
### [./tmpfs](./tmpfs)
123+
124+
Package tmpfs takes in an memory description of a filesystem and writes it to a temp directory so that it may be used as an io/fs.FS.

ci

Submodule ci updated 1 file

tmpfs/tmpfs.go

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Package tmpfs takes in an memory description of a filesystem
2+
// and writes it to a temp directory so that it may be used as an io/fs.FS.
3+
package tmpfs
4+
5+
import (
6+
"errors"
7+
"fmt"
8+
"io/fs"
9+
"os"
10+
"path"
11+
)
12+
13+
type FS struct {
14+
dir string
15+
fs.FS
16+
}
17+
18+
func Make(m map[string]string) (*FS, error) {
19+
tempDir, err := os.MkdirTemp("", "tmpfs-*")
20+
if err != nil {
21+
return nil, fmt.Errorf("failed to create root tmpfs dir: %w", err)
22+
}
23+
for p, s := range m {
24+
p = path.Join(tempDir, p)
25+
err = os.MkdirAll(path.Dir(p), 0755)
26+
if err != nil {
27+
return nil, fmt.Errorf("failed to create tmpfs dir %q: %w", path.Dir(p), err)
28+
}
29+
err = os.WriteFile(p, []byte(s), 0644)
30+
if err != nil {
31+
return nil, fmt.Errorf("failed to write tmpfs file %q: %w", p, err)
32+
}
33+
}
34+
return &FS{
35+
dir: tempDir,
36+
FS: os.DirFS(tempDir),
37+
}, nil
38+
}
39+
40+
func (fs *FS) Close() error {
41+
err := os.RemoveAll(fs.dir)
42+
if errors.Is(err, os.ErrNotExist) {
43+
return nil
44+
}
45+
if err != nil {
46+
return fmt.Errorf("failed to close tmpfs.FS: %w", err)
47+
}
48+
return nil
49+
}

tmpfs/tmpfs_test.go

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package tmpfs_test
2+
3+
import (
4+
"io/fs"
5+
"testing"
6+
7+
"oss.terrastruct.com/util-go/assert"
8+
"oss.terrastruct.com/util-go/tmpfs"
9+
)
10+
11+
func TestMemFS(t *testing.T) {
12+
t.Parallel()
13+
14+
m := map[string]string{
15+
"index": "<Espy_on_crack> I installed 'Linux 6.1', doesn't that make me a unix",
16+
"d2/imports": "Do your part to help preserve life on Earth -- by trying to preserve your own.",
17+
"d2/globs": "I'm going to raise an issue and stick it in your ear.",
18+
"nested/nested/nested/nested": "Yuppie Wannabes",
19+
}
20+
21+
tmpfs, err := tmpfs.Make(m)
22+
assert.Success(t, err)
23+
t.Cleanup(func() {
24+
err := tmpfs.Close()
25+
assert.Success(t, err)
26+
})
27+
28+
for p, s := range m {
29+
b, err := fs.ReadFile(tmpfs, p)
30+
assert.Success(t, err)
31+
assert.Equal(t, s, string(b))
32+
}
33+
34+
_, err = fs.ReadFile(tmpfs, "../escape")
35+
assert.ErrorString(t, err, "stat ../escape: invalid argument")
36+
_, err = fs.ReadFile(tmpfs, "/root")
37+
assert.ErrorString(t, err, "stat /root: invalid argument")
38+
}

0 commit comments

Comments
 (0)