summaryrefslogtreecommitdiffstats
path: root/modules/util
diff options
context:
space:
mode:
authoryp05327 <576951401@qq.com>2023-06-13 18:02:25 +0900
committerGitHub <noreply@github.com>2023-06-13 09:02:25 +0000
commit22a39bb961daedccb08e47cb4cf83b2d4ef72108 (patch)
tree5a98a90df3293ea75754db5e64d4d7f5f43be9f5 /modules/util
parenta583c5630629fa664e77bad62afe95c0d9fb0a5e (diff)
downloadgitea-22a39bb961daedccb08e47cb4cf83b2d4ef72108.tar.gz
gitea-22a39bb961daedccb08e47cb4cf83b2d4ef72108.zip
Fix profile render when the README.md size is larger than 1024 bytes (#25131)
Fixes https://github.com/go-gitea/gitea/issues/25094 `GetBlobContent` will only get the first 1024 bytes, if the README.md size is larger than 1024 bytes, We can not render the rest of them. After this fix, we should provide the limited size to read when call `GetBlobContent`. After: ![image](https://github.com/go-gitea/gitea/assets/18380374/22a42936-4cf8-40b4-a5c7-e384082beb0d) --------- Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Diffstat (limited to 'modules/util')
-rw-r--r--modules/util/io.go39
-rw-r--r--modules/util/io_test.go66
2 files changed, 104 insertions, 1 deletions
diff --git a/modules/util/io.go b/modules/util/io.go
index 69b1d63145..1559b019a0 100644
--- a/modules/util/io.go
+++ b/modules/util/io.go
@@ -4,13 +4,14 @@
package util
import (
+ "bytes"
"errors"
"io"
)
// ReadAtMost reads at most len(buf) bytes from r into buf.
// It returns the number of bytes copied. n is only less than len(buf) if r provides fewer bytes.
-// If EOF occurs while reading, err will be nil.
+// If EOF or ErrUnexpectedEOF occurs while reading, err will be nil.
func ReadAtMost(r io.Reader, buf []byte) (n int, err error) {
n, err = io.ReadFull(r, buf)
if err == io.EOF || err == io.ErrUnexpectedEOF {
@@ -19,6 +20,42 @@ func ReadAtMost(r io.Reader, buf []byte) (n int, err error) {
return n, err
}
+// ReadWithLimit reads at most "limit" bytes from r into buf.
+// If EOF or ErrUnexpectedEOF occurs while reading, err will be nil.
+func ReadWithLimit(r io.Reader, n int) (buf []byte, err error) {
+ return readWithLimit(r, 1024, n)
+}
+
+func readWithLimit(r io.Reader, batch, limit int) ([]byte, error) {
+ if limit <= batch {
+ buf := make([]byte, limit)
+ n, err := ReadAtMost(r, buf)
+ if err != nil {
+ return nil, err
+ }
+ return buf[:n], nil
+ }
+ res := bytes.NewBuffer(make([]byte, 0, batch))
+ bufFix := make([]byte, batch)
+ eof := false
+ for res.Len() < limit && !eof {
+ bufTmp := bufFix
+ if res.Len()+batch > limit {
+ bufTmp = bufFix[:limit-res.Len()]
+ }
+ n, err := io.ReadFull(r, bufTmp)
+ if err == io.EOF || err == io.ErrUnexpectedEOF {
+ eof = true
+ } else if err != nil {
+ return nil, err
+ }
+ if _, err = res.Write(bufTmp[:n]); err != nil {
+ return nil, err
+ }
+ }
+ return res.Bytes(), nil
+}
+
// ErrNotEmpty is an error reported when there is a non-empty reader
var ErrNotEmpty = errors.New("not-empty")
diff --git a/modules/util/io_test.go b/modules/util/io_test.go
new file mode 100644
index 0000000000..275575463a
--- /dev/null
+++ b/modules/util/io_test.go
@@ -0,0 +1,66 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package util
+
+import (
+ "bytes"
+ "errors"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+type readerWithError struct {
+ buf *bytes.Buffer
+}
+
+func (r *readerWithError) Read(p []byte) (n int, err error) {
+ if r.buf.Len() < 2 {
+ return 0, errors.New("test error")
+ }
+ return r.buf.Read(p)
+}
+
+func TestReadWithLimit(t *testing.T) {
+ bs := []byte("0123456789abcdef")
+
+ // normal test
+ buf, err := readWithLimit(bytes.NewBuffer(bs), 5, 2)
+ assert.NoError(t, err)
+ assert.Equal(t, []byte("01"), buf)
+
+ buf, err = readWithLimit(bytes.NewBuffer(bs), 5, 5)
+ assert.NoError(t, err)
+ assert.Equal(t, []byte("01234"), buf)
+
+ buf, err = readWithLimit(bytes.NewBuffer(bs), 5, 6)
+ assert.NoError(t, err)
+ assert.Equal(t, []byte("012345"), buf)
+
+ buf, err = readWithLimit(bytes.NewBuffer(bs), 5, len(bs))
+ assert.NoError(t, err)
+ assert.Equal(t, []byte("0123456789abcdef"), buf)
+
+ buf, err = readWithLimit(bytes.NewBuffer(bs), 5, 100)
+ assert.NoError(t, err)
+ assert.Equal(t, []byte("0123456789abcdef"), buf)
+
+ // test with error
+ buf, err = readWithLimit(&readerWithError{bytes.NewBuffer(bs)}, 5, 10)
+ assert.NoError(t, err)
+ assert.Equal(t, []byte("0123456789"), buf)
+
+ buf, err = readWithLimit(&readerWithError{bytes.NewBuffer(bs)}, 5, 100)
+ assert.ErrorContains(t, err, "test error")
+ assert.Empty(t, buf)
+
+ // test public function
+ buf, err = ReadWithLimit(bytes.NewBuffer(bs), 2)
+ assert.NoError(t, err)
+ assert.Equal(t, []byte("01"), buf)
+
+ buf, err = ReadWithLimit(bytes.NewBuffer(bs), 9999999)
+ assert.NoError(t, err)
+ assert.Equal(t, []byte("0123456789abcdef"), buf)
+}