1
0
Fork 0
golang-forgejo-f3-gof3/tree/f3/objects/objects.go
Daniel Baumann 03bfe4079e
Adding upstream version 3.10.8.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-05-18 09:37:23 +02:00

99 lines
1.7 KiB
Go

// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package objects
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"os"
"path/filepath"
"runtime"
)
type Interface interface {
Save(rc io.ReadCloser) (string, string)
}
type helper struct {
dir *string
}
func (o *helper) getDir() string {
if o.dir == nil {
dir, err := os.MkdirTemp("", "objectHelper")
if err != nil {
panic(err)
}
runtime.SetFinalizer(o, func(o *helper) {
err := os.RemoveAll(dir)
if err != nil {
panic(err)
}
})
o.dir = &dir
}
return *o.dir
}
func (o *helper) getPath(sha string) string {
return filepath.Join(o.getDir(), sha[0:2], sha[2:4], sha)
}
func (o *helper) Save(rc io.ReadCloser) (string, string) {
tempFile, err := os.CreateTemp("", "object")
if err != nil {
panic(err)
}
tempRemoved := false
defer func() {
if !tempRemoved {
_ = os.Remove(tempFile.Name())
}
}()
// reader
defer rc.Close()
// writer to file
f, err := os.OpenFile(tempFile.Name(), os.O_CREATE|os.O_RDWR, 0o644)
if err != nil {
panic(err)
}
defer f.Close()
// writer to sha256
h := sha256.New()
// copy reader to file & sha256
w := io.MultiWriter(f, h)
if _, err := io.Copy(w, rc); err != nil {
panic(fmt.Errorf("while copying object: %w", err))
}
// finalize writer to sha256
sha := hex.EncodeToString(h.Sum(nil))
// finalize writer to file
if err := tempFile.Close(); err != nil {
panic(err)
}
path := o.getPath(sha)
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
panic(err)
}
if err := os.Rename(tempFile.Name(), path); err != nil {
panic(err)
}
tempRemoved = true
return sha, path
}
func NewObjectsHelper() Interface {
return &helper{}
}