shithub: hugo

Download patch

ref: ca6ca4f4fc29906e491b5ac6b63fb65125c9c9e4
parent: bcc42c0549263681ef9eada21a9fc4eb2d8ff055
author: Steve Francia <[email protected]>
date: Mon Dec 21 19:10:01 EST 2015

Separate handling content, data and template changes

Data & Templates reading independently
Need to work on page source reading and other source files

--- a/commands/hugo.go
+++ b/commands/hugo.go
@@ -44,6 +44,8 @@
 	"gopkg.in/fsnotify.v1"
 )
 
+var mainSite *hugolib.Site
+
 // userError is an error used to signal different error situations in command handling.
 type commandError struct {
 	s         string
@@ -528,20 +530,34 @@
 
 func buildSite(watching ...bool) (err error) {
 	startTime := time.Now()
-	site := &hugolib.Site{}
+	if mainSite == nil {
+		mainSite = new(hugolib.Site)
+	}
 	if len(watching) > 0 && watching[0] {
-		site.RunMode.Watching = true
+		mainSite.RunMode.Watching = true
 	}
-	err = site.Build()
+	err = mainSite.Build()
 	if err != nil {
 		return err
 	}
-	site.Stats()
+	mainSite.Stats()
 	jww.FEEDBACK.Printf("in %v ms\n", int(1000*time.Since(startTime).Seconds()))
 
 	return nil
 }
 
+func rebuildSite(changes map[string]bool) error {
+	startTime := time.Now()
+	err := mainSite.ReBuild(changes)
+	if err != nil {
+		return err
+	}
+	mainSite.Stats()
+	jww.FEEDBACK.Printf("in %v ms\n", int(1000*time.Since(startTime).Seconds()))
+
+	return nil
+}
+
 // NewWatcher creates a new watcher to watch filesystem events.
 func NewWatcher(port int) error {
 	if runtime.GOOS == "darwin" {
@@ -574,6 +590,7 @@
 				staticChanged := false
 				dynamicChanged := false
 				staticFilesChanged := make(map[string]bool)
+				dynamicFilesChanged := make(map[string]bool)
 
 				for _, ev := range evs {
 					ext := filepath.Ext(ev.Name)
@@ -603,7 +620,11 @@
 					dynamicChanged = dynamicChanged || !isstatic
 
 					if isstatic {
-						staticFilesChanged[ev.Name] = true
+						if staticPath, err := helpers.MakeStaticPathRelative(ev.Name); err == nil {
+							staticFilesChanged[staticPath] = true
+						}
+					} else {
+						dynamicFilesChanged[ev.Name] = true
 					}
 
 					// add new directory to watch list
@@ -680,7 +701,10 @@
 					fmt.Print("\nChange detected, rebuilding site\n")
 					const layout = "2006-01-02 15:04 -0700"
 					fmt.Println(time.Now().Format(layout))
-					utils.CheckErr(buildSite(true))
+					//TODO here
+
+				//	utils.CheckErr(buildSite(true))
+					rebuildSite(dynamicFilesChanged)
 
 					if !BuildWatch && !viper.GetBool("DisableLiveReload") {
 						// Will block forever trying to write to a channel that nobody is reading if livereload isn't initalized
--- a/hugolib/site.go
+++ b/hugolib/site.go
@@ -426,6 +426,78 @@
 	return nil
 }
 
+func (s *Site) ReBuild(changed map[string]bool) error {
+	s.timerStep("initialize rebuild")
+	// First we need to determine what changed
+
+	sourceChanged := []string{}
+	tmplChanged := []string{}
+	dataChanged := []string{}
+	var err error
+
+	for f := range changed {
+		// Need to re-read source
+		if strings.HasPrefix(f, s.absContentDir()) {
+			fmt.Println("Source changed", f)
+			sourceChanged = append(sourceChanged, f)
+		}
+		if strings.HasPrefix(f, s.absLayoutDir()) || strings.HasPrefix(f, s.absThemeDir()) {
+			fmt.Println("Template changed", f)
+			tmplChanged = append(tmplChanged, f)
+		}
+		if strings.HasPrefix(f, s.absDataDir()) {
+			fmt.Println("Data changed", f)
+			dataChanged = append(dataChanged, f)
+		}
+	}
+
+
+	if len(tmplChanged) > 0 {
+		s.prepTemplates()
+		s.Tmpl.PrintErrors()
+		s.timerStep("template prep")
+	}
+
+	if len(dataChanged) > 0 {
+		s.ReadDataFromSourceFS()
+	}
+
+	if len (sourceChanged) > 0 {
+		if err = s.CreatePages(); err != nil {
+			return err
+		}
+		s.setupPrevNext()
+		if err = s.BuildSiteMeta(); err != nil {
+			return err
+		}
+		s.timerStep("build taxonomies")
+	}
+
+	if err = s.Render(); err != nil {
+		// Better reporting when the template is missing (commit 2bbecc7b)
+		jww.ERROR.Printf("Error rendering site: %s", err)
+
+		jww.ERROR.Printf("Available templates:")
+		var keys []string
+		for _, template := range s.Tmpl.Templates() {
+			if name := template.Name(); name != "" {
+				keys = append(keys, name)
+			}
+		}
+		sort.Strings(keys)
+		for _, k := range keys {
+			jww.ERROR.Printf("\t%s\n", k)
+		}
+
+		return nil
+	} else {
+		return err
+	}
+
+	return nil
+}
+
+
 func (s *Site) Analyze() error {
 	if err := s.Process(); err != nil {
 		return err
@@ -508,17 +580,8 @@
 	}
 }
 
-func (s *Site) Process() (err error) {
-	s.timerStep("Go initialization")
-	if err = s.initialize(); err != nil {
-		return
-	}
-	s.prepTemplates()
-	s.Tmpl.PrintErrors()
-	s.timerStep("initialize & template prep")
-
+func (s *Site) ReadDataFromSourceFS() error {
 	dataSources := make([]source.Input, 0, 2)
-
 	dataSources = append(dataSources, &source.Filesystem{Base: s.absDataDir()})
 
 	// have to be last - duplicate keys in earlier entries will win
@@ -527,11 +590,24 @@
 		dataSources = append(dataSources, &source.Filesystem{Base: themeStaticDir})
 	}
 
-	if err = s.loadData(dataSources); err != nil {
+	err = s.loadData(dataSources)
+	s.timerStep("load data")
+	return err
+}
+
+func (s *Site) Process() (err error) {
+	s.timerStep("Go initialization")
+	if err = s.initialize(); err != nil {
 		return
 	}
-	s.timerStep("load data")
+	s.prepTemplates()
+	s.Tmpl.PrintErrors()
+	s.timerStep("initialize & template prep")
 
+	if err = s.ReadDataFromSourceFS(); err != nil {
+		return
+	}
+
 	if err = s.CreatePages(); err != nil {
 		return
 	}
@@ -864,7 +940,6 @@
 }
 
 func (s *Site) BuildSiteMeta() (err error) {
-
 	s.assembleMenus()
 
 	if len(s.Pages) == 0 {
@@ -929,6 +1004,7 @@
 }
 
 func (s *Site) assembleMenus() {
+	s.Menus = Menus{}
 
 	type twoD struct {
 		MenuName, EntryName string