(ctx context.Context, blobRef blob.Ref, source io.Reader)
| 190 | } |
| 191 | |
| 192 | func (ix *Index) ReceiveBlob(ctx context.Context, blobRef blob.Ref, source io.Reader) (blob.SizedRef, error) { |
| 193 | // Read from source before acquiring ix.Lock (Issue 878): |
| 194 | sniffer := NewBlobSniffer(blobRef) |
| 195 | written, err := io.Copy(sniffer, source) |
| 196 | if err != nil { |
| 197 | return blob.SizedRef{}, err |
| 198 | } |
| 199 | sbr := blob.SizedRef{Ref: blobRef, Size: uint32(written)} |
| 200 | |
| 201 | ix.Lock() |
| 202 | defer ix.Unlock() |
| 203 | |
| 204 | missingDeps := false |
| 205 | defer func() { |
| 206 | if err == nil { |
| 207 | ix.noteBlobIndexed(blobRef) |
| 208 | if !missingDeps { |
| 209 | ix.removeAllMissingEdges(blobRef) |
| 210 | } |
| 211 | } |
| 212 | }() |
| 213 | |
| 214 | // By default, return immediately if it looks like we already |
| 215 | // have indexed this blob before. But if the user has |
| 216 | // CAMLI_REDO_INDEX_ON_RECEIVE set in their environment, |
| 217 | // always index it. This is generally only useful when working |
| 218 | // on the indexing code and retroactively indexing a subset of |
| 219 | // content without forcing a global reindexing. |
| 220 | if haveVal, haveErr := ix.s.Get("have:" + blobRef.String()); haveErr == nil { |
| 221 | if strings.HasSuffix(haveVal, "|indexed") { |
| 222 | if allowReindex, _ := strconv.ParseBool(os.Getenv("CAMLI_REDO_INDEX_ON_RECEIVE")); allowReindex { |
| 223 | if debugEnv { |
| 224 | log.Printf("index: reindexing %v", sbr) |
| 225 | } |
| 226 | } else { |
| 227 | if debugEnv { |
| 228 | log.Printf("index: ignoring upload of already-indexed %v", sbr) |
| 229 | } |
| 230 | return sbr, nil |
| 231 | } |
| 232 | } |
| 233 | } |
| 234 | |
| 235 | sniffer.Parse() |
| 236 | |
| 237 | fetcher := &missTrackFetcher{ |
| 238 | fetcher: ix.blobSource, |
| 239 | } |
| 240 | |
| 241 | mm, err := ix.populateMutationMap(ctx, fetcher, blobRef, sniffer) |
| 242 | if debugEnv { |
| 243 | log.Printf("index of %v: mm=%v, err=%v", blobRef, mm, err) |
| 244 | } |
| 245 | if err != nil { |
| 246 | if err != errMissingDep { |
| 247 | return blob.SizedRef{}, err |
| 248 | } |
| 249 | fetcher.mu.Lock() |
nothing calls this directly
no test coverage detected