71
char *ref_name;
72
struct lock_file lk;
73
struct object_id old_oid;
74
+ unsigned int count; /* track users of the lock (ref update + reflog updates) */
75
};
76
77
struct files_ref_store {
639
640
static void unlock_ref(struct ref_lock *lock)
641
{
641
- rollback_lock_file(&lock->lk);
642
- free(lock->ref_name);
643
- free(lock);
642
+ lock->count--;
643
+ if (!lock->count) {
644
+ rollback_lock_file(&lock->lk);
645
+ free(lock->ref_name);
646
+ free(lock);
647
+ }
648
}
649
650
/*
700
*lock_p = CALLOC_ARRAY(lock, 1);
701
702
lock->ref_name = xstrdup(refname);
703
+ lock->count = 1;
704
files_ref_path(refs, &ref_file, refname);
705
706
retry:
1174
goto error_return;
1175
1176
lock->ref_name = xstrdup(refname);
1177
+ lock->count = 1;
1178
1179
if (raceproof_create_file(ref_file.buf, create_reflock, &lock->lk)) {
1180
unable_to_lock_message(ref_file.buf, errno, err);
2541
return -1;
2542
}
2543
2544
+struct files_transaction_backend_data {
2545
+ struct ref_transaction *packed_transaction;
2546
+ int packed_refs_locked;
2547
+ struct strmap ref_locks;
2548
+};
2549
+
2550
/*
2551
* Prepare for carrying out update:
2552
* - Lock the reference referred to by update.
2569
{
2570
struct strbuf referent = STRBUF_INIT;
2571
int mustexist = ref_update_expects_existing_old_ref(update);
2572
+ struct files_transaction_backend_data *backend_data;
2573
int ret = 0;
2574
struct ref_lock *lock;
2575
2576
files_assert_main_repository(refs, "lock_ref_for_update");
2577
2578
+ backend_data = transaction->backend_data;
2579
+
2580
if ((update->flags & REF_HAVE_NEW) && ref_update_has_null_new_value(update))
2581
update->flags |= REF_DELETING;
2582
2587
goto out;
2588
}
2589
2575
- ret = lock_raw_ref(refs, update->refname, mustexist,
2576
- affected_refnames,
2577
- &lock, &referent,
2578
- &update->type, err);
2579
- if (ret) {
2580
- char *reason;
2590
+ lock = strmap_get(&backend_data->ref_locks, update->refname);
2591
+ if (lock) {
2592
+ lock->count++;
2593
+ } else {
2594
+ ret = lock_raw_ref(refs, update->refname, mustexist,
2595
+ affected_refnames,
2596
+ &lock, &referent,
2597
+ &update->type, err);
2598
+ if (ret) {
2599
+ char *reason;
2600
+
2601
+ reason = strbuf_detach(err, NULL);
2602
+ strbuf_addf(err, "cannot lock ref '%s': %s",
2603
+ ref_update_original_update_refname(update), reason);
2604
+ free(reason);
2605
+ goto out;
2606
+ }
2607
2582
- reason = strbuf_detach(err, NULL);
2583
- strbuf_addf(err, "cannot lock ref '%s': %s",
2584
- ref_update_original_update_refname(update), reason);
2585
- free(reason);
2586
- goto out;
2608
+ strmap_put(&backend_data->ref_locks, update->refname, lock);
2609
}
2610
2611
update->backend_data = lock;
2752
return ret;
2753
}
2754
2733
-struct files_transaction_backend_data {
2734
- struct ref_transaction *packed_transaction;
2735
- int packed_refs_locked;
2736
-};
2737
-
2755
/*
2756
* Unlock any references in `transaction` that are still locked, and
2757
* mark the transaction closed.
2784
if (backend_data->packed_refs_locked)
2785
packed_refs_unlock(refs->packed_ref_store);
2786
2787
+ strmap_clear(&backend_data->ref_locks, 0);
2788
+
2789
free(backend_data);
2790
}
2791
2815
goto cleanup;
2816
2817
CALLOC_ARRAY(backend_data, 1);
2818
+ strmap_init(&backend_data->ref_locks);
2819
transaction->backend_data = backend_data;
2820
2821
/*