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.

commit_reader.go 2.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. // Copyright 2020 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package git
  4. import (
  5. "bufio"
  6. "bytes"
  7. "io"
  8. "strings"
  9. )
  10. // CommitFromReader will generate a Commit from a provided reader
  11. // We need this to interpret commits from cat-file or cat-file --batch
  12. //
  13. // If used as part of a cat-file --batch stream you need to limit the reader to the correct size
  14. func CommitFromReader(gitRepo *Repository, sha SHA1, reader io.Reader) (*Commit, error) {
  15. commit := &Commit{
  16. ID: sha,
  17. Author: &Signature{},
  18. Committer: &Signature{},
  19. }
  20. payloadSB := new(strings.Builder)
  21. signatureSB := new(strings.Builder)
  22. messageSB := new(strings.Builder)
  23. message := false
  24. pgpsig := false
  25. bufReader, ok := reader.(*bufio.Reader)
  26. if !ok {
  27. bufReader = bufio.NewReader(reader)
  28. }
  29. readLoop:
  30. for {
  31. line, err := bufReader.ReadBytes('\n')
  32. if err != nil {
  33. if err == io.EOF {
  34. if message {
  35. _, _ = messageSB.Write(line)
  36. }
  37. _, _ = payloadSB.Write(line)
  38. break readLoop
  39. }
  40. return nil, err
  41. }
  42. if pgpsig {
  43. if len(line) > 0 && line[0] == ' ' {
  44. _, _ = signatureSB.Write(line[1:])
  45. continue
  46. } else {
  47. pgpsig = false
  48. }
  49. }
  50. if !message {
  51. // This is probably not correct but is copied from go-gits interpretation...
  52. trimmed := bytes.TrimSpace(line)
  53. if len(trimmed) == 0 {
  54. message = true
  55. _, _ = payloadSB.Write(line)
  56. continue
  57. }
  58. split := bytes.SplitN(trimmed, []byte{' '}, 2)
  59. var data []byte
  60. if len(split) > 1 {
  61. data = split[1]
  62. }
  63. switch string(split[0]) {
  64. case "tree":
  65. commit.Tree = *NewTree(gitRepo, MustIDFromString(string(data)))
  66. _, _ = payloadSB.Write(line)
  67. case "parent":
  68. commit.Parents = append(commit.Parents, MustIDFromString(string(data)))
  69. _, _ = payloadSB.Write(line)
  70. case "author":
  71. commit.Author = &Signature{}
  72. commit.Author.Decode(data)
  73. _, _ = payloadSB.Write(line)
  74. case "committer":
  75. commit.Committer = &Signature{}
  76. commit.Committer.Decode(data)
  77. _, _ = payloadSB.Write(line)
  78. case "gpgsig":
  79. _, _ = signatureSB.Write(data)
  80. _ = signatureSB.WriteByte('\n')
  81. pgpsig = true
  82. }
  83. } else {
  84. _, _ = messageSB.Write(line)
  85. _, _ = payloadSB.Write(line)
  86. }
  87. }
  88. commit.CommitMessage = messageSB.String()
  89. commit.Signature = &CommitGPGSignature{
  90. Signature: signatureSB.String(),
  91. Payload: payloadSB.String(),
  92. }
  93. if len(commit.Signature.Signature) == 0 {
  94. commit.Signature = nil
  95. }
  96. return commit, nil
  97. }