aboutsummaryrefslogtreecommitdiff
path: root/sequencer.c
diff options
context:
space:
mode:
Diffstat (limited to 'sequencer.c')
-rw-r--r--sequencer.c120
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;