summaryrefslogtreecommitdiff
path: root/sequencer.c
diff options
context:
space:
mode:
authorJohannes Schindelin <johannes.schindelin@gmx.de>2017-01-02 15:28:16 (GMT)
committerJunio C Hamano <gitster@pobox.com>2017-01-09 22:57:30 (GMT)
commit25cb8df97c9be26d7638e79595d361fbc40b65a0 (patch)
treeff93603412007aeb9f8ad9f0ae5059c6b27ae764 /sequencer.c
parent8ab37ef21f9c48bf034128523c489b4f39bcbb88 (diff)
downloadgit-25cb8df97c9be26d7638e79595d361fbc40b65a0.zip
git-25cb8df97c9be26d7638e79595d361fbc40b65a0.tar.gz
git-25cb8df97c9be26d7638e79595d361fbc40b65a0.tar.bz2
sequencer (rebase -i): copy commit notes at end
When rebasing commits that have commit notes attached, the interactive rebase rewrites those notes faithfully at the end. The sequencer must do this, too, if it wishes to do interactive rebase's job. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'sequencer.c')
-rw-r--r--sequencer.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/sequencer.c b/sequencer.c
index 95ae4bc..50380a1 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -96,6 +96,15 @@ static GIT_PATH_FUNC(rebase_path_amend, "rebase-merge/amend")
*/
static GIT_PATH_FUNC(rebase_path_stopped_sha, "rebase-merge/stopped-sha")
/*
+ * For the post-rewrite hook, we make a list of rewritten commits and
+ * their new sha1s. The rewritten-pending list keeps the sha1s of
+ * commits that have been processed, but not committed yet,
+ * e.g. because they are waiting for a 'squash' command.
+ */
+static GIT_PATH_FUNC(rebase_path_rewritten_list, "rebase-merge/rewritten-list")
+static GIT_PATH_FUNC(rebase_path_rewritten_pending,
+ "rebase-merge/rewritten-pending")
+/*
* The following files are written by git-rebase just after parsing the
* command-line (and are only consumed, not modified, by the sequencer).
*/
@@ -850,6 +859,44 @@ static int update_squash_messages(enum todo_command command,
return res;
}
+static void flush_rewritten_pending(void) {
+ struct strbuf buf = STRBUF_INIT;
+ unsigned char newsha1[20];
+ FILE *out;
+
+ if (strbuf_read_file(&buf, rebase_path_rewritten_pending(), 82) > 0 &&
+ !get_sha1("HEAD", newsha1) &&
+ (out = fopen(rebase_path_rewritten_list(), "a"))) {
+ char *bol = buf.buf, *eol;
+
+ while (*bol) {
+ eol = strchrnul(bol, '\n');
+ fprintf(out, "%.*s %s\n", (int)(eol - bol),
+ bol, sha1_to_hex(newsha1));
+ if (!*eol)
+ break;
+ bol = eol + 1;
+ }
+ fclose(out);
+ unlink(rebase_path_rewritten_pending());
+ }
+ strbuf_release(&buf);
+}
+
+static void record_in_rewritten(struct object_id *oid,
+ enum todo_command next_command) {
+ FILE *out = fopen(rebase_path_rewritten_pending(), "a");
+
+ if (!out)
+ return;
+
+ fprintf(out, "%s\n", oid_to_hex(oid));
+ fclose(out);
+
+ if (!is_fixup(next_command))
+ flush_rewritten_pending();
+}
+
static int do_pick_commit(enum todo_command command, struct commit *commit,
struct replay_opts *opts, int final_fixup)
{
@@ -1743,6 +1790,17 @@ static int is_final_fixup(struct todo_list *todo_list)
return 1;
}
+static enum todo_command peek_command(struct todo_list *todo_list, int offset)
+{
+ int i;
+
+ for (i = todo_list->current + offset; i < todo_list->nr; i++)
+ if (!is_noop(todo_list->items[i].command))
+ return todo_list->items[i].command;
+
+ return -1;
+}
+
static const char *reflog_message(struct replay_opts *opts,
const char *sub_action, const char *fmt, ...)
{
@@ -1801,6 +1859,9 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
item->arg, item->arg_len, opts, res,
!res);
}
+ if (is_rebase_i(opts) && !res)
+ record_in_rewritten(&item->commit->object.oid,
+ peek_command(todo_list, 1));
if (res && is_fixup(item->command)) {
if (res == 1)
intend_to_amend();
@@ -1827,6 +1888,7 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
if (is_rebase_i(opts)) {
struct strbuf head_ref = STRBUF_INIT, buf = STRBUF_INIT;
+ struct stat st;
/* Stopped in the middle, as planned? */
if (todo_list->current < todo_list->nr)
@@ -1891,6 +1953,20 @@ cleanup_head_ref:
log_tree_diff_flush(&log_tree_opt);
}
}
+ flush_rewritten_pending();
+ if (!stat(rebase_path_rewritten_list(), &st) &&
+ st.st_size > 0) {
+ struct child_process child = CHILD_PROCESS_INIT;
+
+ child.in = open(rebase_path_rewritten_list(), O_RDONLY);
+ child.git_cmd = 1;
+ argv_array_push(&child.args, "notes");
+ argv_array_push(&child.args, "copy");
+ argv_array_push(&child.args, "--for-rewrite=rebase");
+ /* we don't care if this copying failed */
+ run_command(&child);
+ }
+
strbuf_release(&buf);
strbuf_release(&head_ref);
}