mirror of
https://codeberg.org/git-pages/git-pages.git
synced 2026-05-29 18:40:47 +00:00
137 lines
3.0 KiB
Go
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
|
|
}
|