| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- // Copyright 2019 The Gitea Authors. All rights reserved.
- // SPDX-License-Identifier: MIT
-
- package git
-
- import (
- "bytes"
- "context"
- "os"
- "path/filepath"
- "strings"
-
- "code.gitea.io/gitea/modules/git/gitcmd"
- "code.gitea.io/gitea/modules/setting"
- )
-
- // ReadTreeToIndex reads a treeish to the index
- func (repo *Repository) ReadTreeToIndex(treeish string, indexFilename ...string) error {
- objectFormat, err := repo.GetObjectFormat()
- if err != nil {
- return err
- }
-
- if len(treeish) != objectFormat.FullLength() {
- res, _, err := gitcmd.NewCommand("rev-parse", "--verify").AddDynamicArguments(treeish).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
- if err != nil {
- return err
- }
- if len(res) > 0 {
- treeish = res[:len(res)-1]
- }
- }
- id, err := NewIDFromString(treeish)
- if err != nil {
- return err
- }
- return repo.readTreeToIndex(id, indexFilename...)
- }
-
- func (repo *Repository) readTreeToIndex(id ObjectID, indexFilename ...string) error {
- var env []string
- if len(indexFilename) > 0 {
- env = append(os.Environ(), "GIT_INDEX_FILE="+indexFilename[0])
- }
- _, _, err := gitcmd.NewCommand("read-tree").AddDynamicArguments(id.String()).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path, Env: env})
- if err != nil {
- return err
- }
- return nil
- }
-
- // ReadTreeToTemporaryIndex reads a treeish to a temporary index file
- func (repo *Repository) ReadTreeToTemporaryIndex(treeish string) (tmpIndexFilename, tmpDir string, cancel context.CancelFunc, err error) {
- defer func() {
- // if error happens and there is a cancel function, do clean up
- if err != nil && cancel != nil {
- cancel()
- cancel = nil
- }
- }()
-
- tmpDir, cancel, err = setting.AppDataTempDir("git-repo-content").MkdirTempRandom("index")
- if err != nil {
- return "", "", nil, err
- }
-
- tmpIndexFilename = filepath.Join(tmpDir, ".tmp-index")
-
- err = repo.ReadTreeToIndex(treeish, tmpIndexFilename)
- if err != nil {
- return "", "", cancel, err
- }
- return tmpIndexFilename, tmpDir, cancel, nil
- }
-
- // EmptyIndex empties the index
- func (repo *Repository) EmptyIndex() error {
- _, _, err := gitcmd.NewCommand("read-tree", "--empty").RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
- return err
- }
-
- // LsFiles checks if the given filenames are in the index
- func (repo *Repository) LsFiles(filenames ...string) ([]string, error) {
- cmd := gitcmd.NewCommand("ls-files", "-z").AddDashesAndList(filenames...)
- res, _, err := cmd.RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
- if err != nil {
- return nil, err
- }
- filelist := make([]string, 0, len(filenames))
- for line := range bytes.SplitSeq(res, []byte{'\000'}) {
- filelist = append(filelist, string(line))
- }
-
- return filelist, err
- }
-
- // RemoveFilesFromIndex removes given filenames from the index - it does not check whether they are present.
- func (repo *Repository) RemoveFilesFromIndex(filenames ...string) error {
- objectFormat, err := repo.GetObjectFormat()
- if err != nil {
- return err
- }
- cmd := gitcmd.NewCommand("update-index", "--remove", "-z", "--index-info")
- stdout := new(bytes.Buffer)
- stderr := new(bytes.Buffer)
- buffer := new(bytes.Buffer)
- for _, file := range filenames {
- if file != "" {
- // using format: mode SP type SP sha1 TAB path
- buffer.WriteString("0 blob " + objectFormat.EmptyObjectID().String() + "\t" + file + "\000")
- }
- }
- return cmd.Run(repo.Ctx, &gitcmd.RunOpts{
- Dir: repo.Path,
- Stdin: bytes.NewReader(buffer.Bytes()),
- Stdout: stdout,
- Stderr: stderr,
- })
- }
-
- type IndexObjectInfo struct {
- Mode string
- Object ObjectID
- Filename string
- }
-
- // AddObjectsToIndex adds the provided object hashes to the index at the provided filenames
- func (repo *Repository) AddObjectsToIndex(objects ...IndexObjectInfo) error {
- cmd := gitcmd.NewCommand("update-index", "--add", "--replace", "-z", "--index-info")
- stdout := new(bytes.Buffer)
- stderr := new(bytes.Buffer)
- buffer := new(bytes.Buffer)
- for _, object := range objects {
- // using format: mode SP type SP sha1 TAB path
- buffer.WriteString(object.Mode + " blob " + object.Object.String() + "\t" + object.Filename + "\000")
- }
- return cmd.Run(repo.Ctx, &gitcmd.RunOpts{
- Dir: repo.Path,
- Stdin: bytes.NewReader(buffer.Bytes()),
- Stdout: stdout,
- Stderr: stderr,
- })
- }
-
- // AddObjectToIndex adds the provided object hash to the index at the provided filename
- func (repo *Repository) AddObjectToIndex(mode string, object ObjectID, filename string) error {
- return repo.AddObjectsToIndex(IndexObjectInfo{Mode: mode, Object: object, Filename: filename})
- }
-
- // WriteTree writes the current index as a tree to the object db and returns its hash
- func (repo *Repository) WriteTree() (*Tree, error) {
- stdout, _, runErr := gitcmd.NewCommand("write-tree").RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
- if runErr != nil {
- return nil, runErr
- }
- id, err := NewIDFromString(strings.TrimSpace(stdout))
- if err != nil {
- return nil, err
- }
- return NewTree(repo, id), nil
- }
|