Normalize paths within hugo

filepath was used inconsistently throughout the hugolib.  With the
introduction of source and target modules, all path are normalized to
"/".  This simplifies the processing of paths.  It does mean that
contributors need to be aware of using path/filepath in any module other
than source or target is not recommended.  The current exception is
hugolib/config.go
This commit is contained in:
Noah Campbell 2013-09-12 10:48:59 -07:00
parent 998b2f73f8
commit 74b55fc7c8
8 changed files with 46 additions and 43 deletions

View file

@ -103,7 +103,7 @@ func (c *Config) readInConfig() {
func (c *Config) setPath(p string) { func (c *Config) setPath(p string) {
if p == "" { if p == "" {
path, err := FindPath() path, err := findPath()
if err != nil { if err != nil {
fmt.Printf("Error finding path: %s", err) fmt.Printf("Error finding path: %s", err)
} }
@ -124,7 +124,7 @@ func (c *Config) GetPath() string {
return c.Path return c.Path
} }
func FindPath() (string, error) { func findPath() (string, error) {
serverFile, err := filepath.Abs(os.Args[0]) serverFile, err := filepath.Abs(os.Args[0])
if err != nil { if err != nil {
@ -147,13 +147,14 @@ func FindPath() (string, error) {
return path, nil return path, nil
} }
// GetAbsPath return the absolute path for a given path with the internal slashes
// properly converted.
func (c *Config) GetAbsPath(name string) string { func (c *Config) GetAbsPath(name string) string {
if filepath.IsAbs(name) { if filepath.IsAbs(name) {
return name return name
} }
p := filepath.Join(c.GetPath(), name) return filepath.ToSlash(filepath.Join(c.GetPath(), name))
return p
} }
func (c *Config) findConfigFile(configFileName string) (string, error) { func (c *Config) findConfigFile(configFileName string) (string, error) {

View file

@ -26,16 +26,13 @@ import (
"html/template" "html/template"
"io" "io"
"launchpad.net/goyaml" "launchpad.net/goyaml"
"os" "path"
"path/filepath"
"sort" "sort"
"strings" "strings"
"time" "time"
"unicode" "unicode"
) )
var _ = filepath.Base("")
type Page struct { type Page struct {
Status string Status string
Images []string Images []string
@ -135,7 +132,7 @@ func StripHTML(s string) string {
func (p *Page) guessSection() { func (p *Page) guessSection() {
if p.Section == "" { if p.Section == "" {
x := strings.Split(p.FileName, string(os.PathSeparator)) x := strings.Split(p.FileName, "/")
if len(x) > 1 { if len(x) > 1 {
if section := x[len(x)-2]; section != "content" { if section := x[len(x)-2]; section != "content" {
p.Section = section p.Section = section
@ -223,26 +220,26 @@ func (p *Page) Permalink() template.HTML {
section := strings.TrimSpace(p.Section) section := strings.TrimSpace(p.Section)
pSlug := strings.TrimSpace(p.Slug) pSlug := strings.TrimSpace(p.Slug)
pUrl := strings.TrimSpace(p.Url) pUrl := strings.TrimSpace(p.Url)
var path string var permalink string
if len(pSlug) > 0 { if len(pSlug) > 0 {
if p.Site.Config.UglyUrls { if p.Site.Config.UglyUrls {
path = section + "/" + p.Slug + "." + p.Extension permalink = section + "/" + p.Slug + "." + p.Extension
} else { } else {
path = section + "/" + p.Slug + "/" permalink = section + "/" + p.Slug + "/"
} }
} else if len(pUrl) > 2 { } else if len(pUrl) > 2 {
path = pUrl permalink = pUrl
} else { } else {
_, t := filepath.Split(p.FileName) _, t := path.Split(p.FileName)
if p.Site.Config.UglyUrls { if p.Site.Config.UglyUrls {
x := replaceExtension(strings.TrimSpace(t), p.Extension) x := replaceExtension(strings.TrimSpace(t), p.Extension)
path = section + "/" + x permalink = section + "/" + x
} else { } else {
file, _ := fileExt(strings.TrimSpace(t)) file, _ := fileExt(strings.TrimSpace(t))
path = section + "/" + file permalink = section + "/" + file
} }
} }
return template.HTML(MakePermalink(baseUrl, path)) return template.HTML(MakePermalink(baseUrl, permalink))
} }
func (page *Page) handleTomlMetaData(datum []byte) (interface{}, error) { func (page *Page) handleTomlMetaData(datum []byte) (interface{}, error) {

View file

@ -2,7 +2,7 @@ package hugolib
import ( import (
"html/template" "html/template"
"path/filepath" "path"
"strings" "strings"
"testing" "testing"
"time" "time"
@ -260,7 +260,7 @@ func TestDegenerateInvalidFrontMatterLeadingWhitespace(t *testing.T) {
} }
func TestSectionEvaluation(t *testing.T) { func TestSectionEvaluation(t *testing.T) {
page, _ := ReadFrom(strings.NewReader(SIMPLE_PAGE), filepath.FromSlash("blue/file1.md")) page, _ := ReadFrom(strings.NewReader(SIMPLE_PAGE), "blue/file1.md")
if page.Section != "blue" { if page.Section != "blue" {
t.Errorf("Section should be %s, got: %s", "blue", page.Section) t.Errorf("Section should be %s, got: %s", "blue", page.Section)
} }
@ -268,11 +268,11 @@ func TestSectionEvaluation(t *testing.T) {
func TestLayoutOverride(t *testing.T) { func TestLayoutOverride(t *testing.T) {
var ( var (
path_content_one_dir = filepath.Join("content", "gub", "file1.md") path_content_one_dir = path.Join("content", "gub", "file1.md")
path_content_two_dir = filepath.Join("content", "dub", "sub", "file1.md") path_content_two_dir = path.Join("content", "dub", "sub", "file1.md")
path_content_no_dir = filepath.Join("content", "file1") path_content_no_dir = path.Join("content", "file1")
path_one_directory = filepath.Join("fub", "file1.md") path_one_directory = path.Join("fub", "file1.md")
path_no_directory = filepath.Join("file1.md") path_no_directory = path.Join("file1.md")
) )
tests := []struct { tests := []struct {
content string content string

View file

@ -1,7 +1,7 @@
package hugolib package hugolib
import ( import (
"path/filepath" "path"
"strings" "strings"
"testing" "testing"
) )
@ -13,7 +13,7 @@ Sample Text
` `
func TestDegenerateMissingFolderInPageFilename(t *testing.T) { func TestDegenerateMissingFolderInPageFilename(t *testing.T) {
p, err := ReadFrom(strings.NewReader(SIMPLE_PAGE_YAML), filepath.Join("foobar")) p, err := ReadFrom(strings.NewReader(SIMPLE_PAGE_YAML), path.Join("foobar"))
if err != nil { if err != nil {
t.Fatalf("Error in ReadFrom") t.Fatalf("Error in ReadFrom")
} }
@ -28,9 +28,9 @@ func TestNewPageWithFilePath(t *testing.T) {
section string section string
layout string layout string
}{ }{
{filepath.Join("sub", "foobar.html"), "sub", "sub/single.html"}, {path.Join("sub", "foobar.html"), "sub", "sub/single.html"},
{filepath.Join("content", "sub", "foobar.html"), "sub", "sub/single.html"}, {path.Join("content", "sub", "foobar.html"), "sub", "sub/single.html"},
{filepath.Join("content", "dub", "sub", "foobar.html"), "sub", "sub/single.html"}, {path.Join("content", "dub", "sub", "foobar.html"), "sub", "sub/single.html"},
} }
for _, el := range toCheck { for _, el := range toCheck {

View file

@ -24,7 +24,7 @@ import (
"github.com/spf13/nitro" "github.com/spf13/nitro"
"html/template" "html/template"
"os" "os"
"path/filepath" "path"
"strings" "strings"
"time" "time"
) )
@ -264,7 +264,9 @@ func (s *Site) CreatePages() (err error) {
} }
page.Site = s.Info page.Site = s.Info
page.Tmpl = s.Tmpl page.Tmpl = s.Tmpl
_ = s.setUrlPath(page) if err = s.setUrlPath(page); err != nil {
return err
}
s.setOutFile(page) s.setOutFile(page)
if s.Config.BuildDrafts || !page.Draft { if s.Config.BuildDrafts || !page.Draft {
s.Pages = append(s.Pages, page) s.Pages = append(s.Pages, page)
@ -288,15 +290,15 @@ func (s *Site) setupPrevNext() {
} }
func (s *Site) setUrlPath(p *Page) error { func (s *Site) setUrlPath(p *Page) error {
y := strings.TrimPrefix(p.FileName, s.Config.GetAbsPath(s.Config.ContentDir)) y := strings.TrimPrefix(p.FileName, s.absContentDir())
x := strings.Split(y, string(os.PathSeparator)) x := strings.Split(y, "/")
if len(x) <= 1 { if len(x) <= 1 {
return fmt.Errorf("Zero length page name") return fmt.Errorf("Zero length page name")
} }
p.Section = strings.Trim(x[1], "/\\") p.Section = strings.Trim(x[1], "/")
p.Path = strings.Trim(strings.Join(x[:len(x)-1], string(os.PathSeparator)), "/\\") p.Path = path.Join(x[:len(x)-1]...)
return nil return nil
} }
@ -320,11 +322,11 @@ func (s *Site) setOutFile(p *Page) {
outfile = strings.TrimSpace(p.Slug) + "." + p.Extension outfile = strings.TrimSpace(p.Slug) + "." + p.Extension
} else { } else {
// Fall back to filename // Fall back to filename
_, t := filepath.Split(p.FileName) _, t := path.Split(p.FileName)
outfile = replaceExtension(strings.TrimSpace(t), p.Extension) outfile = replaceExtension(strings.TrimSpace(t), p.Extension)
} }
p.OutFile = p.Path + string(os.PathSeparator) + strings.TrimSpace(outfile) p.OutFile = p.Path + "/" + strings.TrimSpace(outfile)
} }
func (s *Site) BuildSiteMeta() (err error) { func (s *Site) BuildSiteMeta() (err error) {
@ -524,7 +526,7 @@ func (s *Site) RenderLists() error {
if err != nil { if err != nil {
return err return err
} }
err = s.WritePublic(section+"/index.html", content.Bytes()) err = s.WritePublic(section, content.Bytes())
if err != nil { if err != nil {
return err return err
} }

View file

@ -3,7 +3,6 @@ package hugolib
import ( import (
"bytes" "bytes"
"io" "io"
"path/filepath"
"strings" "strings"
"testing" "testing"
) )
@ -49,8 +48,8 @@ func TestPageCount(t *testing.T) {
s := &Site{Target: target} s := &Site{Target: target}
s.prepTemplates() s.prepTemplates()
must(s.addTemplate("indexes/blue.html", INDEX_TEMPLATE)) must(s.addTemplate("indexes/blue.html", INDEX_TEMPLATE))
s.Pages = append(s.Pages, mustReturn(ReadFrom(strings.NewReader(SLUG_DOC_1), filepath.FromSlash("content/blue/doc1.md")))) s.Pages = append(s.Pages, mustReturn(ReadFrom(strings.NewReader(SLUG_DOC_1), "content/blue/doc1.md")))
s.Pages = append(s.Pages, mustReturn(ReadFrom(strings.NewReader(SLUG_DOC_2), filepath.FromSlash("content/blue/doc2.md")))) s.Pages = append(s.Pages, mustReturn(ReadFrom(strings.NewReader(SLUG_DOC_2), "content/blue/doc2.md")))
if err := s.BuildSiteMeta(); err != nil { if err := s.BuildSiteMeta(); err != nil {
t.Errorf("Unable to build site metadata: %s", err) t.Errorf("Unable to build site metadata: %s", err)
@ -60,7 +59,7 @@ func TestPageCount(t *testing.T) {
t.Errorf("Unable to render site lists: %s", err) t.Errorf("Unable to render site lists: %s", err)
} }
blueIndex := target.files["blue/index.html"] blueIndex := target.files["blue"]
if blueIndex == nil { if blueIndex == nil {
t.Errorf("No indexed rendered. %v", target.files) t.Errorf("No indexed rendered. %v", target.files)
} }

View file

@ -27,6 +27,7 @@ func (f *Filesystem) Files() []*File {
} }
func (f *Filesystem) add(name string, reader io.Reader) { func (f *Filesystem) add(name string, reader io.Reader) {
name = filepath.ToSlash(name)
f.files = append(f.files, &File{Name: name, Contents: reader}) f.files = append(f.files, &File{Name: name, Contents: reader})
} }

View file

@ -14,6 +14,8 @@ func TestFileTranslator(t *testing.T) {
{"foo", "foo/index.html"}, {"foo", "foo/index.html"},
{"foo.html", "foo/index.html"}, {"foo.html", "foo/index.html"},
{"foo.xhtml", "foo/index.xhtml"}, {"foo.xhtml", "foo/index.xhtml"},
{"section", "section/index.html"},
{"section/", "section/index.html"},
{"section/foo", "section/foo/index.html"}, {"section/foo", "section/foo/index.html"},
{"section/foo.html", "section/foo/index.html"}, {"section/foo.html", "section/foo/index.html"},
{"section/foo.rss", "section/foo/index.rss"}, {"section/foo.rss", "section/foo/index.rss"},
@ -34,7 +36,7 @@ func TestFileTranslator(t *testing.T) {
func TestFileTranslatorBase(t *testing.T) { func TestFileTranslatorBase(t *testing.T) {
tests := []struct { tests := []struct {
content string content string
expected string expected string
}{ }{
{"/", "a/base/index.html"}, {"/", "a/base/index.html"},
@ -64,6 +66,7 @@ func TestTranslateUglyUrls(t *testing.T) {
}{ }{
{"foo.html", "foo.html"}, {"foo.html", "foo.html"},
{"/", "index.html"}, {"/", "index.html"},
{"section", "section.html"},
{"index.html", "index.html"}, {"index.html", "index.html"},
} }