github.com/gitbundle/modules@v0.0.0-20231025071548-85b91c5c3b01/git/pipeline/catfile.go (about)

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