* Write the packed refs from the current snapshot to the packed-refs * tempfile, incorporating any changes from `updates`. `updates` must * be a sorted string list whose keys are the refnames and whose util * values are `struct ref_update *`. On error, rollback the tempfile, * write an error message to `err`, and return a nonzero value. * * The packfile must be locked before calling this fun
| 1356 | * remain locked when it is done. |
| 1357 | */ |
| 1358 | static enum ref_transaction_error write_with_updates(struct packed_ref_store *refs, |
| 1359 | struct ref_transaction *transaction, |
| 1360 | struct strbuf *err) |
| 1361 | { |
| 1362 | enum ref_transaction_error ret = REF_TRANSACTION_ERROR_GENERIC; |
| 1363 | struct string_list *updates = &transaction->refnames; |
| 1364 | struct ref_iterator *iter = NULL; |
| 1365 | size_t i; |
| 1366 | int ok; |
| 1367 | FILE *out; |
| 1368 | struct strbuf sb = STRBUF_INIT; |
| 1369 | char *packed_refs_path; |
| 1370 | |
| 1371 | if (!is_lock_file_locked(&refs->lock)) |
| 1372 | BUG("write_with_updates() called while unlocked"); |
| 1373 | |
| 1374 | /* |
| 1375 | * If packed-refs is a symlink, we want to overwrite the |
| 1376 | * symlinked-to file, not the symlink itself. Also, put the |
| 1377 | * staging file next to it: |
| 1378 | */ |
| 1379 | packed_refs_path = get_locked_file_path(&refs->lock); |
| 1380 | strbuf_addf(&sb, "%s.new", packed_refs_path); |
| 1381 | free(packed_refs_path); |
| 1382 | refs->tempfile = create_tempfile(sb.buf); |
| 1383 | if (!refs->tempfile) { |
| 1384 | strbuf_addf(err, "unable to create file %s: %s", |
| 1385 | sb.buf, strerror(errno)); |
| 1386 | strbuf_release(&sb); |
| 1387 | return REF_TRANSACTION_ERROR_GENERIC; |
| 1388 | } |
| 1389 | strbuf_release(&sb); |
| 1390 | |
| 1391 | out = fdopen_tempfile(refs->tempfile, "w"); |
| 1392 | if (!out) { |
| 1393 | strbuf_addf(err, "unable to fdopen packed-refs tempfile: %s", |
| 1394 | strerror(errno)); |
| 1395 | goto error; |
| 1396 | } |
| 1397 | |
| 1398 | if (fprintf(out, "%s", PACKED_REFS_HEADER) < 0) |
| 1399 | goto write_error; |
| 1400 | |
| 1401 | /* |
| 1402 | * We iterate in parallel through the current list of refs and |
| 1403 | * the list of updates, processing an entry from at least one |
| 1404 | * of the lists each time through the loop. When the current |
| 1405 | * list of refs is exhausted, set iter to NULL. When the list |
| 1406 | * of updates is exhausted, leave i set to updates->nr. |
| 1407 | */ |
| 1408 | iter = packed_ref_iterator_begin(&refs->base, "", NULL, |
| 1409 | REFS_FOR_EACH_INCLUDE_BROKEN); |
| 1410 | if ((ok = ref_iterator_advance(iter)) != ITER_OK) { |
| 1411 | ref_iterator_free(iter); |
| 1412 | iter = NULL; |
| 1413 | } |
| 1414 | |
| 1415 | i = 0; |
no test coverage detected