mirror of
https://github.com/git-pkgs/proxy.git
synced 2026-09-16 07:42:05 -04:00
97 lines
2.2 KiB
Go
97 lines
2.2 KiB
Go
|
|
package storage
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"crypto/sha256"
|
||
|
|
"encoding/hex"
|
||
|
|
"errors"
|
||
|
|
"io"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
gcstorage "github.com/git-pkgs/gcs"
|
||
|
|
)
|
||
|
|
|
||
|
|
// GCS adapts a Google Cloud Storage bucket to Storage.
|
||
|
|
type GCS struct {
|
||
|
|
bucket *gcstorage.Bucket
|
||
|
|
url string
|
||
|
|
}
|
||
|
|
|
||
|
|
// OpenGCS opens a Google Cloud Storage bucket from a gs:// URL.
|
||
|
|
func OpenGCS(ctx context.Context, urlStr string) (*GCS, error) {
|
||
|
|
bucket, err := gcstorage.OpenBucket(ctx, urlStr)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
return &GCS{bucket: bucket, url: urlStr}, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (g *GCS) Store(ctx context.Context, path string, r io.Reader) (int64, string, error) {
|
||
|
|
h := sha256.New()
|
||
|
|
size, err := g.bucket.Write(ctx, path, io.TeeReader(r, h))
|
||
|
|
if err != nil {
|
||
|
|
return 0, "", err
|
||
|
|
}
|
||
|
|
return size, hex.EncodeToString(h.Sum(nil)), nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (g *GCS) Open(ctx context.Context, path string) (io.ReadCloser, error) {
|
||
|
|
r, err := g.bucket.Open(ctx, path)
|
||
|
|
if errors.Is(err, gcstorage.ErrNotFound) {
|
||
|
|
return nil, ErrNotFound
|
||
|
|
}
|
||
|
|
return r, err
|
||
|
|
}
|
||
|
|
|
||
|
|
func (g *GCS) Exists(ctx context.Context, path string) (bool, error) {
|
||
|
|
return g.bucket.Exists(ctx, path)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (g *GCS) Delete(ctx context.Context, path string) error {
|
||
|
|
return g.bucket.Delete(ctx, path)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (g *GCS) Size(ctx context.Context, path string) (int64, error) {
|
||
|
|
size, err := g.bucket.Size(ctx, path)
|
||
|
|
if errors.Is(err, gcstorage.ErrNotFound) {
|
||
|
|
return 0, ErrNotFound
|
||
|
|
}
|
||
|
|
return size, err
|
||
|
|
}
|
||
|
|
|
||
|
|
func (g *GCS) SignedURL(ctx context.Context, path string, expiry time.Duration) (string, error) {
|
||
|
|
u, err := g.bucket.SignedURL(ctx, path, expiry)
|
||
|
|
if errors.Is(err, gcstorage.ErrSignedURLUnsupported) {
|
||
|
|
return "", ErrSignedURLUnsupported
|
||
|
|
}
|
||
|
|
return u, err
|
||
|
|
}
|
||
|
|
|
||
|
|
func (g *GCS) UsedSpace(ctx context.Context) (int64, error) {
|
||
|
|
return g.bucket.UsedSpace(ctx)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (g *GCS) ListPrefix(ctx context.Context, prefix string) ([]ObjectInfo, error) {
|
||
|
|
objects, err := g.bucket.ListPrefix(ctx, prefix)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
|
||
|
|
result := make([]ObjectInfo, 0, len(objects))
|
||
|
|
for _, object := range objects {
|
||
|
|
result = append(result, ObjectInfo{
|
||
|
|
Path: object.Name,
|
||
|
|
Size: object.Size,
|
||
|
|
ModTime: object.ModTime,
|
||
|
|
})
|
||
|
|
}
|
||
|
|
return result, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (g *GCS) Close() error {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (g *GCS) URL() string {
|
||
|
|
return g.url
|
||
|
|
}
|