Adding upstream version 3.10.8.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
37e9b6d587
commit
03bfe4079e
356 changed files with 28857 additions and 0 deletions
99
tree/f3/objects/objects.go
Normal file
99
tree/f3/objects/objects.go
Normal file
|
@ -0,0 +1,99 @@
|
|||
// 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{}
|
||||
}
|
68
tree/f3/objects/sha.go
Normal file
68
tree/f3/objects/sha.go
Normal file
|
@ -0,0 +1,68 @@
|
|||
// 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"
|
||||
"hash"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
options_http "code.forgejo.org/f3/gof3/v3/options/http"
|
||||
)
|
||||
|
||||
type SHASetter interface {
|
||||
SetSHA(sha string)
|
||||
}
|
||||
|
||||
func FuncReadURLAndSetSHA(newHTTPClient options_http.NewMigrationHTTPClientFun, url string, sha SHASetter) func() io.ReadCloser {
|
||||
return func() io.ReadCloser {
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
httpClient := newHTTPClient()
|
||||
resp, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("while downloading %s %w", url, err))
|
||||
}
|
||||
|
||||
return FuncReadAndSetSHA(resp.Body, sha)()
|
||||
}
|
||||
}
|
||||
|
||||
type readAndSetSHA struct {
|
||||
reader io.Reader
|
||||
closer io.Closer
|
||||
sha SHASetter
|
||||
hasher hash.Hash
|
||||
}
|
||||
|
||||
func (o *readAndSetSHA) Read(b []byte) (n int, err error) {
|
||||
return o.reader.Read(b)
|
||||
}
|
||||
|
||||
func (o *readAndSetSHA) Close() error {
|
||||
o.sha.SetSHA(hex.EncodeToString(o.hasher.Sum(nil)))
|
||||
return o.closer.Close()
|
||||
}
|
||||
|
||||
func newReadAndSetSHA(reader io.ReadCloser, sha SHASetter) *readAndSetSHA {
|
||||
hasher := sha256.New()
|
||||
return &readAndSetSHA{
|
||||
reader: io.TeeReader(reader, hasher),
|
||||
closer: reader,
|
||||
sha: sha,
|
||||
hasher: hasher,
|
||||
}
|
||||
}
|
||||
|
||||
func FuncReadAndSetSHA(reader io.ReadCloser, sha SHASetter) func() io.ReadCloser {
|
||||
return func() io.ReadCloser {
|
||||
return newReadAndSetSHA(reader, sha)
|
||||
}
|
||||
}
|
35
tree/f3/objects/sha_test.go
Normal file
35
tree/f3/objects/sha_test.go
Normal file
|
@ -0,0 +1,35 @@
|
|||
// Copyright Earl Warren <contact@earl-warren.org>
|
||||
// Copyright Loïc Dachary <loic@dachary.org>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package objects
|
||||
|
||||
import (
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type sha string
|
||||
|
||||
func (o *sha) SetSHA(s string) {
|
||||
*o = sha(s)
|
||||
}
|
||||
|
||||
func (o *sha) GetSHA() string {
|
||||
return string(*o)
|
||||
}
|
||||
|
||||
func Test_FuncReadAndSetSHA(t *testing.T) {
|
||||
content := "CONTENT"
|
||||
r := strings.NewReader(content)
|
||||
s := new(sha)
|
||||
f := FuncReadAndSetSHA(io.NopCloser(r), s)()
|
||||
c, err := io.ReadAll(f)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.Close())
|
||||
require.Equal(t, "65f23e22a9bfedda96929b3cfcb8b6d2fdd34a2e877ddb81f45d79ab05710e12", s.GetSHA())
|
||||
require.Equal(t, content, string(c))
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue