mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-07 20:30:36 -05:00
Fix server rebuilds when adding sub sections especially on Windows
This commit also optimizes for the case where change events for both file (e.g. `_index.md`) and the container directory comes in the same event batch. While testing this on Windows 11 (ARM64), I notice that Windows behaves a little oddly when dumping a folder of files into the content tree; it works (at least after this commit), but it seems like the event batching behaves differently compared to other OSes (even older Win versions). A related tip would be to try starting the server with polling, to see if that improves the situation, e.g.: ``` hugo server --poll 700ms ``` Fixes #12230
This commit is contained in:
parent
f038a51b3e
commit
07b2e535be
3 changed files with 76 additions and 30 deletions
|
@ -595,8 +595,10 @@ func (h *HugoSites) processPartial(ctx context.Context, l logg.LevelLogger, conf
|
|||
return sb.String()
|
||||
}))
|
||||
|
||||
// For a list of events for the different OSes, see the test output in https://github.com/bep/fsnotifyeventlister/.
|
||||
events = h.fileEventsFilter(events)
|
||||
events = h.fileEventsTranslate(events)
|
||||
eventInfos := h.fileEventsApplyInfo(events)
|
||||
|
||||
logger := h.Log
|
||||
|
||||
|
@ -631,36 +633,12 @@ func (h *HugoSites) processPartial(ctx context.Context, l logg.LevelLogger, conf
|
|||
addedContentPaths []*paths.Path
|
||||
)
|
||||
|
||||
for _, ev := range events {
|
||||
removed := false
|
||||
added := false
|
||||
|
||||
if ev.Op&fsnotify.Remove == fsnotify.Remove {
|
||||
removed = true
|
||||
}
|
||||
|
||||
fi, statErr := h.Fs.Source.Stat(ev.Name)
|
||||
|
||||
// Some editors (Vim) sometimes issue only a Rename operation when writing an existing file
|
||||
// Sometimes a rename operation means that file has been renamed other times it means
|
||||
// it's been updated.
|
||||
if ev.Op.Has(fsnotify.Rename) {
|
||||
// If the file is still on disk, it's only been updated, if it's not, it's been moved
|
||||
if statErr != nil {
|
||||
removed = true
|
||||
}
|
||||
}
|
||||
if ev.Op.Has(fsnotify.Create) {
|
||||
added = true
|
||||
}
|
||||
|
||||
isChangedDir := statErr == nil && fi.IsDir()
|
||||
|
||||
for _, ev := range eventInfos {
|
||||
cpss := h.BaseFs.ResolvePaths(ev.Name)
|
||||
pss := make([]*paths.Path, len(cpss))
|
||||
for i, cps := range cpss {
|
||||
p := cps.Path
|
||||
if removed && !paths.HasExt(p) {
|
||||
if ev.removed && !paths.HasExt(p) {
|
||||
// Assume this is a renamed/removed directory.
|
||||
// For deletes, we walk up the tree to find the container (e.g. branch bundle),
|
||||
// so we will catch this even if it is a file without extension.
|
||||
|
@ -671,7 +649,7 @@ func (h *HugoSites) processPartial(ctx context.Context, l logg.LevelLogger, conf
|
|||
}
|
||||
|
||||
pss[i] = h.Configs.ContentPathParser.Parse(cps.Component, p)
|
||||
if added && !isChangedDir && cps.Component == files.ComponentFolderContent {
|
||||
if ev.added && !ev.isChangedDir && cps.Component == files.ComponentFolderContent {
|
||||
addedContentPaths = append(addedContentPaths, pss[i])
|
||||
}
|
||||
|
||||
|
@ -683,9 +661,9 @@ func (h *HugoSites) processPartial(ctx context.Context, l logg.LevelLogger, conf
|
|||
}
|
||||
}
|
||||
|
||||
if removed {
|
||||
if ev.removed {
|
||||
changedPaths.deleted = append(changedPaths.deleted, pss...)
|
||||
} else if isChangedDir {
|
||||
} else if ev.isChangedDir {
|
||||
changedPaths.changedDirs = append(changedPaths.changedDirs, pss...)
|
||||
} else {
|
||||
changedPaths.changedFiles = append(changedPaths.changedFiles, pss...)
|
||||
|
|
|
@ -161,7 +161,7 @@ func (c *pagesCollector) Collect() (collectErr error) {
|
|||
// We always start from a directory.
|
||||
collectErr = c.collectDir(id.p, id.isDir, func(fim hugofs.FileMetaInfo) bool {
|
||||
if id.delete || id.isDir {
|
||||
if id.isDir {
|
||||
if id.isDir && fim.Meta().PathInfo.IsLeafBundle() {
|
||||
return strings.HasPrefix(fim.Meta().PathInfo.Path(), paths.AddTrailingSlash(id.p.Path()))
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"io"
|
||||
"mime"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
|
@ -426,6 +427,73 @@ func (h *HugoSites) fileEventsFilter(events []fsnotify.Event) []fsnotify.Event {
|
|||
return events[:n]
|
||||
}
|
||||
|
||||
type fileEventInfo struct {
|
||||
fsnotify.Event
|
||||
fi os.FileInfo
|
||||
added bool
|
||||
removed bool
|
||||
isChangedDir bool
|
||||
}
|
||||
|
||||
func (h *HugoSites) fileEventsApplyInfo(events []fsnotify.Event) []fileEventInfo {
|
||||
var infos []fileEventInfo
|
||||
for _, ev := range events {
|
||||
removed := false
|
||||
added := false
|
||||
|
||||
if ev.Op&fsnotify.Remove == fsnotify.Remove {
|
||||
removed = true
|
||||
}
|
||||
|
||||
fi, statErr := h.Fs.Source.Stat(ev.Name)
|
||||
|
||||
// Some editors (Vim) sometimes issue only a Rename operation when writing an existing file
|
||||
// Sometimes a rename operation means that file has been renamed other times it means
|
||||
// it's been updated.
|
||||
if ev.Op.Has(fsnotify.Rename) {
|
||||
// If the file is still on disk, it's only been updated, if it's not, it's been moved
|
||||
if statErr != nil {
|
||||
removed = true
|
||||
}
|
||||
}
|
||||
if ev.Op.Has(fsnotify.Create) {
|
||||
added = true
|
||||
}
|
||||
|
||||
isChangedDir := statErr == nil && fi.IsDir()
|
||||
|
||||
infos = append(infos, fileEventInfo{
|
||||
Event: ev,
|
||||
fi: fi,
|
||||
added: added,
|
||||
removed: removed,
|
||||
isChangedDir: isChangedDir,
|
||||
})
|
||||
}
|
||||
|
||||
n := 0
|
||||
|
||||
for _, ev := range infos {
|
||||
// Remove any directories that's also represented by a file.
|
||||
keep := true
|
||||
if ev.isChangedDir {
|
||||
for _, ev2 := range infos {
|
||||
if ev2.fi != nil && !ev2.fi.IsDir() && filepath.Dir(ev2.Name) == ev.Name {
|
||||
keep = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if keep {
|
||||
infos[n] = ev
|
||||
n++
|
||||
}
|
||||
}
|
||||
infos = infos[:n]
|
||||
|
||||
return infos
|
||||
}
|
||||
|
||||
func (h *HugoSites) fileEventsTranslate(events []fsnotify.Event) []fsnotify.Event {
|
||||
eventMap := make(map[string][]fsnotify.Event)
|
||||
|
||||
|
|
Loading…
Reference in a new issue