You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

repo_index.go 4.0KB

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