Merge branch 'dl/complete-cherry-pick-revert-skip'
[gitweb.git] / refs / files-backend.c
index 06ba49f47ab1b465555f9128a91b9d0a51a55ef3..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;
@@ -214,28 +215,28 @@ static void files_ref_path(struct files_ref_store *refs,
 }
 
 /*
- * Manually add refs/bisect and refs/worktree, which, being
+ * Manually add refs/bisect, refs/rewritten and refs/worktree, which, being
  * per-worktree, might not appear in the directory listing for
  * refs/ in the main repo.
  */
 static void add_per_worktree_entries_to_dir(struct ref_dir *dir, const char *dirname)
 {
-       int pos;
+       const char *prefixes[] = { "refs/bisect/", "refs/worktree/", "refs/rewritten/" };
+       int ip;
 
        if (strcmp(dirname, "refs/"))
                return;
 
-       pos = search_ref_dir(dir, "refs/bisect/", 12);
-       if (pos < 0) {
-               struct ref_entry *child_entry =
-                       create_dir_entry(dir->cache, "refs/bisect/", 12, 1);
-               add_entry_to_dir(dir, child_entry);
-       }
+       for (ip = 0; ip < ARRAY_SIZE(prefixes); ip++) {
+               const char *prefix = prefixes[ip];
+               int prefix_len = strlen(prefix);
+               struct ref_entry *child_entry;
+               int pos;
 
-       pos = search_ref_dir(dir, "refs/worktree/", 11);
-       if (pos < 0) {
-               struct ref_entry *child_entry =
-                       create_dir_entry(dir->cache, "refs/worktree/", 11, 1);
+               pos = search_ref_dir(dir, prefix, prefix_len);
+               if (pos >= 0)
+                       continue;
+               child_entry = create_dir_entry(dir->cache, prefix, prefix_len, 1);
                add_entry_to_dir(dir, child_entry);
        }
 }
@@ -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;
                }
        }