code: func (ix *Index) populateMutationMap(ctx context.Context, fetcher *missTrackFetcher, br blob.Ref, sniffer *BlobSniffer) (*mutationMap, error) {
  	mm := &mutationMap{
  		kv: map[string]string{
  			"meta:" + br.String(): fmt.Sprintf("%d|%s", sniffer.Size(), sniffer.MIMEType()),
  		},
  	}
  	var err error
  	if blob, ok := sniffer.SchemaBlob(); ok {
  		switch blob.Type() {
  		case "claim":
  			err = ix.populateClaim(ctx, fetcher, blob, mm)
  		case "file":
  			err = ix.populateFile(ctx, fetcher, blob, mm)
  		case "directory":
  			err = ix.populateDir(ctx, fetcher, blob, mm)
  		}
  	}
  	if err != nil && err != errMissingDep {
  		return nil, err
  	}
  	var haveVal string
  	if err == errMissingDep {
  		haveVal = fmt.Sprintf("%d", sniffer.Size())
  	} else {
  		haveVal = fmt.Sprintf("%d|indexed", sniffer.Size())
  	}
  	mm.kv["have:"+br.String()] = haveVal
  	if len(fetcher.missing) == 0 {
  		// If err == nil, we're good. Else (err == errMissingDep), we
  		// know the error did not come from a fetching miss (because
  		// len(fetcher.missing) == 0) , but from an index miss. Therefore
  		// we know the miss has already been noted and will be dealt with
  		// later, so we can also pretend everything's fine.
  		return mm, nil
  	}
  	return mm, err
  }
docs: // populateMutationMap populates keys & values that will be committed
  // into the returned map.
  //
  // the blobref can be trusted at this point (it's been fully consumed
  // and verified to match), and the sniffer has been populated.