Change delete_ref_loose()) to just flag that a ref is to be deleted but do not actually unlink the files. Change commit_ref_lock() so that it will unlink refs that are flagged for deletion. Change all callers of delete_ref_loose() to explicitely call commit_ref_lock() to commit the deletion. The new pattern for deleting loose refs thus become: lock = lock_ref_sha1_basic() (or varient of) delete_ref_loose(lock) unlock_ref(lock) | commit_ref_lock(lock) Signed-off-by: Ronnie Sahlberg <sahlberg@xxxxxxxxxx> --- refs.c | 31 ++++++++++++++++++++----------- refs.h | 2 ++ 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/refs.c b/refs.c index 9771237..038614d 100644 --- a/refs.c +++ b/refs.c @@ -2484,16 +2484,9 @@ static int repack_without_ref(const char *refname) static int delete_ref_loose(struct ref_lock *lock, int flag) { - if (!(flag & REF_ISPACKED) || flag & REF_ISSYMREF) { - /* loose */ - int err, i = strlen(lock->lk->filename) - 5; /* .lock */ - - lock->lk->filename[i] = 0; - err = unlink_or_warn(lock->lk->filename); - lock->lk->filename[i] = '.'; - if (err && errno != ENOENT) - return 1; - } + lock->delete_ref = 1; + lock->delete_flag = flag; + return 0; } @@ -2515,7 +2508,7 @@ int delete_ref(const char *refname, const unsigned char *sha1, int delopt) unlink_or_warn(git_path("logs/%s", lock->ref_name)); clear_loose_ref_cache(&ref_cache); - unlock_ref(lock); + ret |= commit_ref_lock(lock); return ret; } @@ -2868,6 +2861,20 @@ int write_ref_sha1(struct ref_lock *lock, int commit_ref_lock(struct ref_lock *lock) { + if (lock->delete_ref) { + int flag = lock->delete_flag; + + if (!(flag & REF_ISPACKED) || flag & REF_ISSYMREF) { + /* loose */ + int err, i = strlen(lock->lk->filename) - 5; /* .lock */ + + lock->lk->filename[i] = 0; + err = unlink_or_warn(lock->lk->filename); + lock->lk->filename[i] = '.'; + if (err && errno != ENOENT) + return 1; + } + } else if (!lock->skipped_write && commit_ref(lock)) { error("Couldn't set %s", lock->ref_name); unlock_ref(lock); @@ -3382,6 +3389,8 @@ int update_refs(const char *action, const struct ref_update **updates_orig, if (locks[i]) { delnames[delnum++] = locks[i]->ref_name; ret |= delete_ref_loose(locks[i], types[i]); + ret |= commit_ref_lock(locks[i]); + locks[i] = NULL; } ret |= repack_without_refs(delnames, delnum); for (i = 0; i < delnum; i++) diff --git a/refs.h b/refs.h index 0382128..2230d67 100644 --- a/refs.h +++ b/refs.h @@ -9,6 +9,8 @@ struct ref_lock { int lock_fd; int force_write; int skipped_write; + int delete_ref; + int delete_flag; }; /** -- 1.9.1.477.g7668a0d.dirty -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html