aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/site
diff options
context:
space:
mode:
authorLeonardo Bishop <me@leonardobishop.net>2025-07-08 23:26:05 +0100
committerLeonardo Bishop <me@leonardobishop.net>2025-07-08 23:26:05 +0100
commitcdb75d3fcbc9339b897f8c6ff4d69a577f017393 (patch)
tree5e757cd236540c2cea9874c1bc09f19548db05d5 /pkg/site
parentb56101f1a11552067f594679a497ebd4cf7427d4 (diff)
Rewrite in Go
Diffstat (limited to 'pkg/site')
-rw-r--r--pkg/site/fs.go36
-rw-r--r--pkg/site/site.go150
2 files changed, 186 insertions, 0 deletions
diff --git a/pkg/site/fs.go b/pkg/site/fs.go
new file mode 100644
index 0000000..a77da63
--- /dev/null
+++ b/pkg/site/fs.go
@@ -0,0 +1,36 @@
+package site
+
+import (
+ "net/http"
+ "path/filepath"
+)
+
+type siteFS struct {
+ fs http.FileSystem
+}
+
+func (sfs siteFS) Open(path string) (http.File, error) {
+ f, err := sfs.fs.Open(path)
+ if err != nil {
+ return nil, err
+ }
+
+ s, err := f.Stat()
+ if err != nil {
+ return nil, err
+ }
+
+ if s.IsDir() {
+ index := filepath.Join(path, "index.html")
+ if _, err := sfs.fs.Open(index); err != nil {
+ closeErr := f.Close()
+ if closeErr != nil {
+ return nil, closeErr
+ }
+
+ return nil, err
+ }
+ }
+
+ return f, nil
+}
diff --git a/pkg/site/site.go b/pkg/site/site.go
new file mode 100644
index 0000000..37dca5f
--- /dev/null
+++ b/pkg/site/site.go
@@ -0,0 +1,150 @@
+package site
+
+import (
+ "errors"
+ "fmt"
+ "net/http"
+ "os"
+ "path"
+ "path/filepath"
+ "regexp"
+ "time"
+
+ "github.com/LMBishop/scrapbook/pkg/config"
+)
+
+const versionRegex = "[0-9]{4}_[0-9]{2}_[0-9]{2}_[0-9]{2}_[0-9]{2}_[0-9]{2}"
+const timeFormat = "2006_01_02_15_04_05"
+
+type Site struct {
+ Name string
+ Path string
+ Handler http.Handler
+ SiteConfig *config.SiteConfig
+}
+
+func NewSite(name string, dir string, config *config.SiteConfig) *Site {
+ var site Site
+ site.Name = name
+ site.Path = dir
+ site.SiteConfig = config
+ site.Handler = http.FileServer(siteFS{http.Dir(path.Join(dir, "default"))})
+ return &site
+}
+
+func CreateNewSite(name string, baseDir string, host string) (*Site, error) {
+ dir := path.Join(baseDir, name)
+ _, err := os.Stat(dir)
+ if err == nil {
+ return nil, fmt.Errorf("site with name already exists: %s", name)
+ }
+ if !errors.Is(err, os.ErrNotExist) {
+ return nil, fmt.Errorf("failed to check site uniqueness: %w", err)
+ }
+
+ cfg := &config.SiteConfig{
+ Host: host,
+ }
+ site := NewSite(name, dir, cfg)
+
+ err = os.Mkdir(dir, 0o755)
+ if err != nil {
+ return nil, fmt.Errorf("failed to create directory: %w", err)
+ }
+
+ err = config.WriteSiteConfig(path.Join(dir, "site.toml"), cfg)
+ if err != nil {
+ return nil, fmt.Errorf("failed to write site config: %w", err)
+ }
+
+ return site, nil
+}
+
+func (s *Site) GetCurrentPath() string {
+ return path.Join(s.Path, "default")
+}
+
+func (s *Site) GetCurrentVersion() (string, error) {
+ dir, err := filepath.EvalSymlinks(path.Join(s.Path, "default"))
+ if err != nil {
+ return "", err
+ }
+
+ return filepath.Base(dir), nil
+}
+
+func (s *Site) UpdateVersion(newVersion string) error {
+ newVersionPath := path.Join(s.Path, newVersion)
+
+ stat, err := os.Stat(newVersionPath)
+ if err != nil {
+ return err
+ }
+
+ if !stat.IsDir() {
+ return fmt.Errorf("not a directory: %s", newVersionPath)
+ }
+
+ currentVersionPath := s.GetCurrentPath()
+
+ os.Remove(currentVersionPath)
+ return os.Symlink(newVersion, currentVersionPath)
+}
+
+func (s *Site) GetAllVersions() ([]string, error) {
+ entries, err := os.ReadDir(s.Path)
+
+ if err != nil {
+ return nil, err
+ }
+
+ var versions []string
+
+ for _, entry := range entries {
+ if !entry.IsDir() {
+ continue
+ }
+
+ match, err := regexp.MatchString(versionRegex, entry.Name())
+ if err != nil {
+ return nil, err
+ }
+
+ if match {
+ versions = append(versions, entry.Name())
+ }
+ }
+
+ return versions, err
+}
+
+func (s *Site) CreateNewVersion() (string, error) {
+ t := time.Now()
+ dirName := t.Format("2006_01_02_15_04_05")
+ newVersionDir := path.Join(s.Path, dirName)
+
+ err := os.MkdirAll(newVersionDir, os.FileMode(0o755))
+ if err != nil {
+ return "", err
+ }
+
+ return dirName, nil
+}
+
+func (s *Site) EvaluateSiteStatus() string {
+ stat, err := os.Stat(s.GetCurrentPath())
+ if err != nil || !stat.IsDir() {
+ return "inactive"
+ }
+
+ return "live"
+}
+
+func (s *Site) EvaluateSiteStatusReason() string {
+ stat, err := os.Stat(s.GetCurrentPath())
+ if err != nil || !stat.IsDir() {
+ return "This site is inacessible because no version is active"
+ }
+
+ return "This site is live"
+}