81 lines
1.7 KiB
Go
81 lines
1.7 KiB
Go
package sync
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
)
|
|
|
|
// BlobDir returns the path to .verstak/blobs/ inside the vault.
|
|
func BlobDir(vaultRoot string) string {
|
|
return filepath.Join(vaultRoot, ".verstak", "blobs")
|
|
}
|
|
|
|
// BlobPath returns the on-disk path for a SHA-256 hash.
|
|
func BlobPath(blobsDir, shaHex string) string {
|
|
return filepath.Join(blobsDir, shaHex[:2], shaHex[2:4], shaHex)
|
|
}
|
|
|
|
// HashFile computes SHA-256 of a file.
|
|
func HashFile(path string) (string, error) {
|
|
f, err := os.Open(path)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer f.Close()
|
|
h := sha256.New()
|
|
if _, err := io.Copy(h, f); err != nil {
|
|
return "", err
|
|
}
|
|
return hex.EncodeToString(h.Sum(nil)), nil
|
|
}
|
|
|
|
// HashBytes computes SHA-256 of byte data.
|
|
func HashBytes(data []byte) string {
|
|
h := sha256.Sum256(data)
|
|
return hex.EncodeToString(h[:])
|
|
}
|
|
|
|
// StoreBlob copies a file into the blob store, returns its SHA-256.
|
|
func StoreBlob(blobsDir, srcPath string) (string, error) {
|
|
shaHex, err := HashFile(srcPath)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
dest := BlobPath(blobsDir, shaHex)
|
|
if _, err := os.Stat(dest); err == nil {
|
|
return shaHex, nil // already exists
|
|
}
|
|
if err := os.MkdirAll(filepath.Dir(dest), 0750); err != nil {
|
|
return "", err
|
|
}
|
|
src, err := os.Open(srcPath)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer src.Close()
|
|
|
|
dst, err := os.Create(dest)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer dst.Close()
|
|
|
|
if _, err := io.Copy(dst, src); err != nil {
|
|
return "", err
|
|
}
|
|
_ = dst.Sync()
|
|
return shaHex, nil
|
|
}
|
|
|
|
// ReadBlob reads a blob by SHA-256 hash.
|
|
func ReadBlob(blobsDir, shaHex string) ([]byte, error) {
|
|
return os.ReadFile(BlobPath(blobsDir, shaHex))
|
|
}
|
|
|
|
// Ensure the package compiles without unused errors.
|
|
var _ = fmt.Sprintf
|