From cd1125a213d742b5a89e8b60f0c7aafef13b8783 Mon Sep 17 00:00:00 2001 From: Alan Pearce Date: Tue, 25 Jun 2024 17:07:47 +0200 Subject: fetch and build site on server start --- internal/server/server.go | 52 ++++++++++++++++++++++++++++--------- internal/vcs/repository.go | 65 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 12 deletions(-) create mode 100644 internal/vcs/repository.go (limited to 'internal') diff --git a/internal/server/server.go b/internal/server/server.go index 60b20d2..e75efd3 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -6,14 +6,17 @@ import ( "net" "net/http" "net/url" + "os" "slices" "time" "website/internal/builder" cfg "website/internal/config" "website/internal/log" + "website/internal/vcs" "website/internal/website" + "github.com/ardanlabs/conf/v3" "github.com/osdevisnot/sorvor/pkg/livereload" "github.com/pkg/errors" "golang.org/x/net/http2" @@ -72,8 +75,34 @@ func serverHeaderHandler(wrappedHandler http.Handler) http.Handler { }) } +func rebuild(builderConfig builder.IOConfig, config *cfg.Config) error { + r, err := builder.BuildSite(builderConfig) + if err != nil { + return errors.WithMessage(err, "could not build site") + } + updateCSPHashes(config, r) + + return nil +} + func New(runtimeConfig *Config) (*Server, error) { - var err error + if !runtimeConfig.Development { + vcsConfig := &vcs.Config{} + _, err := conf.Parse("", vcsConfig) + if err != nil { + return nil, err + } + _, err = vcs.CloneOrUpdate(vcsConfig) + if err != nil { + return nil, err + } + err = os.Chdir(vcsConfig.LocalPath) + if err != nil { + return nil, err + } + runtimeConfig.Root = "website" + } + config, err := cfg.GetConfig() if err != nil { return nil, errors.WithMessage(err, "error parsing configuration file") @@ -90,11 +119,7 @@ func New(runtimeConfig *Config) (*Server, error) { BaseURL: config.BaseURL, Development: true, } - r, err := builder.BuildSite(builderConfig) - if err != nil { - return nil, errors.WithMessage(err, "could not build site") - } - updateCSPHashes(config, r) + rebuild(builderConfig, config) liveReload := livereload.New() top.Handle("/_/reload", liveReload) @@ -118,13 +143,16 @@ func New(runtimeConfig *Config) (*Server, error) { return nil, errors.WithMessage(err, "could not add directory to file watcher") } go fw.Start(func(filename string) { - r, err := builder.BuildSite(builderConfig) - if err != nil { - log.Error("could not build site", "error", err) - } - updateCSPHashes(config, r) - liveReload.Reload() + rebuild(builderConfig, config) }) + } else { + builderConfig := builder.IOConfig{ + Source: "content", + Destination: runtimeConfig.Root, + BaseURL: config.BaseURL, + Development: false, + } + rebuild(builderConfig, config) } loggingMux := http.NewServeMux() diff --git a/internal/vcs/repository.go b/internal/vcs/repository.go new file mode 100644 index 0000000..cc9bdaa --- /dev/null +++ b/internal/vcs/repository.go @@ -0,0 +1,65 @@ +package vcs + +import ( + "os" + "website/internal/config" + + "github.com/go-git/go-git/v5" + gitc "github.com/go-git/go-git/v5/config" + "github.com/pkg/errors" +) + +type Config struct { + LocalPath string + RemoteURL config.URL + Branch string `conf:"default:main"` +} + +type Repository struct { + repo *git.Repository +} + +func CloneOrUpdate(cfg *Config) (*Repository, error) { + gr, err := git.PlainClone(cfg.LocalPath, false, &git.CloneOptions{ + URL: cfg.RemoteURL.String(), + Progress: os.Stdout, + }) + if err != nil { + if !errors.Is(err, git.ErrRepositoryAlreadyExists) { + return nil, err + } + gr, err = git.PlainOpen(cfg.LocalPath) + if err != nil { + return nil, err + } + repo := &Repository{ + repo: gr, + } + _, err := repo.Update(cfg) + if err != nil { + return nil, err + } + return repo, nil + } + + return &Repository{ + repo: gr, + }, nil +} + +func (r *Repository) Update(cfg *Config) (bool, error) { + err := r.repo.Fetch(&git.FetchOptions{ + RefSpecs: []gitc.RefSpec{ + gitc.RefSpec( + "+refs/heads/" + cfg.Branch + ":refs/remotes/origin/" + cfg.Branch, + ), + }, + }) + if err != nil { + if errors.Is(err, git.NoErrAlreadyUpToDate) { + return false, nil + } + return false, err + } + return true, nil +} -- cgit 1.4.1