1
0
mirror of https://github.com/gohugoio/hugo.git synced 2024-05-11 05:54:58 +00:00

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
This commit is contained in:
Bjørn Erik Pedersen
2016-07-10 19:37:27 +02:00
parent e70cf1ace4
commit 364e69ab7f
3 changed files with 124 additions and 10 deletions

View File

@@ -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) {