mirror of
https://github.com/gohugoio/hugo.git
synced 2025-08-16 20:53:59 +02:00
Introduce source.Filesystem
This provides an abstraction over how files are processed by Hugo. This allows for alternatives like CMS systems or Dropbox, etc.
This commit is contained in:
25
source/content_directory_test.go
Normal file
25
source/content_directory_test.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package source
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIgnoreDotFiles(t *testing.T) {
|
||||
tests := []struct {
|
||||
path string
|
||||
ignore bool
|
||||
}{
|
||||
{"barfoo.md", false},
|
||||
{"foobar/barfoo.md", false},
|
||||
{"foobar/.barfoo.md", true},
|
||||
{".barfoo.md", true},
|
||||
{".md", true},
|
||||
{"", true},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
if ignored := ignoreDotFile(test.path); test.ignore != ignored {
|
||||
t.Errorf("File not ignored. Expected: %t, got: %t", test.ignore, ignored)
|
||||
}
|
||||
}
|
||||
}
|
72
source/filesystem.go
Normal file
72
source/filesystem.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package source
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
type Input interface {
|
||||
Files() []*File
|
||||
}
|
||||
|
||||
type File struct {
|
||||
Name string
|
||||
Contents io.Reader
|
||||
}
|
||||
|
||||
type Filesystem struct {
|
||||
files []*File
|
||||
Base string
|
||||
AvoidPaths []string
|
||||
}
|
||||
|
||||
func (f *Filesystem) Files() []*File {
|
||||
f.captureFiles()
|
||||
return f.files
|
||||
}
|
||||
|
||||
func (f *Filesystem) add(name string, reader io.Reader) {
|
||||
f.files = append(f.files, &File{Name: name, Contents: reader})
|
||||
}
|
||||
|
||||
func (f *Filesystem) captureFiles() {
|
||||
|
||||
walker := func(path string, fi os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if fi.IsDir() {
|
||||
if f.avoid(path) {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
return nil
|
||||
} else {
|
||||
if ignoreDotFile(path) {
|
||||
return nil
|
||||
}
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f.add(path, file)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
filepath.Walk(f.Base, walker)
|
||||
}
|
||||
|
||||
func (f *Filesystem) avoid(path string) bool {
|
||||
for _, avoid := range f.AvoidPaths {
|
||||
if avoid == path {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func ignoreDotFile(path string) bool {
|
||||
return filepath.Base(path)[0] == '.'
|
||||
}
|
32
source/filesystem_test.go
Normal file
32
source/filesystem_test.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package source
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestEmptySourceFilesystem(t *testing.T) {
|
||||
src := new(Filesystem)
|
||||
if len(src.Files()) != 0 {
|
||||
t.Errorf("new filesystem should contain 0 files.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddFile(t *testing.T) {
|
||||
src := new(Filesystem)
|
||||
src.add("foobar", bytes.NewReader([]byte("aaa")))
|
||||
if len(src.Files()) != 1 {
|
||||
t.Errorf("Files() should return 1 file")
|
||||
}
|
||||
|
||||
f := src.Files()[0]
|
||||
if f.Name != "foobar" {
|
||||
t.Errorf("File name should be 'foobar', got: %s", f.Name)
|
||||
}
|
||||
|
||||
b := new(bytes.Buffer)
|
||||
b.ReadFrom(f.Contents)
|
||||
if b.String() != "aaa" {
|
||||
t.Errorf("File contents should be 'aaa', got: %s", b.String())
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user