| 267 | } |
| 268 | |
| 269 | static int write_pc_item_to_fd(struct parallel_checkout_item *pc_item, int fd, |
| 270 | const char *path) |
| 271 | { |
| 272 | int ret; |
| 273 | struct stream_filter *filter; |
| 274 | struct strbuf buf = STRBUF_INIT; |
| 275 | char *blob; |
| 276 | size_t size; |
| 277 | ssize_t wrote; |
| 278 | |
| 279 | /* Sanity check */ |
| 280 | ASSERT(is_eligible_for_parallel_checkout(pc_item->ce, &pc_item->ca)); |
| 281 | |
| 282 | filter = get_stream_filter_ca(&pc_item->ca, &pc_item->ce->oid); |
| 283 | if (filter) { |
| 284 | if (odb_stream_blob_to_fd(the_repository->objects, fd, |
| 285 | &pc_item->ce->oid, filter, 1)) { |
| 286 | /* On error, reset fd to try writing without streaming */ |
| 287 | if (reset_fd(fd, path)) |
| 288 | return -1; |
| 289 | } else { |
| 290 | return 0; |
| 291 | } |
| 292 | } |
| 293 | |
| 294 | blob = read_blob_entry(pc_item->ce, &size); |
| 295 | if (!blob) |
| 296 | return error("cannot read object %s '%s'", |
| 297 | oid_to_hex(&pc_item->ce->oid), pc_item->ce->name); |
| 298 | |
| 299 | /* |
| 300 | * checkout metadata is used to give context for external process |
| 301 | * filters. Files requiring such filters are not eligible for parallel |
| 302 | * checkout, so pass NULL. Note: if that changes, the metadata must also |
| 303 | * be passed from the main process to the workers. |
| 304 | */ |
| 305 | ret = convert_to_working_tree_ca(&pc_item->ca, pc_item->ce->name, |
| 306 | blob, size, &buf, NULL); |
| 307 | |
| 308 | if (ret) { |
| 309 | size_t newsize; |
| 310 | free(blob); |
| 311 | blob = strbuf_detach(&buf, &newsize); |
| 312 | size = newsize; |
| 313 | } |
| 314 | |
| 315 | wrote = write_in_full(fd, blob, size); |
| 316 | free(blob); |
| 317 | if (wrote < 0) |
| 318 | return error("unable to write file '%s'", path); |
| 319 | |
| 320 | return 0; |
| 321 | } |
| 322 | |
| 323 | static int close_and_clear(int *fd) |
| 324 | { |
no test coverage detected