Merge branch 'dl/complete-cherry-pick-revert-skip'
[gitweb.git] / refs / files-backend.c
index 3daf8e6dd0223258d7ef37f8003bfea17b11e39a..d60767ab739f0e20e45c700368f7f9f24a52c3f8 100644 (file)
@@ -180,7 +180,8 @@ static void files_reflog_path(struct files_ref_store *refs,
                break;
        case REF_TYPE_OTHER_PSEUDOREF:
        case REF_TYPE_MAIN_PSEUDOREF:
-               return files_reflog_path_other_worktrees(refs, sb, refname);
+               files_reflog_path_other_worktrees(refs, sb, refname);
+               break;
        case REF_TYPE_NORMAL:
                strbuf_addf(sb, "%s/logs/%s", refs->gitcommondir, refname);
                break;
@@ -2142,13 +2143,24 @@ static struct ref_iterator_vtable files_reflog_iterator_vtable = {
 static struct ref_iterator *reflog_iterator_begin(struct ref_store *ref_store,
                                                  const char *gitdir)
 {
-       struct files_reflog_iterator *iter = xcalloc(1, sizeof(*iter));
-       struct ref_iterator *ref_iterator = &iter->base;
+       struct dir_iterator *diter;
+       struct files_reflog_iterator *iter;
+       struct ref_iterator *ref_iterator;
        struct strbuf sb = STRBUF_INIT;
 
-       base_ref_iterator_init(ref_iterator, &files_reflog_iterator_vtable, 0);
        strbuf_addf(&sb, "%s/logs", gitdir);
-       iter->dir_iterator = dir_iterator_begin(sb.buf);
+
+       diter = dir_iterator_begin(sb.buf, 0);
+       if (!diter) {
+               strbuf_release(&sb);
+               return empty_ref_iterator_begin();
+       }
+
+       iter = xcalloc(1, sizeof(*iter));
+       ref_iterator = &iter->base;
+
+       base_ref_iterator_init(ref_iterator, &files_reflog_iterator_vtable, 0);
+       iter->dir_iterator = diter;
        iter->ref_store = ref_store;
        strbuf_release(&sb);
 
@@ -2259,8 +2271,7 @@ static int split_head_update(struct ref_update *update,
  * Note that the new update will itself be subject to splitting when
  * the iteration gets to it.
  */
-static int split_symref_update(struct files_ref_store *refs,
-                              struct ref_update *update,
+static int split_symref_update(struct ref_update *update,
                               const char *referent,
                               struct ref_transaction *transaction,
                               struct string_list *affected_refnames,
@@ -2454,7 +2465,7 @@ static int lock_ref_for_update(struct files_ref_store *refs,
                         * of processing the split-off update, so we
                         * don't have to do it here.
                         */
-                       ret = split_symref_update(refs, update,
+                       ret = split_symref_update(update,
                                                  referent.buf, transaction,
                                                  affected_refnames, err);
                        if (ret)
@@ -2701,18 +2712,32 @@ static int files_transaction_prepare(struct ref_store *ref_store,
                if (is_packed_transaction_needed(refs->packed_ref_store,
                                                 packed_transaction)) {
                        ret = ref_transaction_prepare(packed_transaction, err);
+                       /*
+                        * A failure during the prepare step will abort
+                        * itself, but not free. Do that now, and disconnect
+                        * from the files_transaction so it does not try to
+                        * abort us when we hit the cleanup code below.
+                        */
+                       if (ret) {
+                               ref_transaction_free(packed_transaction);
+                               backend_data->packed_transaction = NULL;
+                       }
                } else {
                        /*
                         * We can skip rewriting the `packed-refs`
                         * file. But we do need to leave it locked, so
                         * that somebody else doesn't pack a reference
                         * that we are trying to delete.
+                        *
+                        * We need to disconnect our transaction from
+                        * backend_data, since the abort (whether successful or
+                        * not) will free it.
                         */
+                       backend_data->packed_transaction = NULL;
                        if (ref_transaction_abort(packed_transaction, err)) {
                                ret = TRANSACTION_GENERIC_ERROR;
                                goto cleanup;
                        }
-                       backend_data->packed_transaction = NULL;
                }
        }