@@ -4061,11 +4061,71 @@ leave_merge:
return ret;
}
-static int do_update_refs(struct repository *r)
+struct update_refs_context {
+ struct ref_store *refs;
+ char **ref_names;
+ struct object_id *old;
+ struct object_id *new;
+ size_t nr;
+ size_t alloc;
+};
+
+static int add_ref_to_context(const char *refname,
+ const struct object_id *oid,
+ int flags,
+ void *data)
{
+ int f = 0;
+ const char *name;
+ struct update_refs_context *ctx = data;
+
+ ALLOC_GROW(ctx->ref_names, ctx->nr + 1, ctx->alloc);
+ ALLOC_GROW(ctx->old, ctx->nr + 1, ctx->alloc);
+ ALLOC_GROW(ctx->new, ctx->nr + 1, ctx->alloc);
+
+ if (!skip_prefix(refname, "refs/rewritten/for-update-refs/", &name))
+ return 1;
+
+ ctx->ref_names[ctx->nr] = xstrdup(name);
+ oidcpy(&ctx->new[ctx->nr], oid);
+ if (!refs_resolve_ref_unsafe(ctx->refs, name, 0,
+ &ctx->old[ctx->nr], &f))
+ return 1;
+
+ ctx->nr++;
return 0;
}
+static int do_update_refs(struct repository *r)
+{
+ int i, res;
+ struct update_refs_context ctx = {
+ .refs = get_main_ref_store(r),
+ .alloc = 16,
+ };
+ ALLOC_ARRAY(ctx.ref_names, ctx.alloc);
+ ALLOC_ARRAY(ctx.old, ctx.alloc);
+ ALLOC_ARRAY(ctx.new, ctx.alloc);
+
+ res = refs_for_each_fullref_in(ctx.refs,
+ "refs/rewritten/for-update-refs/",
+ add_ref_to_context,
+ &ctx);
+
+ for (i = 0; !res && i < ctx.nr; i++)
+ res = refs_update_ref(ctx.refs, "rewritten during rebase",
+ ctx.ref_names[i],
+ &ctx.new[i], &ctx.old[i],
+ 0, UPDATE_REFS_MSG_ON_ERR);
+
+ for (i = 0; i < ctx.nr; i++)
+ free(ctx.ref_names[i]);
+ free(ctx.ref_names);
+ free(ctx.old);
+ free(ctx.new);
+ return res;
+}
+
static int is_final_fixup(struct todo_list *todo_list)
{
int i = todo_list->current;
@@ -1815,6 +1815,30 @@ test_expect_success '--update-refs adds commands with --rebase-merges' '
)
'
+compare_two_refs () {
+ git rev-parse $1 >expect &&
+ git rev-parse $2 >actual &&
+ test_cmp expect actual
+}
+
+test_expect_success '--update-refs updates refs correctly' '
+ git checkout -B update-refs no-conflict-branch &&
+ git branch -f base HEAD~4 &&
+ git branch -f first HEAD~3 &&
+ git branch -f second HEAD~3 &&
+ git branch -f third HEAD~1 &&
+ test_commit extra2 fileX &&
+ git commit --amend --fixup=L &&
+ (
+ git rebase -i --autosquash --update-refs primary &&
+
+ compare_two_refs HEAD~3 refs/heads/first &&
+ compare_two_refs HEAD~3 refs/heads/second &&
+ compare_two_refs HEAD~1 refs/heads/third &&
+ compare_two_refs HEAD refs/heads/no-conflict-branch
+ )
+'
+
# This must be the last test in this file
test_expect_success '$EDITOR and friends are unchanged' '
test_editor_unchanged