mirror of
https://github.com/gohugoio/hugo.git
synced 2025-08-16 20:53:59 +02:00
Big refactor of how source files are used. Also added default destination extension option.
This commit is contained in:
114
source/file.go
Normal file
114
source/file.go
Normal file
@@ -0,0 +1,114 @@
|
||||
// Copyright © 2014 Steve Francia <spf@spf13.com>.
|
||||
//
|
||||
// Licensed under the Simple Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://opensource.org/licenses/Simple-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package source
|
||||
|
||||
import (
|
||||
"io"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/hugo/helpers"
|
||||
)
|
||||
|
||||
type File struct {
|
||||
relpath string // Original Full Path eg. /Users/Home/Hugo/foo.txt
|
||||
logicalName string // foo.txt
|
||||
Contents io.Reader
|
||||
section string // The first directory
|
||||
dir string // The full directory Path (minus file name)
|
||||
ext string // Just the ext (eg txt)
|
||||
uniqueId string // MD5 of the filename
|
||||
}
|
||||
|
||||
func (f *File) UniqueId() string {
|
||||
if f.uniqueId == "" {
|
||||
f.uniqueId = helpers.Md5String(f.LogicalName())
|
||||
}
|
||||
return f.uniqueId
|
||||
}
|
||||
|
||||
// Filename without extension
|
||||
func (f *File) BaseFileName() string {
|
||||
return helpers.Filename(f.LogicalName())
|
||||
}
|
||||
|
||||
func (f *File) Section() string {
|
||||
if f.section != "" {
|
||||
return f.section
|
||||
} else {
|
||||
f.section = helpers.GuessSection(f.Dir())
|
||||
return f.section
|
||||
}
|
||||
}
|
||||
|
||||
func (f *File) LogicalName() string {
|
||||
if f.logicalName != "" {
|
||||
return f.logicalName
|
||||
} else {
|
||||
_, f.logicalName = path.Split(f.relpath)
|
||||
return f.logicalName
|
||||
}
|
||||
}
|
||||
|
||||
//func (f *File) SetDir(dir string) {
|
||||
//f.dir = dir
|
||||
//}
|
||||
|
||||
func (f *File) Dir() string {
|
||||
if f.dir != "" {
|
||||
return f.dir
|
||||
} else {
|
||||
f.dir, _ = path.Split(f.relpath)
|
||||
return f.dir
|
||||
}
|
||||
}
|
||||
|
||||
func (f *File) Extension() string {
|
||||
if f.ext != "" {
|
||||
return f.ext
|
||||
} else {
|
||||
f.ext = strings.TrimPrefix(filepath.Ext(f.LogicalName()), ".")
|
||||
return f.ext
|
||||
}
|
||||
}
|
||||
|
||||
func (f *File) Ext() string {
|
||||
return f.Extension()
|
||||
}
|
||||
|
||||
func (f *File) Path() string {
|
||||
return f.relpath
|
||||
}
|
||||
|
||||
func NewFileWithContents(relpath string, content io.Reader) *File {
|
||||
file := NewFile(relpath)
|
||||
file.Contents = content
|
||||
return file
|
||||
}
|
||||
|
||||
func NewFile(relpath string) *File {
|
||||
return &File{
|
||||
relpath: relpath,
|
||||
}
|
||||
}
|
||||
|
||||
func NewFileFromAbs(base, fullpath string, content io.Reader) (f *File, err error) {
|
||||
var name string
|
||||
if name, err = helpers.GetRelativePath(fullpath, base); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewFileWithContents(name, content), nil
|
||||
}
|
@@ -1,34 +1,56 @@
|
||||
// Copyright © 2014 Steve Francia <spf@spf13.com>.
|
||||
//
|
||||
// Licensed under the Simple Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://opensource.org/licenses/Simple-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package source
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/hugo/helpers"
|
||||
)
|
||||
|
||||
type Input interface {
|
||||
Files() []*File
|
||||
}
|
||||
|
||||
type File struct {
|
||||
name string
|
||||
LogicalName string
|
||||
Contents io.Reader
|
||||
Section string
|
||||
Dir string
|
||||
}
|
||||
|
||||
type Filesystem struct {
|
||||
files []*File
|
||||
Base string
|
||||
AvoidPaths []string
|
||||
}
|
||||
|
||||
func (f *Filesystem) FilesByExts(exts ...string) []*File {
|
||||
var newFiles []*File
|
||||
|
||||
if len(exts) == 0 {
|
||||
return f.Files()
|
||||
}
|
||||
|
||||
for _, x := range f.Files() {
|
||||
for _, e := range exts {
|
||||
if x.Ext() == strings.TrimPrefix(e, ".") {
|
||||
newFiles = append(newFiles, x)
|
||||
}
|
||||
}
|
||||
}
|
||||
return newFiles
|
||||
}
|
||||
|
||||
func (f *Filesystem) Files() []*File {
|
||||
if len(f.files) < 1 {
|
||||
f.captureFiles()
|
||||
@@ -36,47 +58,23 @@ func (f *Filesystem) Files() []*File {
|
||||
return f.files
|
||||
}
|
||||
|
||||
var errMissingBaseDir = errors.New("source: missing base directory")
|
||||
|
||||
func (f *Filesystem) add(name string, reader io.Reader) (err error) {
|
||||
var file *File
|
||||
|
||||
if name, err = f.getRelativePath(name); err != nil {
|
||||
return err
|
||||
//if f.Base == "" {
|
||||
//file = NewFileWithContents(name, reader)
|
||||
//} else {
|
||||
file, err = NewFileFromAbs(f.Base, name, reader)
|
||||
//}
|
||||
|
||||
if err == nil {
|
||||
f.files = append(f.files, file)
|
||||
}
|
||||
|
||||
// section should be the first part of the path
|
||||
dir, logical := path.Split(name)
|
||||
parts := strings.Split(dir, "/")
|
||||
section := parts[0]
|
||||
|
||||
if section == "." {
|
||||
section = ""
|
||||
}
|
||||
|
||||
f.files = append(f.files, &File{
|
||||
name: name,
|
||||
LogicalName: logical,
|
||||
Contents: reader,
|
||||
Section: section,
|
||||
Dir: dir,
|
||||
})
|
||||
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
func (f *Filesystem) getRelativePath(name string) (final string, err error) {
|
||||
if filepath.IsAbs(name) && f.Base == "" {
|
||||
return "", errMissingBaseDir
|
||||
}
|
||||
name = filepath.Clean(name)
|
||||
base := filepath.Clean(f.Base)
|
||||
|
||||
name, err = filepath.Rel(base, name)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
name = filepath.ToSlash(name)
|
||||
return name, nil
|
||||
return helpers.GetRelativePath(name, f.Base)
|
||||
}
|
||||
|
||||
func (f *Filesystem) captureFiles() {
|
||||
|
@@ -32,16 +32,17 @@ func TestAddFile(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, src := range []*Filesystem{srcDefault, srcWithBase} {
|
||||
|
||||
p := test.filename
|
||||
if !filepath.IsAbs(test.filename) {
|
||||
p = path.Join(src.Base, test.filename)
|
||||
}
|
||||
|
||||
if err := src.add(p, bytes.NewReader([]byte(test.content))); err != nil {
|
||||
if err == errMissingBaseDir {
|
||||
if err.Error() == "source: missing base directory" {
|
||||
continue
|
||||
}
|
||||
t.Fatalf("%s add returned and error: %s", p, err)
|
||||
t.Fatalf("%s add returned an error: %s", p, err)
|
||||
}
|
||||
|
||||
if len(src.Files()) != 1 {
|
||||
@@ -49,8 +50,8 @@ func TestAddFile(t *testing.T) {
|
||||
}
|
||||
|
||||
f := src.Files()[0]
|
||||
if f.LogicalName != test.logical {
|
||||
t.Errorf("Filename (Base: %q) expected: %q, got: %q", src.Base, test.logical, f.LogicalName)
|
||||
if f.LogicalName() != test.logical {
|
||||
t.Errorf("Filename (Base: %q) expected: %q, got: %q", src.Base, test.logical, f.LogicalName())
|
||||
}
|
||||
|
||||
b := new(bytes.Buffer)
|
||||
@@ -59,12 +60,12 @@ func TestAddFile(t *testing.T) {
|
||||
t.Errorf("File (Base: %q) contents should be %q, got: %q", src.Base, test.content, b.String())
|
||||
}
|
||||
|
||||
if f.Section != test.section {
|
||||
t.Errorf("File section (Base: %q) expected: %q, got: %q", src.Base, test.section, f.Section)
|
||||
if f.Section() != test.section {
|
||||
t.Errorf("File section (Base: %q) expected: %q, got: %q", src.Base, test.section, f.Section())
|
||||
}
|
||||
|
||||
if f.Dir != test.dir {
|
||||
t.Errorf("Dir path (Base: %q) expected: %q, got: %q", src.Base, test.dir, f.Dir)
|
||||
if f.Dir() != test.dir {
|
||||
t.Errorf("Dir path (Base: %q) expected: %q, got: %q", src.Base, test.dir, f.Dir())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,17 +3,15 @@ package source
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"path"
|
||||
)
|
||||
|
||||
type ByteSource struct {
|
||||
Name string
|
||||
Content []byte
|
||||
Section string
|
||||
}
|
||||
|
||||
func (b *ByteSource) String() string {
|
||||
return fmt.Sprintf("%s %s %s", b.Name, b.Section, string(b.Content))
|
||||
return fmt.Sprintf("%s %s", b.Name, string(b.Content))
|
||||
}
|
||||
|
||||
type InMemorySource struct {
|
||||
@@ -23,12 +21,7 @@ type InMemorySource struct {
|
||||
func (i *InMemorySource) Files() (files []*File) {
|
||||
files = make([]*File, len(i.ByteSource))
|
||||
for i, fake := range i.ByteSource {
|
||||
files[i] = &File{
|
||||
LogicalName: fake.Name,
|
||||
Contents: bytes.NewReader(fake.Content),
|
||||
Section: fake.Section,
|
||||
Dir: path.Dir(fake.Name),
|
||||
}
|
||||
files[i] = NewFileWithContents(fake.Name, bytes.NewReader(fake.Content))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
Reference in New Issue
Block a user