github.com/kovansky/hugo@v0.92.3-0.20220224232819-63076e4ff19f/hugofs/fs.go (about) 1 // Copyright 2019 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 provides the file systems used by Hugo. 15 package hugofs 16 17 import ( 18 "fmt" 19 "os" 20 "strings" 21 22 "github.com/gohugoio/hugo/config" 23 "github.com/spf13/afero" 24 ) 25 26 // Os points to the (real) Os filesystem. 27 var Os = &afero.OsFs{} 28 29 // Fs abstracts the file system to separate source and destination file systems 30 // and allows both to be mocked for testing. 31 type Fs struct { 32 // Source is Hugo's source file system. 33 Source afero.Fs 34 35 // Destination is Hugo's destination file system. 36 Destination afero.Fs 37 38 // Os is an OS file system. 39 // NOTE: Field is currently unused. 40 Os afero.Fs 41 42 // WorkingDir is a read-only file system 43 // restricted to the project working dir. 44 WorkingDir *afero.BasePathFs 45 } 46 47 // NewDefault creates a new Fs with the OS file system 48 // as source and destination file systems. 49 func NewDefault(cfg config.Provider) *Fs { 50 fs := &afero.OsFs{} 51 return newFs(fs, cfg) 52 } 53 54 // NewMem creates a new Fs with the MemMapFs 55 // as source and destination file systems. 56 // Useful for testing. 57 func NewMem(cfg config.Provider) *Fs { 58 fs := &afero.MemMapFs{} 59 return newFs(fs, cfg) 60 } 61 62 // NewFrom creates a new Fs based on the provided Afero Fs 63 // as source and destination file systems. 64 // Useful for testing. 65 func NewFrom(fs afero.Fs, cfg config.Provider) *Fs { 66 return newFs(fs, cfg) 67 } 68 69 func newFs(base afero.Fs, cfg config.Provider) *Fs { 70 return &Fs{ 71 Source: base, 72 Destination: base, 73 Os: &afero.OsFs{}, 74 WorkingDir: getWorkingDirFs(base, cfg), 75 } 76 } 77 78 func getWorkingDirFs(base afero.Fs, cfg config.Provider) *afero.BasePathFs { 79 workingDir := cfg.GetString("workingDir") 80 81 if workingDir != "" { 82 return afero.NewBasePathFs(afero.NewReadOnlyFs(base), workingDir).(*afero.BasePathFs) 83 } 84 85 return nil 86 } 87 88 func isWrite(flag int) bool { 89 return flag&os.O_RDWR != 0 || flag&os.O_WRONLY != 0 90 } 91 92 // MakeReadableAndRemoveAllModulePkgDir makes any subdir in dir readable and then 93 // removes the root. 94 // TODO(bep) move this to a more suitable place. 95 // 96 func MakeReadableAndRemoveAllModulePkgDir(fs afero.Fs, dir string) (int, error) { 97 // Safe guard 98 if !strings.Contains(dir, "pkg") { 99 panic(fmt.Sprint("invalid dir:", dir)) 100 } 101 102 counter := 0 103 afero.Walk(fs, dir, func(path string, info os.FileInfo, err error) error { 104 if err != nil { 105 return nil 106 } 107 if info.IsDir() { 108 counter++ 109 fs.Chmod(path, 0777) 110 } 111 return nil 112 }) 113 return counter, fs.RemoveAll(dir) 114 }