code.gitea.io/gitea@v1.19.3/modules/git/pipeline/catfile.go (about)

     1  // Copyright 2019 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package pipeline
     5  
     6  import (
     7  	"bufio"
     8  	"bytes"
     9  	"context"
    10  	"fmt"
    11  	"io"
    12  	"strconv"
    13  	"strings"
    14  	"sync"
    15  
    16  	"code.gitea.io/gitea/modules/git"
    17  	"code.gitea.io/gitea/modules/log"
    18  )
    19  
    20  // CatFileBatchCheck runs cat-file with --batch-check
    21  func CatFileBatchCheck(ctx context.Context, shasToCheckReader *io.PipeReader, catFileCheckWriter *io.PipeWriter, wg *sync.WaitGroup, tmpBasePath string) {
    22  	defer wg.Done()
    23  	defer shasToCheckReader.Close()
    24  	defer catFileCheckWriter.Close()
    25  
    26  	stderr := new(bytes.Buffer)
    27  	var errbuf strings.Builder
    28  	cmd := git.NewCommand(ctx, "cat-file", "--batch-check")
    29  	if err := cmd.Run(&git.RunOpts{
    30  		Dir:    tmpBasePath,
    31  		Stdin:  shasToCheckReader,
    32  		Stdout: catFileCheckWriter,
    33  		Stderr: stderr,
    34  	}); err != nil {
    35  		_ = catFileCheckWriter.CloseWithError(fmt.Errorf("git cat-file --batch-check [%s]: %w - %s", tmpBasePath, err, errbuf.String()))
    36  	}
    37  }
    38  
    39  // CatFileBatchCheckAllObjects runs cat-file with --batch-check --batch-all
    40  func CatFileBatchCheckAllObjects(ctx context.Context, catFileCheckWriter *io.PipeWriter, wg *sync.WaitGroup, tmpBasePath string, errChan chan<- error) {
    41  	defer wg.Done()
    42  	defer catFileCheckWriter.Close()
    43  
    44  	stderr := new(bytes.Buffer)
    45  	var errbuf strings.Builder
    46  	cmd := git.NewCommand(ctx, "cat-file", "--batch-check", "--batch-all-objects")
    47  	if err := cmd.Run(&git.RunOpts{
    48  		Dir:    tmpBasePath,
    49  		Stdout: catFileCheckWriter,
    50  		Stderr: stderr,
    51  	}); err != nil {
    52  		log.Error("git cat-file --batch-check --batch-all-object [%s]: %v - %s", tmpBasePath, err, errbuf.String())
    53  		err = fmt.Errorf("git cat-file --batch-check --batch-all-object [%s]: %w - %s", tmpBasePath, err, errbuf.String())
    54  		_ = catFileCheckWriter.CloseWithError(err)
    55  		errChan <- err
    56  	}
    57  }
    58  
    59  // CatFileBatch runs cat-file --batch
    60  func CatFileBatch(ctx context.Context, shasToBatchReader *io.PipeReader, catFileBatchWriter *io.PipeWriter, wg *sync.WaitGroup, tmpBasePath string) {
    61  	defer wg.Done()
    62  	defer shasToBatchReader.Close()
    63  	defer catFileBatchWriter.Close()
    64  
    65  	stderr := new(bytes.Buffer)
    66  	var errbuf strings.Builder
    67  	if err := git.NewCommand(ctx, "cat-file", "--batch").Run(&git.RunOpts{
    68  		Dir:    tmpBasePath,
    69  		Stdout: catFileBatchWriter,
    70  		Stdin:  shasToBatchReader,
    71  		Stderr: stderr,
    72  	}); err != nil {
    73  		_ = shasToBatchReader.CloseWithError(fmt.Errorf("git rev-list [%s]: %w - %s", tmpBasePath, err, errbuf.String()))
    74  	}
    75  }
    76  
    77  // BlobsLessThan1024FromCatFileBatchCheck reads a pipeline from cat-file --batch-check and returns the blobs <1024 in size
    78  func BlobsLessThan1024FromCatFileBatchCheck(catFileCheckReader *io.PipeReader, shasToBatchWriter *io.PipeWriter, wg *sync.WaitGroup) {
    79  	defer wg.Done()
    80  	defer catFileCheckReader.Close()
    81  	scanner := bufio.NewScanner(catFileCheckReader)
    82  	defer func() {
    83  		_ = shasToBatchWriter.CloseWithError(scanner.Err())
    84  	}()
    85  	for scanner.Scan() {
    86  		line := scanner.Text()
    87  		if len(line) == 0 {
    88  			continue
    89  		}
    90  		fields := strings.Split(line, " ")
    91  		if len(fields) < 3 || fields[1] != "blob" {
    92  			continue
    93  		}
    94  		size, _ := strconv.Atoi(fields[2])
    95  		if size > 1024 {
    96  			continue
    97  		}
    98  		toWrite := []byte(fields[0] + "\n")
    99  		for len(toWrite) > 0 {
   100  			n, err := shasToBatchWriter.Write(toWrite)
   101  			if err != nil {
   102  				_ = catFileCheckReader.CloseWithError(err)
   103  				break
   104  			}
   105  			toWrite = toWrite[n:]
   106  		}
   107  	}
   108  }