filename_filter_fs.go (3982B)
1 // Copyright 2021 The Hugo Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 package hugofs
15
16 import (
17 "os"
18 "strings"
19 "syscall"
20 "time"
21
22 "github.com/gohugoio/hugo/hugofs/glob"
23 "github.com/spf13/afero"
24 )
25
26 var (
27 _ FilesystemUnwrapper = (*filenameFilterFs)(nil)
28 )
29
30 func newFilenameFilterFs(fs afero.Fs, base string, filter *glob.FilenameFilter) afero.Fs {
31 return &filenameFilterFs{
32 fs: fs,
33 base: base,
34 filter: filter,
35 }
36 }
37
38 // filenameFilterFs is a filesystem that filters by filename.
39 type filenameFilterFs struct {
40 base string
41 fs afero.Fs
42
43 filter *glob.FilenameFilter
44 }
45
46 func (fs *filenameFilterFs) UnwrapFilesystem() afero.Fs {
47 return fs.fs
48 }
49
50 func (fs *filenameFilterFs) LstatIfPossible(name string) (os.FileInfo, bool, error) {
51 fi, b, err := fs.fs.(afero.Lstater).LstatIfPossible(name)
52 if err != nil {
53 return nil, false, err
54 }
55 if !fs.filter.Match(name, fi.IsDir()) {
56 return nil, false, os.ErrNotExist
57 }
58 return fi, b, nil
59 }
60
61 func (fs *filenameFilterFs) Open(name string) (afero.File, error) {
62 fi, err := fs.fs.Stat(name)
63 if err != nil {
64 return nil, err
65 }
66
67 if !fs.filter.Match(name, fi.IsDir()) {
68 return nil, os.ErrNotExist
69 }
70
71 f, err := fs.fs.Open(name)
72 if err != nil {
73 return nil, err
74 }
75
76 if !fi.IsDir() {
77 return f, nil
78 }
79
80 return &filenameFilterDir{
81 File: f,
82 base: fs.base,
83 filter: fs.filter,
84 }, nil
85 }
86
87 func (fs *filenameFilterFs) OpenFile(name string, flag int, perm os.FileMode) (afero.File, error) {
88 return fs.Open(name)
89 }
90
91 func (fs *filenameFilterFs) Stat(name string) (os.FileInfo, error) {
92 fi, _, err := fs.LstatIfPossible(name)
93 return fi, err
94 }
95
96 func (fs *filenameFilterFs) getOpener(name string) func() (afero.File, error) {
97 return func() (afero.File, error) {
98 return fs.Open(name)
99 }
100 }
101
102 type filenameFilterDir struct {
103 afero.File
104 base string
105 filter *glob.FilenameFilter
106 }
107
108 func (f *filenameFilterDir) Readdir(count int) ([]os.FileInfo, error) {
109 fis, err := f.File.Readdir(-1)
110 if err != nil {
111 return nil, err
112 }
113
114 var result []os.FileInfo
115 for _, fi := range fis {
116 fim := fi.(FileMetaInfo)
117 if f.filter.Match(strings.TrimPrefix(fim.Meta().Filename, f.base), fim.IsDir()) {
118 result = append(result, fi)
119 }
120 }
121
122 return result, nil
123 }
124
125 func (f *filenameFilterDir) Readdirnames(count int) ([]string, error) {
126 dirsi, err := f.Readdir(count)
127 if err != nil {
128 return nil, err
129 }
130
131 dirs := make([]string, len(dirsi))
132 for i, d := range dirsi {
133 dirs[i] = d.Name()
134 }
135 return dirs, nil
136 }
137
138 func (fs *filenameFilterFs) Chmod(n string, m os.FileMode) error {
139 return syscall.EPERM
140 }
141
142 func (fs *filenameFilterFs) Chtimes(n string, a, m time.Time) error {
143 return syscall.EPERM
144 }
145
146 func (fs *filenameFilterFs) Chown(n string, uid, gid int) error {
147 return syscall.EPERM
148 }
149
150 func (fs *filenameFilterFs) ReadDir(name string) ([]os.FileInfo, error) {
151 panic("not implemented")
152 }
153
154 func (fs *filenameFilterFs) Remove(n string) error {
155 return syscall.EPERM
156 }
157
158 func (fs *filenameFilterFs) RemoveAll(p string) error {
159 return syscall.EPERM
160 }
161
162 func (fs *filenameFilterFs) Rename(o, n string) error {
163 return syscall.EPERM
164 }
165 func (fs *filenameFilterFs) Create(n string) (afero.File, error) {
166 return nil, syscall.EPERM
167 }
168 func (fs *filenameFilterFs) Name() string {
169 return "FinameFilterFS"
170 }
171
172 func (fs *filenameFilterFs) Mkdir(n string, p os.FileMode) error {
173 return syscall.EPERM
174 }
175
176 func (fs *filenameFilterFs) MkdirAll(n string, p os.FileMode) error {
177 return syscall.EPERM
178 }