refs.c: make prune_ref use a transaction to delete the ref
Change prune_ref to delete the ref using a ref transaction. To do this we also need to add a new flag REF_ISPRUNING that will tell the transaction that we do not want to delete this ref from the packed refs. This flag is private to refs.c and not exposed to external callers. Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Reviewed-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Ronnie Sahlberg committed
Apr 30, 2014 at 09:03 UTC
029cdb4ab21c49a916efd68eaf2d2431c7fab7c7
2 files changed
+32
-9
refs.c
+21
-7
@@ -24,6 +24,11 @@ static unsigned char refname_disposition[256] = {
24
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 4, 4
25
};
26
27
+/*
28
+ * Used as a flag to ref_transaction_delete when a loose ref is being
29
+ * pruned.
30
+ */
31
+#define REF_ISPRUNING 0x0100
32
/*
33
* Try to read one refname component from the front of refname.
34
* Return the length of the component found, or -1 if the component is
@@ -2382,17 +2387,25 @@ static void try_remove_empty_parents(char *name)
2387
/* make sure nobody touched the ref, and unlink */
2388
static void prune_ref(struct ref_to_prune *r)
2389
{
2385
- struct ref_lock *lock;
2390
+ struct ref_transaction *transaction;
2391
+ struct strbuf err = STRBUF_INIT;
2392
2393
if (check_refname_format(r->name + 5, 0))
2394
return;
2395
2390
- lock = lock_ref_sha1_basic(r->name, r->sha1, 0, NULL);
2391
- if (lock) {
2392
- unlink_or_warn(git_path("%s", r->name));
2393
- unlock_ref(lock);
2394
- try_remove_empty_parents(r->name);
2396
+ transaction = ref_transaction_begin(&err);
2397
+ if (!transaction ||
2398
+ ref_transaction_delete(transaction, r->name, r->sha1,
2399
+ REF_ISPRUNING, 1, &err) ||
2400
+ ref_transaction_commit(transaction, NULL, &err)) {
2401
+ ref_transaction_free(transaction);
2402
+ error("%s", err.buf);
2403
+ strbuf_release(&err);
2404
+ return;
2405
}
2406
+ ref_transaction_free(transaction);
2407
+ strbuf_release(&err);
2408
+ try_remove_empty_parents(r->name);
2409
}
2410
2411
static void prune_refs(struct ref_to_prune *r)
@@ -3598,8 +3611,9 @@ int ref_transaction_commit(struct ref_transaction *transaction,
3611
struct ref_update *update = updates[i];
3612
3613
if (update->lock) {
3601
- delnames[delnum++] = update->lock->ref_name;
3614
ret |= delete_ref_loose(update->lock, update->type);
3615
+ if (!(update->flags & REF_ISPRUNING))
3616
+ delnames[delnum++] = update->lock->ref_name;
3617
}
3618
}
3619
refs.h
+11
-2
@@ -170,9 +170,18 @@ extern int ref_exists(const char *);
170
*/
171
extern int peel_ref(const char *refname, unsigned char *sha1);
172
173
-/** Locks any ref (for 'HEAD' type refs). */
173
+/*
174
+ * Flags controlling lock_any_ref_for_update(), ref_transaction_update(),
175
+ * ref_transaction_create(), etc.
176
+ * REF_NODEREF: act on the ref directly, instead of dereferencing
177
+ * symbolic references.
178
+ *
179
+ * Flags >= 0x100 are reserved for internal use.
180
+ */
181
#define REF_NODEREF 0x01
175
-/* errno is set to something meaningful on failure */
182
+/*
183
+ * This function sets errno to something meaningful on failure.
184
+ */
185
extern struct ref_lock *lock_any_ref_for_update(const char *refname,
186
const unsigned char *old_sha1,
187
int flags, int *type_p);