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