summaryrefslogtreecommitdiffstats
path: root/modules/git/blob_nogogit.go
diff options
context:
space:
mode:
Diffstat (limited to 'modules/git/blob_nogogit.go')
-rw-r--r--modules/git/blob_nogogit.go118
1 files changed, 118 insertions, 0 deletions
diff --git a/modules/git/blob_nogogit.go b/modules/git/blob_nogogit.go
new file mode 100644
index 00000000..945a6bc4
--- /dev/null
+++ b/modules/git/blob_nogogit.go
@@ -0,0 +1,118 @@
+// Copyright 2020 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+//go:build !gogit
+
+package git
+
+import (
+ "bufio"
+ "bytes"
+ "io"
+
+ "code.gitea.io/gitea/modules/log"
+)
+
+// Blob represents a Git object.
+type Blob struct {
+ ID ObjectID
+
+ gotSize bool
+ size int64
+ name string
+ repo *Repository
+}
+
+// DataAsync gets a ReadCloser for the contents of a blob without reading it all.
+// Calling the Close function on the result will discard all unread output.
+func (b *Blob) DataAsync() (io.ReadCloser, error) {
+ wr, rd, cancel := b.repo.CatFileBatch(b.repo.Ctx)
+
+ _, err := wr.Write([]byte(b.ID.String() + "\n"))
+ if err != nil {
+ cancel()
+ return nil, err
+ }
+ _, _, size, err := ReadBatchLine(rd)
+ if err != nil {
+ cancel()
+ return nil, err
+ }
+ b.gotSize = true
+ b.size = size
+
+ if size < 4096 {
+ bs, err := io.ReadAll(io.LimitReader(rd, size))
+ defer cancel()
+ if err != nil {
+ return nil, err
+ }
+ _, err = rd.Discard(1)
+ return io.NopCloser(bytes.NewReader(bs)), err
+ }
+
+ return &blobReader{
+ rd: rd,
+ n: size,
+ cancel: cancel,
+ }, nil
+}
+
+// Size returns the uncompressed size of the blob
+func (b *Blob) Size() int64 {
+ if b.gotSize {
+ return b.size
+ }
+
+ wr, rd, cancel := b.repo.CatFileBatchCheck(b.repo.Ctx)
+ defer cancel()
+ _, err := wr.Write([]byte(b.ID.String() + "\n"))
+ if err != nil {
+ log.Debug("error whilst reading size for %s in %s. Error: %v", b.ID.String(), b.repo.Path, err)
+ return 0
+ }
+ _, _, b.size, err = ReadBatchLine(rd)
+ if err != nil {
+ log.Debug("error whilst reading size for %s in %s. Error: %v", b.ID.String(), b.repo.Path, err)
+ return 0
+ }
+
+ b.gotSize = true
+
+ return b.size
+}
+
+type blobReader struct {
+ rd *bufio.Reader
+ n int64
+ cancel func()
+}
+
+func (b *blobReader) Read(p []byte) (n int, err error) {
+ if b.n <= 0 {
+ return 0, io.EOF
+ }
+ if int64(len(p)) > b.n {
+ p = p[0:b.n]
+ }
+ n, err = b.rd.Read(p)
+ b.n -= int64(n)
+ return n, err
+}
+
+// Close implements io.Closer
+func (b *blobReader) Close() error {
+ if b.rd == nil {
+ return nil
+ }
+
+ defer b.cancel()
+
+ if err := DiscardFull(b.rd, b.n+1); err != nil {
+ return err
+ }
+
+ b.rd = nil
+
+ return nil
+}