aboutsummaryrefslogtreecommitdiffstats
path: root/modules/lfs
diff options
context:
space:
mode:
Diffstat (limited to 'modules/lfs')
-rw-r--r--modules/lfs/http_client.go10
-rw-r--r--modules/lfs/http_client_test.go8
-rw-r--r--modules/lfs/pointer.go13
-rw-r--r--modules/lfs/pointer_scanner_gogit.go2
-rw-r--r--modules/lfs/transferadapter_test.go9
5 files changed, 22 insertions, 20 deletions
diff --git a/modules/lfs/http_client.go b/modules/lfs/http_client.go
index 3acd23b8f7..4b51193846 100644
--- a/modules/lfs/http_client.go
+++ b/modules/lfs/http_client.go
@@ -70,12 +70,16 @@ func (c *HTTPClient) transferNames() []string {
func (c *HTTPClient) batch(ctx context.Context, operation string, objects []Pointer) (*BatchResponse, error) {
log.Trace("BATCH operation with objects: %v", objects)
- url := fmt.Sprintf("%s/objects/batch", c.endpoint)
+ url := c.endpoint + "/objects/batch"
+ // Original: In some lfs server implementations, they require the ref attribute. #32838
// `ref` is an "optional object describing the server ref that the objects belong to"
- // but some (incorrect) lfs servers require it, so maybe adding an empty ref here doesn't break the correct ones.
+ // but some (incorrect) lfs servers like aliyun require it, so maybe adding an empty ref here doesn't break the correct ones.
// https://github.com/git-lfs/git-lfs/blob/a32a02b44bf8a511aa14f047627c49e1a7fd5021/docs/api/batch.md?plain=1#L37
- request := &BatchRequest{operation, c.transferNames(), &Reference{}, objects}
+ //
+ // UPDATE: it can't use "empty ref" here because it breaks others like https://github.com/go-gitea/gitea/issues/33453
+ request := &BatchRequest{operation, c.transferNames(), nil, objects}
+
payload := new(bytes.Buffer)
err := json.NewEncoder(payload).Encode(request)
if err != nil {
diff --git a/modules/lfs/http_client_test.go b/modules/lfs/http_client_test.go
index aa7e3c45c4..179bcdb29a 100644
--- a/modules/lfs/http_client_test.go
+++ b/modules/lfs/http_client_test.go
@@ -31,7 +31,7 @@ func (a *DummyTransferAdapter) Name() string {
}
func (a *DummyTransferAdapter) Download(ctx context.Context, l *Link) (io.ReadCloser, error) {
- return io.NopCloser(bytes.NewBufferString("dummy")), nil
+ return io.NopCloser(strings.NewReader("dummy")), nil
}
func (a *DummyTransferAdapter) Upload(ctx context.Context, l *Link, p Pointer, r io.Reader) error {
@@ -49,7 +49,7 @@ func lfsTestRoundtripHandler(req *http.Request) *http.Response {
if strings.Contains(url, "status-not-ok") {
return &http.Response{StatusCode: http.StatusBadRequest}
} else if strings.Contains(url, "invalid-json-response") {
- return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(bytes.NewBufferString("invalid json"))}
+ return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(strings.NewReader("invalid json"))}
} else if strings.Contains(url, "valid-batch-request-download") {
batchResponse = &BatchResponse{
Transfer: "dummy",
@@ -248,7 +248,7 @@ func TestHTTPClientDownload(t *testing.T) {
},
}
- err := client.Download(context.Background(), []Pointer{p}, func(p Pointer, content io.ReadCloser, objectError error) error {
+ err := client.Download(t.Context(), []Pointer{p}, func(p Pointer, content io.ReadCloser, objectError error) error {
if objectError != nil {
return objectError
}
@@ -348,7 +348,7 @@ func TestHTTPClientUpload(t *testing.T) {
},
}
- err := client.Upload(context.Background(), []Pointer{p}, func(p Pointer, objectError error) (io.ReadCloser, error) {
+ err := client.Upload(t.Context(), []Pointer{p}, func(p Pointer, objectError error) (io.ReadCloser, error) {
return io.NopCloser(new(bytes.Buffer)), objectError
})
if c.expectedError != "" {
diff --git a/modules/lfs/pointer.go b/modules/lfs/pointer.go
index ebde20f826..9c95613057 100644
--- a/modules/lfs/pointer.go
+++ b/modules/lfs/pointer.go
@@ -15,15 +15,13 @@ import (
"strings"
)
+// spec: https://github.com/git-lfs/git-lfs/blob/master/docs/spec.md
const (
- blobSizeCutoff = 1024
+ MetaFileMaxSize = 1024 // spec says the maximum size of a pointer file must be smaller than 1024
- // MetaFileIdentifier is the string appearing at the first line of LFS pointer files.
- // https://github.com/git-lfs/git-lfs/blob/master/docs/spec.md
- MetaFileIdentifier = "version https://git-lfs.github.com/spec/v1"
+ MetaFileIdentifier = "version https://git-lfs.github.com/spec/v1" // the first line of a pointer file
- // MetaFileOidPrefix appears in LFS pointer files on a line before the sha256 hash.
- MetaFileOidPrefix = "oid sha256:"
+ MetaFileOidPrefix = "oid sha256:" // spec says the only supported hash is sha256 at the moment
)
var (
@@ -39,7 +37,7 @@ var (
// ReadPointer tries to read LFS pointer data from the reader
func ReadPointer(reader io.Reader) (Pointer, error) {
- buf := make([]byte, blobSizeCutoff)
+ buf := make([]byte, MetaFileMaxSize)
n, err := io.ReadFull(reader, buf)
if err != nil && err != io.ErrUnexpectedEOF {
return Pointer{}, err
@@ -65,6 +63,7 @@ func ReadPointerFromBuffer(buf []byte) (Pointer, error) {
return p, ErrInvalidStructure
}
+ // spec says "key/value pairs MUST be sorted alphabetically in ascending order (version is exception and must be the first)"
oid := strings.TrimPrefix(splitLines[1], MetaFileOidPrefix)
if len(oid) != 64 || !oidPattern.MatchString(oid) {
return p, ErrInvalidOIDFormat
diff --git a/modules/lfs/pointer_scanner_gogit.go b/modules/lfs/pointer_scanner_gogit.go
index f4302c23bc..e153b8e24e 100644
--- a/modules/lfs/pointer_scanner_gogit.go
+++ b/modules/lfs/pointer_scanner_gogit.go
@@ -31,7 +31,7 @@ func SearchPointerBlobs(ctx context.Context, repo *git.Repository, pointerChan c
default:
}
- if blob.Size > blobSizeCutoff {
+ if blob.Size > MetaFileMaxSize {
return nil
}
diff --git a/modules/lfs/transferadapter_test.go b/modules/lfs/transferadapter_test.go
index a430b71a5f..ef72d76db4 100644
--- a/modules/lfs/transferadapter_test.go
+++ b/modules/lfs/transferadapter_test.go
@@ -5,7 +5,6 @@ package lfs
import (
"bytes"
- "context"
"io"
"net/http"
"strings"
@@ -33,7 +32,7 @@ func TestBasicTransferAdapter(t *testing.T) {
if strings.Contains(url, "download-request") {
assert.Equal(t, "GET", req.Method)
- return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(bytes.NewBufferString("dummy"))}
+ return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(strings.NewReader("dummy"))}
} else if strings.Contains(url, "upload-request") {
assert.Equal(t, "PUT", req.Method)
assert.Equal(t, "application/octet-stream", req.Header.Get("Content-Type"))
@@ -94,7 +93,7 @@ func TestBasicTransferAdapter(t *testing.T) {
}
for n, c := range cases {
- _, err := a.Download(context.Background(), c.link)
+ _, err := a.Download(t.Context(), c.link)
if len(c.expectederror) > 0 {
assert.Contains(t, err.Error(), c.expectederror, "case %d: '%s' should contain '%s'", n, err.Error(), c.expectederror)
} else {
@@ -127,7 +126,7 @@ func TestBasicTransferAdapter(t *testing.T) {
}
for n, c := range cases {
- err := a.Upload(context.Background(), c.link, p, bytes.NewBufferString("dummy"))
+ err := a.Upload(t.Context(), c.link, p, strings.NewReader("dummy"))
if len(c.expectederror) > 0 {
assert.Contains(t, err.Error(), c.expectederror, "case %d: '%s' should contain '%s'", n, err.Error(), c.expectederror)
} else {
@@ -160,7 +159,7 @@ func TestBasicTransferAdapter(t *testing.T) {
}
for n, c := range cases {
- err := a.Verify(context.Background(), c.link, p)
+ err := a.Verify(t.Context(), c.link, p)
if len(c.expectederror) > 0 {
assert.Contains(t, err.Error(), c.expectederror, "case %d: '%s' should contain '%s'", n, err.Error(), c.expectederror)
} else {