Files
git-pages/src/collect.go
2026-03-25 04:55:34 +00:00

137 lines
3.0 KiB
Go

package git_pages
import (
"archive/tar"
"context"
"fmt"
"io"
)
type Flusher interface {
Flush() error
}
// Inverse of `ExtractTar`.
func CollectTar(
context context.Context, writer io.Writer, manifest *Manifest, metadata ManifestMetadata,
) (
err error,
) {
archive := tar.NewWriter(writer)
appendFile := func(header *tar.Header, data []byte, transform Transform) (err error) {
switch transform {
case Transform_Identity:
case Transform_Zstd:
data, err = zstdDecoder.DecodeAll(data, []byte{})
if err != nil {
return fmt.Errorf("zstd: %s: %w", header.Name, err)
}
default:
return fmt.Errorf("%s: unexpected transform", header.Name)
}
header.Size = int64(len(data))
err = archive.WriteHeader(header)
if err != nil {
return fmt.Errorf("tar: %w", err)
}
_, err = archive.Write(data)
if err != nil {
return fmt.Errorf("tar: %w", err)
}
return
}
for fileName, entry := range manifest.Contents {
var header tar.Header
if fileName == "" {
continue
}
header.Name = fileName
switch entry.GetType() {
case Type_Directory:
header.Typeflag = tar.TypeDir
header.Mode = 0755
header.ModTime = metadata.LastModified
err = appendFile(&header, nil, Transform_Identity)
case Type_InlineFile:
header.Typeflag = tar.TypeReg
header.Mode = 0644
header.ModTime = metadata.LastModified
err = appendFile(&header, entry.GetData(), entry.GetTransform())
case Type_ExternalFile:
var blobReader io.Reader
var blobMetadata BlobMetadata
var blobData []byte
blobReader, blobMetadata, err = backend.GetBlob(context, string(entry.Data))
if err != nil {
return
}
blobData, err = io.ReadAll(blobReader)
if err != nil {
return
}
header.Typeflag = tar.TypeReg
header.Mode = 0644
header.ModTime = blobMetadata.LastModified
err = appendFile(&header, blobData, entry.GetTransform())
case Type_Symlink:
header.Typeflag = tar.TypeSymlink
header.Mode = 0644
header.ModTime = metadata.LastModified
header.Linkname = string(entry.GetData())
err = archive.WriteHeader(&header)
if err != nil {
return fmt.Errorf("tar: %w", err)
}
default:
panic(fmt.Errorf("CollectTar encountered invalid entry: %v, %v",
entry.GetType(), entry.GetTransform()))
}
if err != nil {
return err
}
}
if redirects := CollectRedirectsFile(manifest); redirects != "" {
err = appendFile(&tar.Header{
Name: RedirectsFileName,
Typeflag: tar.TypeReg,
Mode: 0644,
ModTime: metadata.LastModified,
}, []byte(redirects), Transform_Identity)
if err != nil {
return err
}
}
if headers := CollectHeadersFile(manifest); headers != "" {
err = appendFile(&tar.Header{
Name: HeadersFileName,
Typeflag: tar.TypeReg,
Mode: 0644,
ModTime: metadata.LastModified,
}, []byte(headers), Transform_Identity)
if err != nil {
return err
}
}
err = archive.Flush()
if err != nil {
return fmt.Errorf("tar: %w", err)
}
flusher, ok := writer.(Flusher)
if ok {
err = flusher.Flush()
}
return err
}