gitea源码

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // Copyright 2020 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. //go:build !gogit
  4. package git
  5. import (
  6. "bufio"
  7. "errors"
  8. "io"
  9. "strings"
  10. "code.gitea.io/gitea/modules/git/gitcmd"
  11. "code.gitea.io/gitea/modules/log"
  12. )
  13. // ResolveReference resolves a name to a reference
  14. func (repo *Repository) ResolveReference(name string) (string, error) {
  15. stdout, _, err := gitcmd.NewCommand("show-ref", "--hash").AddDynamicArguments(name).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
  16. if err != nil {
  17. if strings.Contains(err.Error(), "not a valid ref") {
  18. return "", ErrNotExist{name, ""}
  19. }
  20. return "", err
  21. }
  22. stdout = strings.TrimSpace(stdout)
  23. if stdout == "" {
  24. return "", ErrNotExist{name, ""}
  25. }
  26. return stdout, nil
  27. }
  28. // GetRefCommitID returns the last commit ID string of given reference (branch or tag).
  29. func (repo *Repository) GetRefCommitID(name string) (string, error) {
  30. wr, rd, cancel, err := repo.CatFileBatchCheck(repo.Ctx)
  31. if err != nil {
  32. return "", err
  33. }
  34. defer cancel()
  35. _, err = wr.Write([]byte(name + "\n"))
  36. if err != nil {
  37. return "", err
  38. }
  39. shaBs, _, _, err := ReadBatchLine(rd)
  40. if IsErrNotExist(err) {
  41. return "", ErrNotExist{name, ""}
  42. }
  43. return string(shaBs), nil
  44. }
  45. // IsCommitExist returns true if given commit exists in current repository.
  46. func (repo *Repository) IsCommitExist(name string) bool {
  47. if err := ensureValidGitRepository(repo.Ctx, repo.Path); err != nil {
  48. log.Error("IsCommitExist: %v", err)
  49. return false
  50. }
  51. _, _, err := gitcmd.NewCommand("cat-file", "-e").AddDynamicArguments(name).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
  52. return err == nil
  53. }
  54. func (repo *Repository) getCommit(id ObjectID) (*Commit, error) {
  55. wr, rd, cancel, err := repo.CatFileBatch(repo.Ctx)
  56. if err != nil {
  57. return nil, err
  58. }
  59. defer cancel()
  60. _, _ = wr.Write([]byte(id.String() + "\n"))
  61. return repo.getCommitFromBatchReader(wr, rd, id)
  62. }
  63. func (repo *Repository) getCommitFromBatchReader(wr WriteCloserError, rd *bufio.Reader, id ObjectID) (*Commit, error) {
  64. _, typ, size, err := ReadBatchLine(rd)
  65. if err != nil {
  66. if errors.Is(err, io.EOF) || IsErrNotExist(err) {
  67. return nil, ErrNotExist{ID: id.String()}
  68. }
  69. return nil, err
  70. }
  71. switch typ {
  72. case "missing":
  73. return nil, ErrNotExist{ID: id.String()}
  74. case "tag":
  75. // then we need to parse the tag
  76. // and load the commit
  77. data, err := io.ReadAll(io.LimitReader(rd, size))
  78. if err != nil {
  79. return nil, err
  80. }
  81. _, err = rd.Discard(1)
  82. if err != nil {
  83. return nil, err
  84. }
  85. tag, err := parseTagData(id.Type(), data)
  86. if err != nil {
  87. return nil, err
  88. }
  89. if _, err := wr.Write([]byte(tag.Object.String() + "\n")); err != nil {
  90. return nil, err
  91. }
  92. commit, err := repo.getCommitFromBatchReader(wr, rd, tag.Object)
  93. if err != nil {
  94. return nil, err
  95. }
  96. return commit, nil
  97. case "commit":
  98. commit, err := CommitFromReader(repo, id, io.LimitReader(rd, size))
  99. if err != nil {
  100. return nil, err
  101. }
  102. _, err = rd.Discard(1)
  103. if err != nil {
  104. return nil, err
  105. }
  106. return commit, nil
  107. default:
  108. log.Debug("Unknown typ: %s", typ)
  109. if err := DiscardFull(rd, size+1); err != nil {
  110. return nil, err
  111. }
  112. return nil, ErrNotExist{
  113. ID: id.String(),
  114. }
  115. }
  116. }
  117. // ConvertToGitID returns a GitHash object from a potential ID string
  118. func (repo *Repository) ConvertToGitID(commitID string) (ObjectID, error) {
  119. objectFormat, err := repo.GetObjectFormat()
  120. if err != nil {
  121. return nil, err
  122. }
  123. if len(commitID) == objectFormat.FullLength() && objectFormat.IsValid(commitID) {
  124. ID, err := NewIDFromString(commitID)
  125. if err == nil {
  126. return ID, nil
  127. }
  128. }
  129. wr, rd, cancel, err := repo.CatFileBatchCheck(repo.Ctx)
  130. if err != nil {
  131. return nil, err
  132. }
  133. defer cancel()
  134. _, err = wr.Write([]byte(commitID + "\n"))
  135. if err != nil {
  136. return nil, err
  137. }
  138. sha, _, _, err := ReadBatchLine(rd)
  139. if err != nil {
  140. if IsErrNotExist(err) {
  141. return nil, ErrNotExist{commitID, ""}
  142. }
  143. return nil, err
  144. }
  145. return MustIDFromString(string(sha)), nil
  146. }