shithub: hugo

Download patch

ref: 74b55fc7c87f2887c42ce8626cb461fee5d7b907
parent: 998b2f73f8da8886be87c29e23623d24445cbe93
author: Noah Campbell <[email protected]>
date: Thu Sep 12 06:48:59 EDT 2013

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

--- a/hugolib/config.go
+++ b/hugolib/config.go
@@ -103,7 +103,7 @@
 
 func (c *Config) setPath(p string) {
 	if p == "" {
-		path, err := FindPath()
+		path, err := findPath()
 		if err != nil {
 			fmt.Printf("Error finding path: %s", err)
 		}
@@ -124,7 +124,7 @@
 	return c.Path
 }
 
-func FindPath() (string, error) {
+func findPath() (string, error) {
 	serverFile, err := filepath.Abs(os.Args[0])
 
 	if err != nil {
@@ -147,13 +147,14 @@
 	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 {
 	if filepath.IsAbs(name) {
 		return name
 	}
 
-	p := filepath.Join(c.GetPath(), name)
-	return p
+	return filepath.ToSlash(filepath.Join(c.GetPath(), name))
 }
 
 func (c *Config) findConfigFile(configFileName string) (string, error) {
--- a/hugolib/page.go
+++ b/hugolib/page.go
@@ -26,8 +26,7 @@
 	"html/template"
 	"io"
 	"launchpad.net/goyaml"
-	"os"
-	"path/filepath"
+	"path"
 	"sort"
 	"strings"
 	"time"
@@ -34,8 +33,6 @@
 	"unicode"
 )
 
-var _ = filepath.Base("")
-
 type Page struct {
 	Status          string
 	Images          []string
@@ -135,7 +132,7 @@
 
 func (p *Page) guessSection() {
 	if p.Section == "" {
-		x := strings.Split(p.FileName, string(os.PathSeparator))
+		x := strings.Split(p.FileName, "/")
 		if len(x) > 1 {
 			if section := x[len(x)-2]; section != "content" {
 				p.Section = section
@@ -223,26 +220,26 @@
 	section := strings.TrimSpace(p.Section)
 	pSlug := strings.TrimSpace(p.Slug)
 	pUrl := strings.TrimSpace(p.Url)
-	var path string
+	var permalink string
 	if len(pSlug) > 0 {
 		if p.Site.Config.UglyUrls {
-			path = section + "/" + p.Slug + "." + p.Extension
+			permalink = section + "/" + p.Slug + "." + p.Extension
 		} else {
-			path = section + "/" + p.Slug + "/"
+			permalink = section + "/" + p.Slug + "/"
 		}
 	} else if len(pUrl) > 2 {
-		path = pUrl
+		permalink = pUrl
 	} else {
-		_, t := filepath.Split(p.FileName)
+		_, t := path.Split(p.FileName)
 		if p.Site.Config.UglyUrls {
 			x := replaceExtension(strings.TrimSpace(t), p.Extension)
-			path = section + "/" + x
+			permalink = section + "/" + x
 		} else {
 			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) {
--- a/hugolib/page_test.go
+++ b/hugolib/page_test.go
@@ -2,7 +2,7 @@
 
 import (
 	"html/template"
-	"path/filepath"
+	"path"
 	"strings"
 	"testing"
 	"time"
@@ -260,7 +260,7 @@
 }
 
 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" {
 		t.Errorf("Section should be %s, got: %s", "blue", page.Section)
 	}
@@ -268,11 +268,11 @@
 
 func TestLayoutOverride(t *testing.T) {
 	var (
-		path_content_one_dir = filepath.Join("content", "gub", "file1.md")
-		path_content_two_dir = filepath.Join("content", "dub", "sub", "file1.md")
-		path_content_no_dir  = filepath.Join("content", "file1")
-		path_one_directory   = filepath.Join("fub", "file1.md")
-		path_no_directory    = filepath.Join("file1.md")
+		path_content_one_dir = path.Join("content", "gub", "file1.md")
+		path_content_two_dir = path.Join("content", "dub", "sub", "file1.md")
+		path_content_no_dir  = path.Join("content", "file1")
+		path_one_directory   = path.Join("fub", "file1.md")
+		path_no_directory    = path.Join("file1.md")
 	)
 	tests := []struct {
 		content        string
--- a/hugolib/path_seperators_test.go
+++ b/hugolib/path_seperators_test.go
@@ -1,7 +1,7 @@
 package hugolib
 
 import (
-	"path/filepath"
+	"path"
 	"strings"
 	"testing"
 )
@@ -13,7 +13,7 @@
 `
 
 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 {
 		t.Fatalf("Error in ReadFrom")
 	}
@@ -28,9 +28,9 @@
 		section string
 		layout  string
 	}{
-		{filepath.Join("sub", "foobar.html"), "sub", "sub/single.html"},
-		{filepath.Join("content", "sub", "foobar.html"), "sub", "sub/single.html"},
-		{filepath.Join("content", "dub", "sub", "foobar.html"), "sub", "sub/single.html"},
+		{path.Join("sub", "foobar.html"), "sub", "sub/single.html"},
+		{path.Join("content", "sub", "foobar.html"), "sub", "sub/single.html"},
+		{path.Join("content", "dub", "sub", "foobar.html"), "sub", "sub/single.html"},
 	}
 
 	for _, el := range toCheck {
--- a/hugolib/site.go
+++ b/hugolib/site.go
@@ -24,7 +24,7 @@
 	"github.com/spf13/nitro"
 	"html/template"
 	"os"
-	"path/filepath"
+	"path"
 	"strings"
 	"time"
 )
@@ -264,7 +264,9 @@
 		}
 		page.Site = s.Info
 		page.Tmpl = s.Tmpl
-		_ = s.setUrlPath(page)
+		if err = s.setUrlPath(page); err != nil {
+			return err
+		}
 		s.setOutFile(page)
 		if s.Config.BuildDrafts || !page.Draft {
 			s.Pages = append(s.Pages, page)
@@ -288,15 +290,15 @@
 }
 
 func (s *Site) setUrlPath(p *Page) error {
-	y := strings.TrimPrefix(p.FileName, s.Config.GetAbsPath(s.Config.ContentDir))
-	x := strings.Split(y, string(os.PathSeparator))
+	y := strings.TrimPrefix(p.FileName, s.absContentDir())
+	x := strings.Split(y, "/")
 
 	if len(x) <= 1 {
 		return fmt.Errorf("Zero length page name")
 	}
 
-	p.Section = strings.Trim(x[1], "/\\")
-	p.Path = strings.Trim(strings.Join(x[:len(x)-1], string(os.PathSeparator)), "/\\")
+	p.Section = strings.Trim(x[1], "/")
+	p.Path = path.Join(x[:len(x)-1]...)
 	return nil
 }
 
@@ -320,11 +322,11 @@
 		outfile = strings.TrimSpace(p.Slug) + "." + p.Extension
 	} else {
 		// Fall back to filename
-		_, t := filepath.Split(p.FileName)
+		_, t := path.Split(p.FileName)
 		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) {
@@ -524,7 +526,7 @@
 		if err != nil {
 			return err
 		}
-		err = s.WritePublic(section+"/index.html", content.Bytes())
+		err = s.WritePublic(section, content.Bytes())
 		if err != nil {
 			return err
 		}
--- a/hugolib/site_url_test.go
+++ b/hugolib/site_url_test.go
@@ -3,7 +3,6 @@
 import (
 	"bytes"
 	"io"
-	"path/filepath"
 	"strings"
 	"testing"
 )
@@ -49,8 +48,8 @@
 	s := &Site{Target: target}
 	s.prepTemplates()
 	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_2), filepath.FromSlash("content/blue/doc2.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), "content/blue/doc2.md")))
 
 	if err := s.BuildSiteMeta(); err != nil {
 		t.Errorf("Unable to build site metadata: %s", err)
@@ -60,7 +59,7 @@
 		t.Errorf("Unable to render site lists: %s", err)
 	}
 
-	blueIndex := target.files["blue/index.html"]
+	blueIndex := target.files["blue"]
 	if blueIndex == nil {
 		t.Errorf("No indexed rendered. %v", target.files)
 	}
--- a/source/filesystem.go
+++ b/source/filesystem.go
@@ -27,6 +27,7 @@
 }
 
 func (f *Filesystem) add(name string, reader io.Reader) {
+	name = filepath.ToSlash(name)
 	f.files = append(f.files, &File{Name: name, Contents: reader})
 }
 
--- a/target/file_test.go
+++ b/target/file_test.go
@@ -14,6 +14,8 @@
 		{"foo", "foo/index.html"},
 		{"foo.html", "foo/index.html"},
 		{"foo.xhtml", "foo/index.xhtml"},
+		{"section", "section/index.html"},
+		{"section/", "section/index.html"},
 		{"section/foo", "section/foo/index.html"},
 		{"section/foo.html", "section/foo/index.html"},
 		{"section/foo.rss", "section/foo/index.rss"},
@@ -34,7 +36,7 @@
 
 func TestFileTranslatorBase(t *testing.T) {
 	tests := []struct {
-		content string
+		content  string
 		expected string
 	}{
 		{"/", "a/base/index.html"},
@@ -64,6 +66,7 @@
 	}{
 		{"foo.html", "foo.html"},
 		{"/", "index.html"},
+		{"section", "section.html"},
 		{"index.html", "index.html"},
 	}