Fix every finding surfaced by the canonical .golangci.yml with golangci-lint v2.12.2 (refs #61), behavior-preserving throughout: - err113: dynamic errors replaced with package-level sentinels and %w wrapping; direct comparisons converted to errors.Is - goprintffuncname: printf-style helpers renamed with an f suffix (ui.Writer message methods, cli.ReportErrorf, database.Fatalf, vaultik stdoutf) and all call sites updated - revive: stuttering type names renamed (blob.Handler, blob.WithReader, blob.ChunkPosition, storage.URL, storage.Info), doc comments added, unused parameters blanked, package comments added - contextcheck/noctx: ctx threaded through blob.Packer (AddChunk/Flush/FinalizeBlob/PackChunks) and scanner call sites; context-aware exec and sql variants used - funlen/cyclop/gocognit/nestif/dupl: oversized or duplicated functions split into focused helpers across production and test code - paralleltest/tparallel/thelper/usetesting/testpackage: tests parallelized where safe (global log.Initialize kept in the serial phase), helpers marked, t.TempDir adopted, external test packages where only exported API is used - gosec: integer conversions clamped or justified, header timeouts added, remaining findings suppressed with per-site justifications - mnd/goconst/lll/wsl_v5/nlreturn/noinlineerr/errcheck and other mechanical findings fixed directly Remove the deprecated log.LogOptions alias (callers migrated to log.Options). make check is green.
89 lines
2.0 KiB
Go
89 lines
2.0 KiB
Go
// Package blobgen implements the blob data pipeline: streaming zstd
|
|
// compression, age encryption, and SHA256 content hashing for blob
|
|
// creation, plus the matching decrypt/decompress/verify reader.
|
|
package blobgen
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"io"
|
|
)
|
|
|
|
// CompressResult contains the results of compression
|
|
type CompressResult struct {
|
|
Data []byte
|
|
UncompressedSize int64
|
|
CompressedSize int64
|
|
SHA256 string
|
|
}
|
|
|
|
// CompressData compresses and encrypts data, returning the result with hash
|
|
func CompressData(
|
|
data []byte, compressionLevel int, recipients []string,
|
|
) (*CompressResult, error) {
|
|
var buf bytes.Buffer
|
|
|
|
// Create writer
|
|
w, err := NewWriter(&buf, compressionLevel, recipients)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("creating writer: %w", err)
|
|
}
|
|
|
|
// Write data
|
|
_, err = w.Write(data)
|
|
if err != nil {
|
|
_ = w.Close()
|
|
|
|
return nil, fmt.Errorf("writing data: %w", err)
|
|
}
|
|
|
|
// Close to flush
|
|
err = w.Close()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("closing writer: %w", err)
|
|
}
|
|
|
|
return &CompressResult{
|
|
Data: buf.Bytes(),
|
|
UncompressedSize: int64(len(data)),
|
|
CompressedSize: int64(buf.Len()),
|
|
SHA256: hex.EncodeToString(w.Sum256()),
|
|
}, nil
|
|
}
|
|
|
|
// CompressStream compresses and encrypts from reader to writer, returning
|
|
// the number of uncompressed bytes written and the content hash.
|
|
func CompressStream(
|
|
dst io.Writer, src io.Reader, compressionLevel int, recipients []string,
|
|
) (int64, string, error) {
|
|
// Create writer
|
|
w, err := NewWriter(dst, compressionLevel, recipients)
|
|
if err != nil {
|
|
return 0, "", fmt.Errorf("creating writer: %w", err)
|
|
}
|
|
|
|
closed := false
|
|
defer func() {
|
|
if !closed {
|
|
_ = w.Close()
|
|
}
|
|
}()
|
|
|
|
// Copy data
|
|
_, err = io.Copy(w, src)
|
|
if err != nil {
|
|
return 0, "", fmt.Errorf("copying data: %w", err)
|
|
}
|
|
|
|
// Close to flush
|
|
err = w.Close()
|
|
if err != nil {
|
|
return 0, "", fmt.Errorf("closing writer: %w", err)
|
|
}
|
|
|
|
closed = true
|
|
|
|
return w.BytesWritten(), hex.EncodeToString(w.Sum256()), nil
|
|
}
|