From d578b71d61ee8131e8abf7f538b93d8c6cc6fe6d Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 27 Mar 2019 17:33:00 +0800 Subject: move code.gitea.io/git to code.gitea.io/gitea/modules/git (#6364) * move code.gitea.io/git to code.gitea.io/gitea/modules/git * fix imports * fix fmt * fix misspell * remove wrong tests data * fix unit tests * fix tests * fix tests * fix tests * fix tests * fix tests * enable Debug to trace the failure tests * fix tests * fix tests * fix tests * fix tests * fix tests * comment commit count tests since git clone depth is 50 * fix tests * update from code.gitea.io/git * revert change to makefile --- modules/git/blob.go | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 modules/git/blob.go (limited to 'modules/git/blob.go') diff --git a/modules/git/blob.go b/modules/git/blob.go new file mode 100644 index 0000000000..a6e392eeb5 --- /dev/null +++ b/modules/git/blob.go @@ -0,0 +1,73 @@ +// Copyright 2015 The Gogs Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package git + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "os" + "os/exec" +) + +// Blob represents a Git object. +type Blob struct { + repo *Repository + *TreeEntry +} + +// Data gets content of blob all at once and wrap it as io.Reader. +// This can be very slow and memory consuming for huge content. +func (b *Blob) Data() (io.Reader, error) { + stdout := new(bytes.Buffer) + stderr := new(bytes.Buffer) + + // Preallocate memory to save ~50% memory usage on big files. + stdout.Grow(int(b.Size() + 2048)) + + if err := b.DataPipeline(stdout, stderr); err != nil { + return nil, concatenateError(err, stderr.String()) + } + return stdout, nil +} + +// DataPipeline gets content of blob and write the result or error to stdout or stderr +func (b *Blob) DataPipeline(stdout, stderr io.Writer) error { + return NewCommand("show", b.ID.String()).RunInDirPipeline(b.repo.Path, stdout, stderr) +} + +type cmdReadCloser struct { + cmd *exec.Cmd + stdout io.Reader +} + +func (c cmdReadCloser) Read(p []byte) (int, error) { + return c.stdout.Read(p) +} + +func (c cmdReadCloser) Close() error { + io.Copy(ioutil.Discard, c.stdout) + return c.cmd.Wait() +} + +// 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) { + cmd := exec.Command("git", "show", b.ID.String()) + cmd.Dir = b.repo.Path + cmd.Stderr = os.Stderr + + stdout, err := cmd.StdoutPipe() + if err != nil { + return nil, fmt.Errorf("StdoutPipe: %v", err) + } + + if err = cmd.Start(); err != nil { + return nil, fmt.Errorf("Start: %v", err) + } + + return cmdReadCloser{stdout: stdout, cmd: cmd}, nil +} -- cgit v1.2.3