From e5aa47749157e4c49a645d37df89fa76b0e8f952 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Sun, 14 Feb 2016 12:16:03 +0100 Subject: [PATCH] Add support for symbolic links for content, layout, static, theme Note: This is for the content roots only, but that should satisfy most needs. Fixes #1855 --- commands/hugo.go | 14 +++++++------- commands/import_jekyll.go | 2 +- helpers/path.go | 18 ++++++++++++++++++ source/filesystem.go | 8 +++++++- 4 files changed, 33 insertions(+), 9 deletions(-) diff --git a/commands/hugo.go b/commands/hugo.go index daf483923..78a416d65 100644 --- a/commands/hugo.go +++ b/commands/hugo.go @@ -17,6 +17,7 @@ package commands import ( "fmt" + "github.com/spf13/hugo/hugofs" "io/ioutil" "net/http" "os" @@ -35,7 +36,6 @@ import ( "github.com/spf13/cobra" "github.com/spf13/fsync" "github.com/spf13/hugo/helpers" - "github.com/spf13/hugo/hugofs" "github.com/spf13/hugo/hugolib" "github.com/spf13/hugo/livereload" "github.com/spf13/hugo/utils" @@ -651,12 +651,12 @@ func getDirList() []string { return nil } - filepath.Walk(dataDir, walker) - filepath.Walk(helpers.AbsPathify(viper.GetString("ContentDir")), walker) - filepath.Walk(helpers.AbsPathify(viper.GetString("LayoutDir")), walker) - filepath.Walk(helpers.AbsPathify(viper.GetString("StaticDir")), walker) + helpers.SymbolicWalk(hugofs.SourceFs, dataDir, walker) + helpers.SymbolicWalk(hugofs.SourceFs, helpers.AbsPathify(viper.GetString("ContentDir")), walker) + helpers.SymbolicWalk(hugofs.SourceFs, helpers.AbsPathify(viper.GetString("LayoutDir")), walker) + helpers.SymbolicWalk(hugofs.SourceFs, helpers.AbsPathify(viper.GetString("StaticDir")), walker) if helpers.ThemeSet() { - filepath.Walk(helpers.AbsPathify(viper.GetString("themesDir")+"/"+viper.GetString("theme")), walker) + helpers.SymbolicWalk(hugofs.SourceFs, helpers.AbsPathify(viper.GetString("themesDir")+"/"+viper.GetString("theme")), walker) } return a @@ -769,7 +769,7 @@ func NewWatcher(port int) error { // When mkdir -p is used, only the top directory triggers an event (at least on OSX) if ev.Op&fsnotify.Create == fsnotify.Create { if s, err := hugofs.SourceFs.Stat(ev.Name); err == nil && s.Mode().IsDir() { - afero.Walk(hugofs.SourceFs, ev.Name, walkAdder) + helpers.SymbolicWalk(hugofs.SourceFs, ev.Name, walkAdder) } } diff --git a/commands/import_jekyll.go b/commands/import_jekyll.go index 820948174..40d243375 100644 --- a/commands/import_jekyll.go +++ b/commands/import_jekyll.go @@ -124,7 +124,7 @@ func importFromJekyll(cmd *cobra.Command, args []string) error { return convertJekyllPost(path, relPath, targetDir, draft) } - err = filepath.Walk(jekyllRoot, callback) + err = helpers.SymbolicWalk(hugofs.OsFs, jekyllRoot, callback) if err != nil { return err diff --git a/helpers/path.go b/helpers/path.go index f39815b6e..1ac5a87d8 100644 --- a/helpers/path.go +++ b/helpers/path.go @@ -428,6 +428,24 @@ func FindCWD() (string, error) { return path, nil } +// SymbolicWalk is like filepath.Walk, but it supports the root being a +// symbolic link. It will still not follow symbolic links deeper down in +// the file structure +func SymbolicWalk(fs afero.Fs, root string, walker filepath.WalkFunc) error { + rootContent, err := afero.ReadDir(fs, root) + + if err != nil { + return walker(root, nil, err) + } + + for _, fi := range rootContent { + afero.Walk(fs, filepath.Join(root, fi.Name()), walker) + } + + return nil + +} + // Same as WriteToDisk but checks to see if file/directory already exists. func SafeWriteToDisk(inpath string, r io.Reader, fs afero.Fs) (err error) { return afero.SafeWriteReader(fs, inpath, r) diff --git a/source/filesystem.go b/source/filesystem.go index 0f5358429..66270c589 100644 --- a/source/filesystem.go +++ b/source/filesystem.go @@ -14,6 +14,7 @@ package source import ( + "github.com/spf13/hugo/hugofs" "io" "os" "path/filepath" @@ -92,7 +93,12 @@ func (f *Filesystem) captureFiles() { return err } - filepath.Walk(f.Base, walker) + err := helpers.SymbolicWalk(hugofs.SourceFs, f.Base, walker) + + if err != nil { + jww.ERROR.Println(err) + } + } func (f *Filesystem) shouldRead(filePath string, fi os.FileInfo) (bool, error) {