diff options
Diffstat (limited to 'sequencer.c')
| -rw-r--r-- | sequencer.c | 120 |
1 files changed, 117 insertions, 3 deletions
diff --git a/sequencer.c b/sequencer.c index 92204a8c2e..98111e394d 100644 --- a/sequencer.c +++ b/sequencer.c @@ -36,6 +36,7 @@ #include "rebase-interactive.h" #include "reset.h" #include "branch.h" +#include "log-tree.h" #define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION" @@ -193,6 +194,21 @@ struct update_ref_record { struct object_id after; }; +static struct update_ref_record *init_update_ref_record(const char *ref) +{ + struct update_ref_record *rec; + + CALLOC_ARRAY(rec, 1); + + oidcpy(&rec->before, null_oid()); + oidcpy(&rec->after, null_oid()); + + /* This may fail, but that's fine, we will keep the null OID. */ + read_ref(ref, &rec->before); + + return rec; +} + static int git_sequencer_config(const char *k, const char *v, void *cb) { struct replay_opts *opts = cb; @@ -4106,11 +4122,97 @@ leave_merge: return ret; } -static int do_update_ref(struct repository *r, const char *ref_name) +static int write_update_refs_state(struct string_list *refs_to_oids) +{ + int result = 0; + struct lock_file lock = LOCK_INIT; + FILE *fp = NULL; + struct string_list_item *item; + char *path; + + if (!refs_to_oids->nr) + return 0; + + path = rebase_path_update_refs(the_repository->gitdir); + + if (safe_create_leading_directories(path)) { + result = error(_("unable to create leading directories of %s"), + path); + goto cleanup; + } + + if (hold_lock_file_for_update(&lock, path, 0) < 0) { + result = error(_("another 'rebase' process appears to be running; " + "'%s.lock' already exists"), + path); + goto cleanup; + } + + fp = fdopen_lock_file(&lock, "w"); + if (!fp) { + result = error_errno(_("could not open '%s' for writing"), path); + rollback_lock_file(&lock); + goto cleanup; + } + + for_each_string_list_item(item, refs_to_oids) { + struct update_ref_record *rec = item->util; + fprintf(fp, "%s\n%s\n%s\n", item->string, + oid_to_hex(&rec->before), oid_to_hex(&rec->after)); + } + + result = commit_lock_file(&lock); + +cleanup: + free(path); + return result; +} + +static int do_update_ref(struct repository *r, const char *refname) { + struct string_list_item *item; + struct string_list list = STRING_LIST_INIT_DUP; + + if (sequencer_get_update_refs_state(r->gitdir, &list)) + return -1; + + for_each_string_list_item(item, &list) { + if (!strcmp(item->string, refname)) { + struct update_ref_record *rec = item->util; + if (read_ref("HEAD", &rec->after)) + return -1; + break; + } + } + + write_update_refs_state(&list); + string_list_clear(&list, 1); return 0; } +static int do_update_refs(struct repository *r) +{ + int res = 0; + struct string_list_item *item; + struct string_list refs_to_oids = STRING_LIST_INIT_DUP; + struct ref_store *refs = get_main_ref_store(r); + + if ((res = sequencer_get_update_refs_state(r->gitdir, &refs_to_oids))) + return res; + + for_each_string_list_item(item, &refs_to_oids) { + struct update_ref_record *rec = item->util; + + res |= refs_update_ref(refs, "rewritten during rebase", + item->string, + &rec->after, &rec->before, + 0, UPDATE_REFS_MSG_ON_ERR); + } + + string_list_clear(&refs_to_oids, 1); + return res; +} + static int is_final_fixup(struct todo_list *todo_list) { int i = todo_list->current; @@ -4627,6 +4729,9 @@ cleanup_head_ref: strbuf_release(&buf); strbuf_release(&head_ref); + + if (do_update_refs(r)) + return -1; } /* @@ -5711,7 +5816,7 @@ static int add_decorations_to_list(const struct commit *commit, sti = string_list_insert(&ctx->refs_to_oids, decoration->name); - sti->util = oiddup(the_hash_algo->null_oid); + sti->util = init_update_ref_record(decoration->name); } item->offset_in_buf = base_offset; @@ -5731,7 +5836,7 @@ static int add_decorations_to_list(const struct commit *commit, */ static int todo_list_add_update_ref_commands(struct todo_list *todo_list) { - int i; + int i, res; static struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP; static struct string_list decorate_refs_exclude_config = STRING_LIST_INIT_NODUP; static struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP; @@ -5767,7 +5872,16 @@ static int todo_list_add_update_ref_commands(struct todo_list *todo_list) } } + res = write_update_refs_state(&ctx.refs_to_oids); + string_list_clear(&ctx.refs_to_oids, 1); + + if (res) { + /* we failed, so clean up the new list. */ + free(ctx.items); + return res; + } + free(todo_list->items); todo_list->items = ctx.items; todo_list->nr = ctx.items_nr; |
