add_update(): initialize the whole ref_update
[gitweb.git] / refs / files-backend.c
index c978fe49c918e2f8ace68fe112975c742cfd9838..1d1b72d57d1c895280e54e79d0e52192a70094de 100644 (file)
@@ -2087,7 +2087,7 @@ static void prune_ref(struct ref_to_prune *r)
        transaction = ref_transaction_begin(&err);
        if (!transaction ||
            ref_transaction_delete(transaction, r->name, r->sha1,
-                                  REF_ISPRUNING, NULL, &err) ||
+                                  REF_ISPRUNING | REF_NODEREF, NULL, &err) ||
            ref_transaction_commit(transaction, &err)) {
                ref_transaction_free(transaction);
                error("%s", err.buf);
@@ -2299,8 +2299,8 @@ static int rename_tmp_log(const char *newrefname)
 }
 
 int verify_refname_available(const char *newname,
-                            struct string_list *extras,
-                            struct string_list *skip,
+                            const struct string_list *extras,
+                            const struct string_list *skip,
                             struct strbuf *err)
 {
        struct ref_dir *packed_refs = get_packed_refs(&ref_cache);
@@ -2333,7 +2333,8 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
        if (log && S_ISLNK(loginfo.st_mode))
                return error("reflog for %s is a symlink", oldrefname);
 
-       if (!resolve_ref_unsafe(oldrefname, RESOLVE_REF_READING, orig_sha1, &flag))
+       if (!resolve_ref_unsafe(oldrefname, RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
+                               orig_sha1, &flag))
                return error("refname %s not found", oldrefname);
 
        if (flag & REF_ISSYMREF)
@@ -2351,8 +2352,16 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
                goto rollback;
        }
 
-       if (!read_ref_full(newrefname, RESOLVE_REF_READING, sha1, NULL) &&
-           delete_ref(newrefname, sha1, REF_NODEREF)) {
+       /*
+        * Since we are doing a shallow lookup, sha1 is not the
+        * correct value to pass to delete_ref as old_sha1. But that
+        * doesn't matter, because an old_sha1 check wouldn't add to
+        * the safety anyway; we want to delete the reference whatever
+        * its current value.
+        */
+       if (!read_ref_full(newrefname, RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
+                          sha1, NULL) &&
+           delete_ref(newrefname, NULL, REF_NODEREF)) {
                if (errno==EISDIR) {
                        struct strbuf path = STRBUF_INIT;
                        int result;
@@ -2376,7 +2385,8 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
 
        logmoved = log;
 
-       lock = lock_ref_sha1_basic(newrefname, NULL, NULL, NULL, 0, NULL, &err);
+       lock = lock_ref_sha1_basic(newrefname, NULL, NULL, NULL, REF_NODEREF,
+                                  NULL, &err);
        if (!lock) {
                error("unable to rename '%s' to '%s': %s", oldrefname, newrefname, err.buf);
                strbuf_release(&err);
@@ -2394,7 +2404,8 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
        return 0;
 
  rollback:
-       lock = lock_ref_sha1_basic(oldrefname, NULL, NULL, NULL, 0, NULL, &err);
+       lock = lock_ref_sha1_basic(oldrefname, NULL, NULL, NULL, REF_NODEREF,
+                                  NULL, &err);
        if (!lock) {
                error("unable to lock %s for rollback: %s", oldrefname, err.buf);
                strbuf_release(&err);
@@ -2683,7 +2694,7 @@ static int commit_ref_update(struct ref_lock *lock,
                        }
                }
        }
-       if (commit_ref(lock)) {
+       if (!(flags & REF_LOG_ONLY) && commit_ref(lock)) {
                strbuf_addf(err, "couldn't set '%s'", lock->ref_name);
                unlock_ref(lock);
                return -1;
@@ -3101,7 +3112,8 @@ int ref_transaction_commit(struct ref_transaction *transaction,
                        goto cleanup;
                }
                if ((update->flags & REF_HAVE_NEW) &&
-                   !(update->flags & REF_DELETING)) {
+                   !(update->flags & REF_DELETING) &&
+                   !(update->flags & REF_LOG_ONLY)) {
                        int overwriting_symref = ((update->type & REF_ISSYMREF) &&
                                                  (update->flags & REF_NODEREF));
 
@@ -3133,12 +3145,14 @@ int ref_transaction_commit(struct ref_transaction *transaction,
                }
                if (!(update->flags & REF_NEEDS_COMMIT)) {
                        /*
-                        * We didn't have to write anything to the lockfile.
-                        * Close it to free up the file descriptor:
+                        * We didn't call write_ref_to_lockfile(), so
+                        * the lockfile is still open. Close it to
+                        * free up the file descriptor:
                         */
                        if (close_ref(update->lock)) {
                                strbuf_addf(err, "couldn't close '%s.lock'",
                                            update->refname);
+                               ret = TRANSACTION_GENERIC_ERROR;
                                goto cleanup;
                        }
                }
@@ -3148,7 +3162,8 @@ int ref_transaction_commit(struct ref_transaction *transaction,
        for (i = 0; i < transaction->nr; i++) {
                struct ref_update *update = transaction->updates[i];
 
-               if (update->flags & REF_NEEDS_COMMIT) {
+               if (update->flags & REF_NEEDS_COMMIT ||
+                   update->flags & REF_LOG_ONLY) {
                        if (commit_ref_update(update->lock,
                                              update->new_sha1, update->msg,
                                              update->flags, err)) {
@@ -3167,7 +3182,8 @@ int ref_transaction_commit(struct ref_transaction *transaction,
        for (i = 0; i < transaction->nr; i++) {
                struct ref_update *update = transaction->updates[i];
 
-               if (update->flags & REF_DELETING) {
+               if (update->flags & REF_DELETING &&
+                   !(update->flags & REF_LOG_ONLY)) {
                        if (delete_ref_loose(update->lock, update->type, err)) {
                                ret = TRANSACTION_GENERIC_ERROR;
                                goto cleanup;