Merge branch 'jc/name-rev-lw-tag'
[gitweb.git] / sequencer.c
index 77afecaebf0980bec4f938b15bd08ae35ba09d83..a23b948ac148304dbebfe38955ec8b40cab3e1e5 100644 (file)
@@ -344,7 +344,7 @@ static int read_oneliner(struct strbuf *buf,
 
 static struct tree *empty_tree(void)
 {
-       return lookup_tree(EMPTY_TREE_SHA1_BIN);
+       return lookup_tree(&empty_tree_oid);
 }
 
 static int error_dirty_index(struct replay_opts *opts)
@@ -374,7 +374,7 @@ static void update_abort_safety_file(void)
                write_file(git_path_abort_safety_file(), "%s", "");
 }
 
-static int fast_forward_to(const unsigned char *to, const unsigned char *from,
+static int fast_forward_to(const struct object_id *to, const struct object_id *from,
                        int unborn, struct replay_opts *opts)
 {
        struct ref_transaction *transaction;
@@ -390,7 +390,7 @@ static int fast_forward_to(const unsigned char *to, const unsigned char *from,
        transaction = ref_transaction_begin(&err);
        if (!transaction ||
            ref_transaction_update(transaction, "HEAD",
-                                  to, unborn ? null_sha1 : from,
+                                  to->hash, unborn ? null_sha1 : from->hash,
                                   0, sb.buf, &err) ||
            ref_transaction_commit(transaction, &err)) {
                ref_transaction_free(transaction);
@@ -426,7 +426,7 @@ void append_conflicts_hint(struct strbuf *msgbuf)
 
 static int do_recursive_merge(struct commit *base, struct commit *next,
                              const char *base_label, const char *next_label,
-                             unsigned char *head, struct strbuf *msgbuf,
+                             struct object_id *head, struct strbuf *msgbuf,
                              struct replay_opts *opts)
 {
        struct merge_options o;
@@ -482,13 +482,13 @@ static int do_recursive_merge(struct commit *base, struct commit *next,
 
 static int is_index_unchanged(void)
 {
-       unsigned char head_sha1[20];
+       struct object_id head_oid;
        struct commit *head_commit;
 
-       if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, head_sha1, NULL))
+       if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, head_oid.hash, NULL))
                return error(_("could not resolve HEAD commit\n"));
 
-       head_commit = lookup_commit(head_sha1);
+       head_commit = lookup_commit(&head_oid);
 
        /*
         * If head_commit is NULL, check_commit, called from
@@ -508,7 +508,8 @@ static int is_index_unchanged(void)
                if (cache_tree_update(&the_index, 0))
                        return error(_("unable to update cache tree\n"));
 
-       return !hashcmp(active_cache_tree->sha1, head_commit->tree->object.oid.hash);
+       return !oidcmp(&active_cache_tree->oid,
+                      &head_commit->tree->object.oid);
 }
 
 static int write_author_script(const char *message)
@@ -834,13 +835,13 @@ static int update_squash_messages(enum todo_command command,
                strbuf_splice(&buf, 0, eol - buf.buf, header.buf, header.len);
                strbuf_release(&header);
        } else {
-               unsigned char head[20];
+               struct object_id head;
                struct commit *head_commit;
                const char *head_message, *body;
 
-               if (get_sha1("HEAD", head))
+               if (get_oid("HEAD", &head))
                        return error(_("need a HEAD to fixup"));
-               if (!(head_commit = lookup_commit_reference(head)))
+               if (!(head_commit = lookup_commit_reference(&head)))
                        return error(_("could not read HEAD"));
                if (!(head_message = get_commit_buffer(head_commit, NULL)))
                        return error(_("could not read HEAD's commit message"));
@@ -934,7 +935,7 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
 {
        unsigned int flags = opts->edit ? EDIT_MSG : 0;
        const char *msg_file = opts->edit ? NULL : git_path_merge_msg();
-       unsigned char head[20];
+       struct object_id head;
        struct commit *base, *next, *parent;
        const char *base_label, *next_label;
        struct commit_message msg = { NULL, NULL, NULL, NULL };
@@ -948,12 +949,12 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
                 * that represents the "current" state for merge-recursive
                 * to work on.
                 */
-               if (write_cache_as_tree(head, 0, NULL))
+               if (write_cache_as_tree(head.hash, 0, NULL))
                        return error(_("your index file is unmerged."));
        } else {
-               unborn = get_sha1("HEAD", head);
+               unborn = get_oid("HEAD", &head);
                if (unborn)
-                       hashcpy(head, EMPTY_TREE_SHA1_BIN);
+                       oidcpy(&head, &empty_tree_oid);
                if (index_differs_from(unborn ? EMPTY_TREE_SHA1_HEX : "HEAD", 0, 0))
                        return error_dirty_index(opts);
        }
@@ -989,11 +990,11 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
                        oid_to_hex(&commit->object.oid));
 
        if (opts->allow_ff && !is_fixup(command) &&
-           ((parent && !hashcmp(parent->object.oid.hash, head)) ||
+           ((parent && !oidcmp(&parent->object.oid, &head)) ||
             (!parent && unborn))) {
                if (is_rebase_i(opts))
                        write_author_script(msg.message);
-               res = fast_forward_to(commit->object.oid.hash, head, unborn,
+               res = fast_forward_to(&commit->object.oid, &head, unborn,
                        opts);
                if (res || command != TODO_REWORD)
                        goto leave;
@@ -1045,6 +1046,7 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
                        strbuf_addstr(&msgbuf, p);
 
                if (opts->record_origin) {
+                       strbuf_complete_line(&msgbuf);
                        if (!has_conforming_footer(&msgbuf, NULL, 0))
                                strbuf_addch(&msgbuf, '\n');
                        strbuf_addstr(&msgbuf, cherry_picked_prefix);
@@ -1065,12 +1067,12 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
                        flags |= CLEANUP_MSG;
                        msg_file = rebase_path_fixup_msg();
                } else {
-                       const char *dest = git_path("SQUASH_MSG");
+                       const char *dest = git_path_squash_msg();
                        unlink(dest);
                        if (copy_file(dest, rebase_path_squash_msg(), 0666))
                                return error(_("could not rename '%s' to '%s'"),
                                             rebase_path_squash_msg(), dest);
-                       unlink(git_path("MERGE_MSG"));
+                       unlink(git_path_merge_msg());
                        msg_file = dest;
                        flags |= EDIT_MSG;
                }
@@ -1080,7 +1082,7 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
                res = -1;
        else if (!opts->strategy || !strcmp(opts->strategy, "recursive") || command == TODO_REVERT) {
                res = do_recursive_merge(base, next, base_label, next_label,
-                                        head, &msgbuf, opts);
+                                        &head, &msgbuf, opts);
                if (res < 0)
                        return res;
                res |= write_message(msgbuf.buf, msgbuf.len,
@@ -1096,7 +1098,7 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
                commit_list_insert(next, &remotes);
                res |= try_merge_command(opts->strategy,
                                         opts->xopts_nr, (const char **)opts->xopts,
-                                       common, sha1_to_hex(head), remotes);
+                                       common, oid_to_hex(&head), remotes);
                free_commit_list(common);
                free_commit_list(remotes);
        }
@@ -1200,6 +1202,7 @@ struct todo_list {
        struct todo_item *items;
        int nr, alloc, current;
        int done_nr, total_nr;
+       struct stat_data stat;
 };
 
 #define TODO_LIST_INIT { STRBUF_INIT }
@@ -1220,7 +1223,7 @@ static struct todo_item *append_new_todo(struct todo_list *todo_list)
 
 static int parse_insn_line(struct todo_item *item, const char *bol, char *eol)
 {
-       unsigned char commit_sha1[20];
+       struct object_id commit_oid;
        char *end_of_object_name;
        int i, saved, status, padding;
 
@@ -1269,7 +1272,7 @@ static int parse_insn_line(struct todo_item *item, const char *bol, char *eol)
        end_of_object_name = (char *) bol + strcspn(bol, " \t\n");
        saved = *end_of_object_name;
        *end_of_object_name = '\0';
-       status = get_sha1(bol, commit_sha1);
+       status = get_oid(bol, &commit_oid);
        *end_of_object_name = saved;
 
        item->arg = end_of_object_name + strspn(end_of_object_name, " \t");
@@ -1278,7 +1281,7 @@ static int parse_insn_line(struct todo_item *item, const char *bol, char *eol)
        if (status < 0)
                return -1;
 
-       item->commit = lookup_commit_reference(commit_sha1);
+       item->commit = lookup_commit_reference(&commit_oid);
        return !item->commit;
 }
 
@@ -1330,6 +1333,7 @@ static int count_commands(struct todo_list *todo_list)
 static int read_populate_todo(struct todo_list *todo_list,
                        struct replay_opts *opts)
 {
+       struct stat st;
        const char *todo_file = get_todo_path(opts);
        int fd, res;
 
@@ -1343,6 +1347,11 @@ static int read_populate_todo(struct todo_list *todo_list,
        }
        close(fd);
 
+       res = stat(todo_file, &st);
+       if (res)
+               return error(_("could not stat '%s'"), todo_file);
+       fill_stat_data(&todo_list->stat, &st);
+
        res = parse_insn_buffer(todo_list->buf.buf, todo_list);
        if (res) {
                if (is_rebase_i(opts))
@@ -1820,10 +1829,10 @@ static int error_failed_squash(struct commit *commit,
                return error(_("could not rename '%s' to '%s'"),
                        rebase_path_squash_msg(), rebase_path_message());
        unlink(rebase_path_fixup_msg());
-       unlink(git_path("MERGE_MSG"));
-       if (copy_file(git_path("MERGE_MSG"), rebase_path_message(), 0666))
+       unlink(git_path_merge_msg());
+       if (copy_file(git_path_merge_msg(), rebase_path_message(), 0666))
                return error(_("could not copy '%s' to '%s'"),
-                            rebase_path_message(), git_path("MERGE_MSG"));
+                            rebase_path_message(), git_path_merge_msg());
        return error_with_patch(commit, subject, subject_len, opts, 1, 0);
 }
 
@@ -1906,11 +1915,13 @@ static int apply_autostash(struct replay_opts *opts)
        strbuf_trim(&stash_sha1);
 
        child.git_cmd = 1;
+       child.no_stdout = 1;
+       child.no_stderr = 1;
        argv_array_push(&child.args, "stash");
        argv_array_push(&child.args, "apply");
        argv_array_push(&child.args, stash_sha1.buf);
        if (!run_command(&child))
-               printf(_("Applied autostash."));
+               printf(_("Applied autostash.\n"));
        else {
                struct child_process store = CHILD_PROCESS_INIT;
 
@@ -2028,10 +2039,25 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
                } else if (item->command == TODO_EXEC) {
                        char *end_of_arg = (char *)(item->arg + item->arg_len);
                        int saved = *end_of_arg;
+                       struct stat st;
 
                        *end_of_arg = '\0';
                        res = do_exec(item->arg);
                        *end_of_arg = saved;
+
+                       /* Reread the todo file if it has changed. */
+                       if (res)
+                               ; /* fall through */
+                       else if (stat(get_todo_path(opts), &st))
+                               res = error_errno(_("could not stat '%s'"),
+                                                 get_todo_path(opts));
+                       else if (match_stat_data(&todo_list->stat, &st)) {
+                               todo_list_release(todo_list);
+                               if (read_populate_todo(todo_list, opts))
+                                       res = -1; /* message was printed */
+                               /* `current` will be incremented below */
+                               todo_list->current = -1;
+                       }
                } else if (!is_noop(item->command))
                        return error(_("unknown command %d"), item->command);
 
@@ -2066,6 +2092,7 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
                                res = error(_("could not read orig-head"));
                                goto cleanup_head_ref;
                        }
+                       strbuf_reset(&buf);
                        if (!read_oneliner(&buf, rebase_path_onto(), 0)) {
                                res = error(_("could not read 'onto'"));
                                goto cleanup_head_ref;
@@ -2167,7 +2194,7 @@ static int commit_staged_changes(struct replay_opts *opts)
        if (has_unstaged_changes(1))
                return error(_("cannot rebase: You have unstaged changes."));
        if (!has_uncommitted_changes(0)) {
-               const char *cherry_pick_head = git_path("CHERRY_PICK_HEAD");
+               const char *cherry_pick_head = git_path_cherry_pick_head();
 
                if (file_exists(cherry_pick_head) && unlink(cherry_pick_head))
                        return error(_("could not remove CHERRY_PICK_HEAD"));
@@ -2258,7 +2285,7 @@ static int single_pick(struct commit *cmit, struct replay_opts *opts)
 int sequencer_pick_revisions(struct replay_opts *opts)
 {
        struct todo_list todo_list = TODO_LIST_INIT;
-       unsigned char sha1[20];
+       struct object_id oid;
        int i, res;
 
        assert(opts->revs);
@@ -2266,16 +2293,16 @@ int sequencer_pick_revisions(struct replay_opts *opts)
                return -1;
 
        for (i = 0; i < opts->revs->pending.nr; i++) {
-               unsigned char sha1[20];
+               struct object_id oid;
                const char *name = opts->revs->pending.objects[i].name;
 
                /* This happens when using --stdin. */
                if (!strlen(name))
                        continue;
 
-               if (!get_sha1(name, sha1)) {
-                       if (!lookup_commit_reference_gently(sha1, 1)) {
-                               enum object_type type = sha1_object_info(sha1, NULL);
+               if (!get_oid(name, &oid)) {
+                       if (!lookup_commit_reference_gently(&oid, 1)) {
+                               enum object_type type = sha1_object_info(oid.hash, NULL);
                                return error(_("%s: can't cherry-pick a %s"),
                                        name, typename(type));
                        }
@@ -2312,9 +2339,9 @@ int sequencer_pick_revisions(struct replay_opts *opts)
        if (walk_revs_populate_todo(&todo_list, opts) ||
                        create_seq_dir() < 0)
                return -1;
-       if (get_sha1("HEAD", sha1) && (opts->action == REPLAY_REVERT))
+       if (get_oid("HEAD", &oid) && (opts->action == REPLAY_REVERT))
                return error(_("can't revert as initial commit"));
-       if (save_head(sha1_to_hex(sha1)))
+       if (save_head(oid_to_hex(&oid)))
                return -1;
        if (save_opts(opts))
                return -1;
@@ -2335,6 +2362,9 @@ void append_signoff(struct strbuf *msgbuf, int ignore_footer, unsigned flag)
                                getenv("GIT_COMMITTER_EMAIL")));
        strbuf_addch(&sob, '\n');
 
+       if (!ignore_footer)
+               strbuf_complete_line(msgbuf);
+
        /*
         * If the whole message buffer is equal to the sob, pretend that we
         * found a conforming footer with a matching sob
@@ -2355,13 +2385,6 @@ void append_signoff(struct strbuf *msgbuf, int ignore_footer, unsigned flag)
                         * the title and body to be filled in by the user.
                         */
                        append_newlines = "\n\n";
-               } else if (msgbuf->buf[len - 1] != '\n') {
-                       /*
-                        * Incomplete line.  Complete the line and add a
-                        * blank one so that there is an empty line between
-                        * the message body and the sob.
-                        */
-                       append_newlines = "\n\n";
                } else if (len == 1) {
                        /*
                         * Buffer contains a single newline.  Add another