(s string)
| 1098 | if !ok { |
| 1099 | if parseErr == nil { |
| 1100 | parseErr = fmt.Errorf("invalid ls-tree record %q", line) |
| 1101 | } |
| 1102 | return |
| 1103 | } |
| 1104 | idx := len(nodes) |
| 1105 | nodes = append(nodes, n) |
| 1106 | if typ == "blob" && n.ObjectOID != "" { |
| 1107 | blobIndex[n.ObjectOID] = append(blobIndex[n.ObjectOID], idx) |
| 1108 | if len(blobIndex[n.ObjectOID]) == 1 { |
| 1109 | blobOIDs = append(blobOIDs, n.ObjectOID) |
| 1110 | } |
| 1111 | } |
| 1112 | }); err != nil { |
| 1113 | return nil, err |
| 1114 | } |
| 1115 | if parseErr != nil { |
| 1116 | return nil, parseErr |
| 1117 | } |
| 1118 | |
| 1119 | // Batch-resolve sizes using cat-file --batch-check. This reads from local |
| 1120 | // pack metadata and doesn't trigger network fetches on blobless clones. |
| 1121 | if err := s.batchResolveSizes(ctx, repo, nodes, blobOIDs, blobIndex); err != nil { |
| 1122 | if contextErr := ctx.Err(); contextErr != nil { |
| 1123 | return nil, contextErr |
| 1124 | } |
| 1125 | // Non-fatal: sizes remain "unknown" and reads will still work via |
| 1126 | // hydration. Log so operators can diagnose unexpected attr hydration. |
| 1127 | s.logger.Warn("batch size resolution failed, some file sizes will resolve on demand", "repo", repo.Name, "error", err) |
| 1128 | } |
| 1129 | if err := ctx.Err(); err != nil { |
| 1130 | return nil, err |
| 1131 | } |
| 1132 | return addImplicitDirs(repo.ID, nodes), nil |
| 1133 | } |
| 1134 | |
| 1135 | func streamTreeRecords(ctx context.Context, gitDir string, headOID string, fn func(string)) error { |
| 1136 | cmd := exec.CommandContext(ctx, "git", "ls-tree", "-r", "-t", "-z", headOID) |
| 1137 | configureCancelableCommand(cmd) |
| 1138 | cmd.Env = append(os.Environ(), "GIT_DIR="+gitDir) |
| 1139 | stdout, err := cmd.StdoutPipe() |
| 1140 | if err != nil { |
| 1141 | return err |
| 1142 | } |
| 1143 | errBuf := &bytes.Buffer{} |
| 1144 | cmd.Stderr = errBuf |
| 1145 | if err := cmd.Start(); err != nil { |
| 1146 | return err |
| 1147 | } |
| 1148 | stopClose := context.AfterFunc(ctx, func() { |
| 1149 | _ = stdout.Close() |
no test coverage detected