github.com/whatlly/hugo@v0.47.1/hugolib/hugo_sites_build.go (about) 1 // Copyright 2016-present The Hugo Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package hugolib 15 16 import ( 17 "bytes" 18 "fmt" 19 20 "errors" 21 22 jww "github.com/spf13/jwalterweatherman" 23 24 "github.com/fsnotify/fsnotify" 25 "github.com/gohugoio/hugo/helpers" 26 ) 27 28 // Build builds all sites. If filesystem events are provided, 29 // this is considered to be a potential partial rebuild. 30 func (h *HugoSites) Build(config BuildCfg, events ...fsnotify.Event) error { 31 32 if h.Metrics != nil { 33 h.Metrics.Reset() 34 } 35 36 //t0 := time.Now() 37 38 // Need a pointer as this may be modified. 39 conf := &config 40 41 if conf.whatChanged == nil { 42 // Assume everything has changed 43 conf.whatChanged = &whatChanged{source: true, other: true} 44 } 45 46 for _, s := range h.Sites { 47 s.Deps.BuildStartListeners.Notify() 48 } 49 50 if len(events) > 0 { 51 // Rebuild 52 if err := h.initRebuild(conf); err != nil { 53 return err 54 } 55 } else { 56 if err := h.init(conf); err != nil { 57 return err 58 } 59 } 60 61 if err := h.process(conf, events...); err != nil { 62 return err 63 } 64 65 if err := h.assemble(conf); err != nil { 66 return err 67 } 68 69 if err := h.render(conf); err != nil { 70 return err 71 } 72 73 if h.Metrics != nil { 74 var b bytes.Buffer 75 h.Metrics.WriteMetrics(&b) 76 77 h.Log.FEEDBACK.Printf("\nTemplate Metrics:\n\n") 78 h.Log.FEEDBACK.Print(b.String()) 79 h.Log.FEEDBACK.Println() 80 } 81 82 errorCount := h.Log.LogCountForLevel(jww.LevelError) 83 if errorCount > 0 { 84 return fmt.Errorf("logged %d error(s)", errorCount) 85 } 86 87 return nil 88 89 } 90 91 // Build lifecycle methods below. 92 // The order listed matches the order of execution. 93 94 func (h *HugoSites) init(config *BuildCfg) error { 95 96 for _, s := range h.Sites { 97 if s.PageCollections == nil { 98 s.PageCollections = newPageCollections() 99 } 100 } 101 102 if config.ResetState { 103 h.reset() 104 } 105 106 if config.CreateSitesFromConfig { 107 if err := h.createSitesFromConfig(); err != nil { 108 return err 109 } 110 } 111 112 return nil 113 } 114 115 func (h *HugoSites) initRebuild(config *BuildCfg) error { 116 if config.CreateSitesFromConfig { 117 return errors.New("Rebuild does not support 'CreateSitesFromConfig'.") 118 } 119 120 if config.ResetState { 121 return errors.New("Rebuild does not support 'ResetState'.") 122 } 123 124 if !h.running { 125 return errors.New("Rebuild called when not in watch mode") 126 } 127 128 if config.whatChanged.source { 129 // This is for the non-renderable content pages (rarely used, I guess). 130 // We could maybe detect if this is really needed, but it should be 131 // pretty fast. 132 h.TemplateHandler().RebuildClone() 133 } 134 135 for _, s := range h.Sites { 136 s.resetBuildState() 137 } 138 139 h.resetLogs() 140 helpers.InitLoggers() 141 142 return nil 143 } 144 145 func (h *HugoSites) process(config *BuildCfg, events ...fsnotify.Event) error { 146 // We should probably refactor the Site and pull up most of the logic from there to here, 147 // but that seems like a daunting task. 148 // So for now, if there are more than one site (language), 149 // we pre-process the first one, then configure all the sites based on that. 150 151 firstSite := h.Sites[0] 152 153 if len(events) > 0 { 154 // This is a rebuild 155 changed, err := firstSite.processPartial(events) 156 config.whatChanged = &changed 157 return err 158 } 159 160 return firstSite.process(*config) 161 162 } 163 164 func (h *HugoSites) assemble(config *BuildCfg) error { 165 if config.whatChanged.source { 166 for _, s := range h.Sites { 167 s.createTaxonomiesEntries() 168 } 169 } 170 171 // TODO(bep) we could probably wait and do this in one go later 172 h.setupTranslations() 173 174 if len(h.Sites) > 1 { 175 // The first is initialized during process; initialize the rest 176 for _, site := range h.Sites[1:] { 177 if err := site.initializeSiteInfo(); err != nil { 178 return err 179 } 180 } 181 } 182 183 if config.whatChanged.source { 184 for _, s := range h.Sites { 185 if err := s.buildSiteMeta(); err != nil { 186 return err 187 } 188 } 189 } 190 191 if err := h.createMissingPages(); err != nil { 192 return err 193 } 194 195 for _, s := range h.Sites { 196 for _, pages := range []Pages{s.Pages, s.headlessPages} { 197 for _, p := range pages { 198 // May have been set in front matter 199 if len(p.outputFormats) == 0 { 200 p.outputFormats = s.outputFormats[p.Kind] 201 } 202 203 if p.headless { 204 // headless = 1 output format only 205 p.outputFormats = p.outputFormats[:1] 206 } 207 for _, r := range p.Resources.ByType(pageResourceType) { 208 r.(*Page).outputFormats = p.outputFormats 209 } 210 211 if err := p.initPaths(); err != nil { 212 return err 213 } 214 215 } 216 } 217 s.assembleMenus() 218 s.refreshPageCaches() 219 s.setupSitePages() 220 } 221 222 if err := h.assignMissingTranslations(); err != nil { 223 return err 224 } 225 226 return nil 227 228 } 229 230 func (h *HugoSites) render(config *BuildCfg) error { 231 for _, s := range h.Sites { 232 s.initRenderFormats() 233 } 234 235 for _, s := range h.Sites { 236 for i, rf := range s.renderFormats { 237 for _, s2 := range h.Sites { 238 // We render site by site, but since the content is lazily rendered 239 // and a site can "borrow" content from other sites, every site 240 // needs this set. 241 s2.rc = &siteRenderingContext{Format: rf} 242 243 isRenderingSite := s == s2 244 245 if err := s2.preparePagesForRender(isRenderingSite && i == 0); err != nil { 246 return err 247 } 248 249 } 250 251 if !config.SkipRender { 252 if err := s.render(config, i); err != nil { 253 return err 254 } 255 } 256 } 257 } 258 259 if !config.SkipRender { 260 if err := h.renderCrossSitesArtifacts(); err != nil { 261 return err 262 } 263 } 264 265 return nil 266 }