gitea源码

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // Copyright 2018 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. //go:build !gogit
  4. package git
  5. import (
  6. "bufio"
  7. "bytes"
  8. "fmt"
  9. "io"
  10. "code.gitea.io/gitea/modules/log"
  11. )
  12. // ParseTreeEntries parses the output of a `git ls-tree -l` command.
  13. func ParseTreeEntries(data []byte) ([]*TreeEntry, error) {
  14. return parseTreeEntries(data, nil)
  15. }
  16. // parseTreeEntries FIXME this function's design is not right, it should not make the caller read all data into memory
  17. func parseTreeEntries(data []byte, ptree *Tree) ([]*TreeEntry, error) {
  18. entries := make([]*TreeEntry, 0, bytes.Count(data, []byte{'\n'})+1)
  19. for pos := 0; pos < len(data); {
  20. posEnd := bytes.IndexByte(data[pos:], '\n')
  21. if posEnd == -1 {
  22. posEnd = len(data)
  23. } else {
  24. posEnd += pos
  25. }
  26. line := data[pos:posEnd]
  27. lsTreeLine, err := parseLsTreeLine(line)
  28. if err != nil {
  29. return nil, err
  30. }
  31. entry := &TreeEntry{
  32. ptree: ptree,
  33. ID: lsTreeLine.ID,
  34. entryMode: lsTreeLine.EntryMode,
  35. name: lsTreeLine.Name,
  36. size: lsTreeLine.Size.Value(),
  37. sized: lsTreeLine.Size.Has(),
  38. }
  39. pos = posEnd + 1
  40. entries = append(entries, entry)
  41. }
  42. return entries, nil
  43. }
  44. func catBatchParseTreeEntries(objectFormat ObjectFormat, ptree *Tree, rd *bufio.Reader, sz int64) ([]*TreeEntry, error) {
  45. fnameBuf := make([]byte, 4096)
  46. modeBuf := make([]byte, 40)
  47. shaBuf := make([]byte, objectFormat.FullLength())
  48. entries := make([]*TreeEntry, 0, 10)
  49. loop:
  50. for sz > 0 {
  51. mode, fname, sha, count, err := ParseCatFileTreeLine(objectFormat, rd, modeBuf, fnameBuf, shaBuf)
  52. if err != nil {
  53. if err == io.EOF {
  54. break loop
  55. }
  56. return nil, err
  57. }
  58. sz -= int64(count)
  59. entry := new(TreeEntry)
  60. entry.ptree = ptree
  61. switch string(mode) {
  62. case "100644":
  63. entry.entryMode = EntryModeBlob
  64. case "100755":
  65. entry.entryMode = EntryModeExec
  66. case "120000":
  67. entry.entryMode = EntryModeSymlink
  68. case "160000":
  69. entry.entryMode = EntryModeCommit
  70. case "40000", "40755": // git uses 40000 for tree object, but some users may get 40755 for unknown reasons
  71. entry.entryMode = EntryModeTree
  72. default:
  73. log.Debug("Unknown mode: %v", string(mode))
  74. return nil, fmt.Errorf("unknown mode: %v", string(mode))
  75. }
  76. entry.ID = objectFormat.MustID(sha)
  77. entry.name = string(fname)
  78. entries = append(entries, entry)
  79. }
  80. if _, err := rd.Discard(1); err != nil {
  81. return entries, err
  82. }
  83. return entries, nil
  84. }