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

     1  // Copyright 2019 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package git
     5  
     6  import (
     7  	"bytes"
     8  	"context"
     9  	"os"
    10  	"path/filepath"
    11  	"strings"
    12  
    13  	"code.gitea.io/gitea/modules/log"
    14  	"code.gitea.io/gitea/modules/util"
    15  )
    16  
    17  // ReadTreeToIndex reads a treeish to the index
    18  func (repo *Repository) ReadTreeToIndex(treeish string, indexFilename ...string) error {
    19  	if len(treeish) != SHAFullLength {
    20  		res, _, err := NewCommand(repo.Ctx, "rev-parse", "--verify").AddDynamicArguments(treeish).RunStdString(&RunOpts{Dir: repo.Path})
    21  		if err != nil {
    22  			return err
    23  		}
    24  		if len(res) > 0 {
    25  			treeish = res[:len(res)-1]
    26  		}
    27  	}
    28  	id, err := NewIDFromString(treeish)
    29  	if err != nil {
    30  		return err
    31  	}
    32  	return repo.readTreeToIndex(id, indexFilename...)
    33  }
    34  
    35  func (repo *Repository) readTreeToIndex(id SHA1, indexFilename ...string) error {
    36  	var env []string
    37  	if len(indexFilename) > 0 {
    38  		env = append(os.Environ(), "GIT_INDEX_FILE="+indexFilename[0])
    39  	}
    40  	_, _, err := NewCommand(repo.Ctx, "read-tree").AddDynamicArguments(id.String()).RunStdString(&RunOpts{Dir: repo.Path, Env: env})
    41  	if err != nil {
    42  		return err
    43  	}
    44  	return nil
    45  }
    46  
    47  // ReadTreeToTemporaryIndex reads a treeish to a temporary index file
    48  func (repo *Repository) ReadTreeToTemporaryIndex(treeish string) (filename, tmpDir string, cancel context.CancelFunc, err error) {
    49  	tmpDir, err = os.MkdirTemp("", "index")
    50  	if err != nil {
    51  		return
    52  	}
    53  
    54  	filename = filepath.Join(tmpDir, ".tmp-index")
    55  	cancel = func() {
    56  		err := util.RemoveAll(tmpDir)
    57  		if err != nil {
    58  			log.Error("failed to remove tmp index file: %v", err)
    59  		}
    60  	}
    61  	err = repo.ReadTreeToIndex(treeish, filename)
    62  	if err != nil {
    63  		defer cancel()
    64  		return "", "", func() {}, err
    65  	}
    66  	return filename, tmpDir, cancel, err
    67  }
    68  
    69  // EmptyIndex empties the index
    70  func (repo *Repository) EmptyIndex() error {
    71  	_, _, err := NewCommand(repo.Ctx, "read-tree", "--empty").RunStdString(&RunOpts{Dir: repo.Path})
    72  	return err
    73  }
    74  
    75  // LsFiles checks if the given filenames are in the index
    76  func (repo *Repository) LsFiles(filenames ...string) ([]string, error) {
    77  	cmd := NewCommand(repo.Ctx, "ls-files", "-z").AddDashesAndList(filenames...)
    78  	res, _, err := cmd.RunStdBytes(&RunOpts{Dir: repo.Path})
    79  	if err != nil {
    80  		return nil, err
    81  	}
    82  	filelist := make([]string, 0, len(filenames))
    83  	for _, line := range bytes.Split(res, []byte{'\000'}) {
    84  		filelist = append(filelist, string(line))
    85  	}
    86  
    87  	return filelist, err
    88  }
    89  
    90  // RemoveFilesFromIndex removes given filenames from the index - it does not check whether they are present.
    91  func (repo *Repository) RemoveFilesFromIndex(filenames ...string) error {
    92  	cmd := NewCommand(repo.Ctx, "update-index", "--remove", "-z", "--index-info")
    93  	stdout := new(bytes.Buffer)
    94  	stderr := new(bytes.Buffer)
    95  	buffer := new(bytes.Buffer)
    96  	for _, file := range filenames {
    97  		if file != "" {
    98  			buffer.WriteString("0 0000000000000000000000000000000000000000\t")
    99  			buffer.WriteString(file)
   100  			buffer.WriteByte('\000')
   101  		}
   102  	}
   103  	return cmd.Run(&RunOpts{
   104  		Dir:    repo.Path,
   105  		Stdin:  bytes.NewReader(buffer.Bytes()),
   106  		Stdout: stdout,
   107  		Stderr: stderr,
   108  	})
   109  }
   110  
   111  // AddObjectToIndex adds the provided object hash to the index at the provided filename
   112  func (repo *Repository) AddObjectToIndex(mode string, object SHA1, filename string) error {
   113  	cmd := NewCommand(repo.Ctx, "update-index", "--add", "--replace", "--cacheinfo").AddDynamicArguments(mode, object.String(), filename)
   114  	_, _, err := cmd.RunStdString(&RunOpts{Dir: repo.Path})
   115  	return err
   116  }
   117  
   118  // WriteTree writes the current index as a tree to the object db and returns its hash
   119  func (repo *Repository) WriteTree() (*Tree, error) {
   120  	stdout, _, runErr := NewCommand(repo.Ctx, "write-tree").RunStdString(&RunOpts{Dir: repo.Path})
   121  	if runErr != nil {
   122  		return nil, runErr
   123  	}
   124  	id, err := NewIDFromString(strings.TrimSpace(stdout))
   125  	if err != nil {
   126  		return nil, err
   127  	}
   128  	return NewTree(repo, id), nil
   129  }