Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/gohugoio/hugo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2016-07-10 20:37:27 +0300
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2016-09-11 21:00:38 +0300
commit364e69ab7f54ab7a9901644647125f21cd39e98c (patch)
treedcc48331b2a7d14c885696bfc5b844a206be0bad /helpers
parente70cf1ace45498366d029e699af39441fab6bd0f (diff)
Handle symlink change event
Hugo 0.16 announced support for symbolic links for the root folders, /content, /static etc., but this got broken pretty fast. The main problem this commit tries to solve is the matching of file change events to "what changed". An example: ContentDir: /mysites/site/content where /mysites/site/content is a symlink to /mycontent /mycontent: /mypost1.md /post/mypost2.md * A change to mypost1.md (on OS X) will trigger a file change event with name "/mycontent/mypost1.md" * A change to mypost2.md gives event with name "/mysites/site/content/mypost2.md" The first change will not trigger a correct update of Hugo before this commit. This commit fixes this by doing a two-step check: 1. Check if "/mysites/site/content/mypost2.md" is within /mysites/site/content 2. Check if "/mysites/site/content/mypost2.md" is within the real path that /mysites/site/content points to Fixes #2265 Closes #2273
Diffstat (limited to 'helpers')
-rw-r--r--helpers/path.go40
-rw-r--r--helpers/path_test.go25
2 files changed, 62 insertions, 3 deletions
diff --git a/helpers/path.go b/helpers/path.go
index a8a50aab3..478512efa 100644
--- a/helpers/path.go
+++ b/helpers/path.go
@@ -481,17 +481,17 @@ func SymbolicWalk(fs afero.Fs, root string, walker filepath.WalkFunc) error {
}
// Handle the root first
- fileInfo, err := lstatIfOs(fs, root)
+ fileInfo, realPath, err := getRealFileInfo(fs, root)
if err != nil {
return walker(root, nil, err)
}
if !fileInfo.IsDir() {
- return nil
+ return fmt.Errorf("Cannot walk regular file %s", root)
}
- if err := walker(root, fileInfo, err); err != nil && err != filepath.SkipDir {
+ if err := walker(realPath, fileInfo, err); err != nil && err != filepath.SkipDir {
return err
}
@@ -511,6 +511,40 @@ func SymbolicWalk(fs afero.Fs, root string, walker filepath.WalkFunc) error {
}
+func getRealFileInfo(fs afero.Fs, path string) (os.FileInfo, string, error) {
+ fileInfo, err := lstatIfOs(fs, path)
+ realPath := path
+
+ if err != nil {
+ return nil, "", err
+ }
+
+ if fileInfo.Mode()&os.ModeSymlink == os.ModeSymlink {
+ link, err := filepath.EvalSymlinks(path)
+ if err != nil {
+ return nil, "", fmt.Errorf("Cannot read symbolic link '%s', error was: %s", path, err)
+ }
+ fileInfo, err = lstatIfOs(fs, link)
+ if err != nil {
+ return nil, "", fmt.Errorf("Cannot stat '%s', error was: %s", link, err)
+ }
+ realPath = link
+ }
+ return fileInfo, realPath, nil
+}
+
+// GetRealPath returns the real file path for the given path, whether it is a
+// symlink or not.
+func GetRealPath(fs afero.Fs, path string) (string, error) {
+ _, realPath, err := getRealFileInfo(fs, path)
+
+ if err != nil {
+ return "", err
+ }
+
+ return realPath, nil
+}
+
// Code copied from Afero's path.go
// if the filesystem is OsFs use Lstat, else use fs.Stat
func lstatIfOs(fs afero.Fs, path string) (info os.FileInfo, err error) {
diff --git a/helpers/path_test.go b/helpers/path_test.go
index a1769f1da..bd8f8ed49 100644
--- a/helpers/path_test.go
+++ b/helpers/path_test.go
@@ -25,6 +25,8 @@ import (
"testing"
"time"
+ "github.com/stretchr/testify/assert"
+
"github.com/spf13/afero"
"github.com/spf13/viper"
)
@@ -141,6 +143,29 @@ func TestGetRelativePath(t *testing.T) {
}
}
+func TestGetRealPath(t *testing.T) {
+ d1, err := ioutil.TempDir("", "d1")
+ defer os.Remove(d1)
+ fs := afero.NewOsFs()
+
+ rp1, err := GetRealPath(fs, d1)
+ assert.NoError(t, err)
+ assert.Equal(t, d1, rp1)
+
+ sym := filepath.Join(os.TempDir(), "d1sym")
+ err = os.Symlink(d1, sym)
+ defer os.Remove(sym)
+ assert.NoError(t, err)
+
+ rp2, err := GetRealPath(fs, sym)
+ assert.NoError(t, err)
+
+ // On OS X, the temp folder is itself a symbolic link (to /private...)
+ // This has to do for now.
+ assert.True(t, strings.HasSuffix(rp2, d1))
+
+}
+
func TestMakePathRelative(t *testing.T) {
type test struct {
inPath, path1, path2, output string