summaryrefslogtreecommitdiff
path: root/funcs/file.go
blob: 32af47cf97894d62e38d00be1b997d5f0136d451 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package funcs

import (
	"context"
	"io/fs"
	"path/filepath"

	osfs "github.com/hack-pad/hackpadfs/os"
	"github.com/hairyhenderson/gomplate/v4/conv"
	"github.com/hairyhenderson/gomplate/v4/internal/datafs"
	"github.com/hairyhenderson/gomplate/v4/internal/iohelpers"
)

// FileNS - the File namespace
//
// Deprecated: don't use
func FileNS() *FileFuncs {
	return &FileFuncs{}
}

// AddFileFuncs -
//
// Deprecated: use [CreateFileFuncs] instead
func AddFileFuncs(f map[string]interface{}) {
	for k, v := range CreateFileFuncs(context.Background()) {
		f[k] = v
	}
}

// CreateFileFuncs -
func CreateFileFuncs(ctx context.Context) map[string]interface{} {
	fsys, err := datafs.FSysForPath(ctx, "/")
	if err != nil {
		fsys = datafs.WrapWdFS(osfs.NewFS())
	}

	ns := &FileFuncs{
		ctx: ctx,
		fs:  fsys,
	}

	return map[string]interface{}{
		"file": func() interface{} { return ns },
	}
}

// FileFuncs -
type FileFuncs struct {
	ctx context.Context
	fs  fs.FS
}

// Read -
func (f *FileFuncs) Read(path interface{}) (string, error) {
	b, err := fs.ReadFile(f.fs, conv.ToString(path))
	return string(b), err
}

// Stat -
func (f *FileFuncs) Stat(path interface{}) (fs.FileInfo, error) {
	return fs.Stat(f.fs, conv.ToString(path))
}

// Exists -
func (f *FileFuncs) Exists(path interface{}) bool {
	_, err := f.Stat(conv.ToString(path))
	return err == nil
}

// IsDir -
func (f *FileFuncs) IsDir(path interface{}) bool {
	i, err := f.Stat(conv.ToString(path))
	return err == nil && i.IsDir()
}

// ReadDir -
func (f *FileFuncs) ReadDir(path interface{}) ([]string, error) {
	des, err := fs.ReadDir(f.fs, conv.ToString(path))
	if err != nil {
		return nil, err
	}

	names := make([]string, len(des))
	for i, de := range des {
		names[i] = de.Name()
	}

	return names, nil
}

// Walk -
func (f *FileFuncs) Walk(path interface{}) ([]string, error) {
	files := make([]string, 0)
	err := fs.WalkDir(f.fs, conv.ToString(path), func(subpath string, d fs.DirEntry, err error) error {
		if err != nil {
			return err
		}

		// fs.WalkDir always uses slash-separated paths, even on Windows. We
		// need to convert them to the OS-specific separator as that was the
		// previous behavior.
		subpath = filepath.FromSlash(subpath)

		files = append(files, subpath)
		return nil
	})
	return files, err
}

// Write -
func (f *FileFuncs) Write(path interface{}, data interface{}) (s string, err error) {
	type byteser interface{ Bytes() []byte }

	var content []byte
	fname := conv.ToString(path)

	if b, ok := data.([]byte); ok {
		content = b
	} else if b, ok := data.(byteser); ok {
		content = b.Bytes()
	} else {
		content = []byte(conv.ToString(data))
	}

	err = iohelpers.WriteFile(f.fs, fname, content)

	return "", err
}