gitea源码

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  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. "io"
  8. "strings"
  9. "code.gitea.io/gitea/modules/git/gitcmd"
  10. )
  11. // GetRefsFiltered returns all references of the repository that matches patterm exactly or starting with.
  12. func (repo *Repository) GetRefsFiltered(pattern string) ([]*Reference, error) {
  13. stdoutReader, stdoutWriter := io.Pipe()
  14. defer func() {
  15. _ = stdoutReader.Close()
  16. _ = stdoutWriter.Close()
  17. }()
  18. go func() {
  19. stderrBuilder := &strings.Builder{}
  20. err := gitcmd.NewCommand("for-each-ref").Run(repo.Ctx, &gitcmd.RunOpts{
  21. Dir: repo.Path,
  22. Stdout: stdoutWriter,
  23. Stderr: stderrBuilder,
  24. })
  25. if err != nil {
  26. _ = stdoutWriter.CloseWithError(gitcmd.ConcatenateError(err, stderrBuilder.String()))
  27. } else {
  28. _ = stdoutWriter.Close()
  29. }
  30. }()
  31. refs := make([]*Reference, 0)
  32. bufReader := bufio.NewReader(stdoutReader)
  33. for {
  34. // The output of for-each-ref is simply a list:
  35. // <sha> SP <type> TAB <ref> LF
  36. sha, err := bufReader.ReadString(' ')
  37. if err == io.EOF {
  38. break
  39. }
  40. if err != nil {
  41. return nil, err
  42. }
  43. sha = sha[:len(sha)-1]
  44. typ, err := bufReader.ReadString('\t')
  45. if err == io.EOF {
  46. // This should not happen, but we'll tolerate it
  47. break
  48. }
  49. if err != nil {
  50. return nil, err
  51. }
  52. typ = typ[:len(typ)-1]
  53. refName, err := bufReader.ReadString('\n')
  54. if err == io.EOF {
  55. // This should not happen, but we'll tolerate it
  56. break
  57. }
  58. if err != nil {
  59. return nil, err
  60. }
  61. refName = refName[:len(refName)-1]
  62. // refName cannot be HEAD but can be remotes or stash
  63. if strings.HasPrefix(refName, RemotePrefix) || refName == "/refs/stash" {
  64. continue
  65. }
  66. if pattern == "" || strings.HasPrefix(refName, pattern) {
  67. r := &Reference{
  68. Name: refName,
  69. Object: MustIDFromString(sha),
  70. Type: typ,
  71. repo: repo,
  72. }
  73. refs = append(refs, r)
  74. }
  75. }
  76. return refs, nil
  77. }