Skip to content

Commit

Permalink
refs.c: make prune_ref use a transaction to delete the ref
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ronnie Sahlberg authored and Junio C Hamano committed Sep 3, 2014
1 parent cba1202 commit 029cdb4
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 9 deletions.
28 changes: 21 additions & 7 deletions refs.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ static unsigned char refname_disposition[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 4, 4
};

/*
* Used as a flag to ref_transaction_delete when a loose ref is being
* pruned.
*/
#define REF_ISPRUNING 0x0100
/*
* Try to read one refname component from the front of refname.
* Return the length of the component found, or -1 if the component is
Expand Down Expand Up @@ -2382,17 +2387,25 @@ static void try_remove_empty_parents(char *name)
/* make sure nobody touched the ref, and unlink */
static void prune_ref(struct ref_to_prune *r)
{
struct ref_lock *lock;
struct ref_transaction *transaction;
struct strbuf err = STRBUF_INIT;

if (check_refname_format(r->name + 5, 0))
return;

lock = lock_ref_sha1_basic(r->name, r->sha1, 0, NULL);
if (lock) {
unlink_or_warn(git_path("%s", r->name));
unlock_ref(lock);
try_remove_empty_parents(r->name);
transaction = ref_transaction_begin(&err);
if (!transaction ||
ref_transaction_delete(transaction, r->name, r->sha1,
REF_ISPRUNING, 1, &err) ||
ref_transaction_commit(transaction, NULL, &err)) {
ref_transaction_free(transaction);
error("%s", err.buf);
strbuf_release(&err);
return;
}
ref_transaction_free(transaction);
strbuf_release(&err);
try_remove_empty_parents(r->name);
}

static void prune_refs(struct ref_to_prune *r)
Expand Down Expand Up @@ -3598,8 +3611,9 @@ int ref_transaction_commit(struct ref_transaction *transaction,
struct ref_update *update = updates[i];

if (update->lock) {
delnames[delnum++] = update->lock->ref_name;
ret |= delete_ref_loose(update->lock, update->type);
if (!(update->flags & REF_ISPRUNING))
delnames[delnum++] = update->lock->ref_name;
}
}

Expand Down
13 changes: 11 additions & 2 deletions refs.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,18 @@ extern int ref_exists(const char *);
*/
extern int peel_ref(const char *refname, unsigned char *sha1);

/** Locks any ref (for 'HEAD' type refs). */
/*
* Flags controlling lock_any_ref_for_update(), ref_transaction_update(),
* ref_transaction_create(), etc.
* REF_NODEREF: act on the ref directly, instead of dereferencing
* symbolic references.
*
* Flags >= 0x100 are reserved for internal use.
*/
#define REF_NODEREF 0x01
/* errno is set to something meaningful on failure */
/*
* This function sets errno to something meaningful on failure.
*/
extern struct ref_lock *lock_any_ref_for_update(const char *refname,
const unsigned char *old_sha1,
int flags, int *type_p);
Expand Down

0 comments on commit 029cdb4

Please sign in to comment.