Files
git-pages/src/update.go
2025-09-20 07:16:10 +00:00

132 lines
2.8 KiB
Go

package main
import (
"context"
"errors"
"fmt"
"io"
"log"
)
type UpdateOutcome int
const (
UpdateError UpdateOutcome = iota
UpdateTimeout
UpdateCreated
UpdateReplaced
UpdateDeleted
UpdateNoChange
)
type UpdateResult struct {
outcome UpdateOutcome
manifest *Manifest
err error
}
func Update(
webRoot string,
manifest *Manifest,
) UpdateResult {
var oldManifest, newManifest *Manifest
var err error
outcome := UpdateError
oldManifest, _ = backend.GetManifest(webRoot)
// log.Println("OLD", ManifestDebugJSON(oldManifest))
if IsManifestEmpty(manifest) {
newManifest, err = manifest, backend.DeleteManifest(webRoot)
// log.Println("NEW", ManifestDebugJSON(newManifest))
if err == nil {
if oldManifest == nil {
outcome = UpdateNoChange
} else {
outcome = UpdateDeleted
}
}
} else if err = PrepareManifest(manifest); err == nil {
newManifest, err = StoreManifest(webRoot, manifest)
// log.Println("NEW", ManifestDebugJSON(newManifest))
if err == nil {
if oldManifest == nil {
outcome = UpdateCreated
} else if CompareManifest(oldManifest, newManifest) {
outcome = UpdateNoChange
} else {
outcome = UpdateReplaced
}
}
}
if err == nil {
status := ""
switch outcome {
case UpdateCreated:
status = "created"
case UpdateReplaced:
status = "replaced"
case UpdateDeleted:
status = "deleted"
case UpdateNoChange:
status = "unchanged"
}
if newManifest.Commit != nil {
log.Printf("update %s ok: %s %s", webRoot, status, *newManifest.Commit)
} else {
log.Printf("update %s ok: %s", webRoot, status)
}
} else {
log.Printf("update %s err: %s", webRoot, err)
}
return UpdateResult{outcome, newManifest, err}
}
func UpdateFromRepository(
ctx context.Context,
webRoot string,
repoURL string,
branch string,
) UpdateResult {
log.Printf("update %s: %s %s\n", webRoot, repoURL, branch)
manifest, err := FetchRepository(ctx, repoURL, branch)
if errors.Is(err, context.DeadlineExceeded) {
return UpdateResult{UpdateTimeout, nil, fmt.Errorf("update timeout")}
} else if err != nil {
return UpdateResult{UpdateError, nil, err}
} else {
return Update(webRoot, manifest)
}
}
var errArchiveFormat = errors.New("unsupported archive format")
func UpdateFromArchive(
webRoot string,
contentType string,
reader io.Reader,
) UpdateResult {
var manifest *Manifest
var err error
switch contentType {
case "application/x-tar":
log.Printf("update %s: (tar)", webRoot)
manifest, err = ExtractTar(reader) // yellow? definitely yellow.
case "application/zip":
log.Printf("update %s: (zip)", webRoot)
manifest, err = ExtractZip(reader)
default:
err = errArchiveFormat
}
if err != nil {
log.Printf("update %s err: %s", webRoot, err)
return UpdateResult{UpdateError, nil, err}
} else {
return Update(webRoot, manifest)
}
}