193 lines
4.4 KiB
Go
193 lines
4.4 KiB
Go
package sitebuilder
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"lmika.dev/lmika/hugo-cms/models"
|
|
"lmika.dev/lmika/hugo-cms/providers/bus"
|
|
"lmika.dev/lmika/hugo-cms/providers/db"
|
|
"lmika.dev/lmika/hugo-cms/providers/git"
|
|
"lmika.dev/lmika/hugo-cms/providers/hugo"
|
|
"lmika.dev/lmika/hugo-cms/providers/netlify"
|
|
"lmika.dev/lmika/hugo-cms/providers/themes"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
)
|
|
|
|
type Service struct {
|
|
db *db.DB
|
|
themes *themes.Provider
|
|
git *git.Provider
|
|
hugo *hugo.Provider
|
|
netlify *netlify.Provider
|
|
bus *bus.Bus
|
|
}
|
|
|
|
func New(
|
|
db *db.DB,
|
|
themes *themes.Provider,
|
|
git *git.Provider,
|
|
hugo *hugo.Provider,
|
|
netlify *netlify.Provider,
|
|
bus *bus.Bus,
|
|
) *Service {
|
|
return &Service{
|
|
db: db,
|
|
themes: themes,
|
|
git: git,
|
|
hugo: hugo,
|
|
netlify: netlify,
|
|
bus: bus,
|
|
}
|
|
}
|
|
|
|
func (s *Service) CreateNewSite(site models.Site) models.Job {
|
|
return models.Job{
|
|
Do: func(ctx context.Context) error {
|
|
s.signalSiteBuildingStarted(ctx, site)
|
|
defer s.signalSiteBuildingFinished(ctx, site)
|
|
|
|
return s.createSite(ctx, site)
|
|
},
|
|
}
|
|
}
|
|
|
|
func (s *Service) RebuildSite(oldSite, newSite models.Site) models.Job {
|
|
return models.Job{
|
|
Do: func(ctx context.Context) error {
|
|
s.signalSiteBuildingStarted(ctx, newSite)
|
|
defer s.signalSiteBuildingFinished(ctx, newSite)
|
|
|
|
return s.rebuildSite(ctx, oldSite, newSite)
|
|
},
|
|
}
|
|
}
|
|
|
|
func (s *Service) RebuildSiteContent(oldSite, newSite models.Site) models.Job {
|
|
return models.Job{
|
|
Do: func(ctx context.Context) error {
|
|
s.signalSiteBuildingStarted(ctx, newSite)
|
|
defer s.signalSiteBuildingFinished(ctx, newSite)
|
|
|
|
return s.rebuildContent(ctx, oldSite, newSite)
|
|
},
|
|
}
|
|
}
|
|
|
|
func (s *Service) rebuildSite(ctx context.Context, oldSite, newSite models.Site) error {
|
|
// Teardown the existing site
|
|
siteDir := s.hugo.SiteStagingDir(oldSite, hugo.BaseSiteDir)
|
|
if err := os.RemoveAll(siteDir); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := s.createSite(ctx, newSite); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := s.writeAllContent(ctx, newSite); err != nil {
|
|
return err
|
|
}
|
|
|
|
return s.publish(ctx, newSite)
|
|
}
|
|
|
|
func (s *Service) rebuildContent(ctx context.Context, oldSite, newSite models.Site) error {
|
|
// Teardown the existing site
|
|
siteDir := s.hugo.SiteStagingDir(oldSite, hugo.ContentSiteDir)
|
|
if err := os.RemoveAll(siteDir); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := s.writeAllContent(ctx, newSite); err != nil {
|
|
return err
|
|
}
|
|
|
|
return s.publish(ctx, newSite)
|
|
}
|
|
|
|
func (s *Service) writeAllContent(ctx context.Context, newSite models.Site) error {
|
|
if err := s.writeAllPosts(ctx, newSite); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := s.writeAllPages(ctx, newSite); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *Service) fullRebuildNecessary(ctx context.Context, site models.Site) (bool, error) {
|
|
dirsMustExists := []string{
|
|
s.hugo.SiteStagingDir(site, hugo.BaseSiteDir),
|
|
s.hugo.SiteStagingDir(site, hugo.ThemeSiteDir),
|
|
s.hugo.SiteStagingDir(site, hugo.ContentSiteDir),
|
|
}
|
|
|
|
filesMustExists := []string{
|
|
filepath.Join(s.hugo.SiteStagingDir(site, hugo.BaseSiteDir), "hugo.yaml"),
|
|
}
|
|
|
|
for _, dir := range dirsMustExists {
|
|
if stat, err := os.Stat(dir); err != nil {
|
|
if errors.Is(err, os.ErrNotExist) {
|
|
return true, nil
|
|
} else {
|
|
return false, err
|
|
}
|
|
} else if !stat.IsDir() {
|
|
return true, nil
|
|
}
|
|
}
|
|
|
|
for _, file := range filesMustExists {
|
|
if _, err := os.Stat(file); err != nil {
|
|
if errors.Is(err, os.ErrNotExist) {
|
|
return true, nil
|
|
} else {
|
|
return false, err
|
|
}
|
|
}
|
|
}
|
|
return false, nil
|
|
}
|
|
|
|
func (s *Service) createSite(ctx context.Context, site models.Site) error {
|
|
themeMeta, ok := s.themes.Lookup(site.Theme)
|
|
if !ok {
|
|
return errors.New("theme not found")
|
|
}
|
|
|
|
// Build the site
|
|
log.Printf(" .. build")
|
|
if err := s.hugo.NewSite(ctx, site); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Setup the theme
|
|
log.Printf(" .. theme")
|
|
if err := s.git.Clone(ctx, themeMeta.URL, s.hugo.SiteStagingDir(site, hugo.ThemeSiteDir)); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := s.hugo.ReconfigureSite(ctx, false, "hugo", site); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := s.hugo.ReconfigureSite(ctx, true, "hugoPreview", site); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *Service) signalSiteBuildingStarted(ctx context.Context, site models.Site) {
|
|
s.bus.Fire(models.Event{Type: models.EventSiteBuildingStart, Data: site})
|
|
}
|
|
|
|
func (s *Service) signalSiteBuildingFinished(ctx context.Context, site models.Site) {
|
|
s.bus.Fire(models.Event{Type: models.EventSiteBuildingDone, Data: site})
|
|
}
|