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 }