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