log: use commit-slab in prepare_bases() instead of commit->util
[gitweb.git] / sequencer.c
index c8160e974d7ee6bcef8cb26c098decf616413c2c..3b6d56d0856aa591ffdd703bb4d5e6f0bb6443fe 100644 (file)
@@ -7,7 +7,7 @@
 #include "sequencer.h"
 #include "tag.h"
 #include "run-command.h"
-#include "exec_cmd.h"
+#include "exec-cmd.h"
 #include "utf8.h"
 #include "cache-tree.h"
 #include "diff.h"
@@ -23,6 +23,7 @@
 #include "hashmap.h"
 #include "notes-utils.h"
 #include "sigchain.h"
+#include "commit-slab.h"
 
 #define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
 
@@ -127,6 +128,7 @@ static GIT_PATH_FUNC(rebase_path_rewritten_pending,
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
+static GIT_PATH_FUNC(rebase_path_signoff, "rebase-merge/signoff")
 static GIT_PATH_FUNC(rebase_path_head_name, "rebase-merge/head-name")
 static GIT_PATH_FUNC(rebase_path_onto, "rebase-merge/onto")
 static GIT_PATH_FUNC(rebase_path_autostash, "rebase-merge/autostash")
@@ -282,7 +284,7 @@ struct commit_message {
 
 static const char *short_commit_name(struct commit *commit)
 {
-       return find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV);
+       return find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV);
 }
 
 static int get_message(struct commit *commit, struct commit_message *out)
@@ -339,7 +341,7 @@ static void print_advice(int show_hint, struct replay_opts *opts)
 static int write_message(const void *buf, size_t len, const char *filename,
                         int append_eol)
 {
-       static struct lock_file msg_file;
+       struct lock_file msg_file = LOCK_INIT;
 
        int msg_fd = hold_lock_file_for_update(&msg_file, filename, 0);
        if (msg_fd < 0)
@@ -352,10 +354,8 @@ static int write_message(const void *buf, size_t len, const char *filename,
                rollback_lock_file(&msg_file);
                return error_errno(_("could not write eol to '%s'"), filename);
        }
-       if (commit_lock_file(&msg_file) < 0) {
-               rollback_lock_file(&msg_file);
-               return error(_("failed to finalize '%s'."), filename);
-       }
+       if (commit_lock_file(&msg_file) < 0)
+               return error(_("failed to finalize '%s'"), filename);
 
        return 0;
 }
@@ -485,7 +485,7 @@ static int do_recursive_merge(struct commit *base, struct commit *next,
        struct tree *result, *next_tree, *base_tree, *head_tree;
        int clean;
        char **xopt;
-       static struct lock_file index_lock;
+       struct lock_file index_lock = LOCK_INIT;
 
        if (hold_locked_index(&index_lock, LOCK_REPORT_ON_ERROR) < 0)
                return -1;
@@ -514,18 +514,19 @@ static int do_recursive_merge(struct commit *base, struct commit *next,
                fputs(o.obuf.buf, stdout);
        strbuf_release(&o.obuf);
        diff_warn_rename_limit("merge.renamelimit", o.needed_rename_limit, 0);
-       if (clean < 0)
+       if (clean < 0) {
+               rollback_lock_file(&index_lock);
                return clean;
+       }
 
-       if (active_cache_changed &&
-           write_locked_index(&the_index, &index_lock, COMMIT_LOCK))
+       if (write_locked_index(&the_index, &index_lock,
+                              COMMIT_LOCK | SKIP_IF_UNCHANGED))
                /*
                 * TRANSLATORS: %s will be "revert", "cherry-pick" or
                 * "rebase -i".
                 */
                return error(_("%s: Unable to write new index file"),
                        _(action_name(opts)));
-       rollback_lock_file(&index_lock);
 
        if (!clean)
                append_conflicts_hint(msgbuf);
@@ -1149,6 +1150,8 @@ static int try_to_commit(struct strbuf *msg, const char *author,
                goto out;
        }
 
+       reset_ident_date();
+
        if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
                                 oid, author, opts->gpg_sign, extra)) {
                res = error(_("failed to write commit object"));
@@ -1605,7 +1608,7 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
                }
        }
 
-       if (opts->signoff)
+       if (opts->signoff && !is_fixup(command))
                append_signoff(&msgbuf, 0, 0);
 
        if (is_rebase_i(opts) && write_author_script(msg.message) < 0)
@@ -1705,7 +1708,7 @@ static int prepare_revs(struct replay_opts *opts)
 
 static int read_and_refresh_cache(struct replay_opts *opts)
 {
-       static struct lock_file index_lock;
+       struct lock_file index_lock = LOCK_INIT;
        int index_fd = hold_locked_index(&index_lock, 0);
        if (read_index_preload(&the_index, NULL) < 0) {
                rollback_lock_file(&index_lock);
@@ -1713,13 +1716,13 @@ static int read_and_refresh_cache(struct replay_opts *opts)
                        _(action_name(opts)));
        }
        refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, NULL, NULL, NULL);
-       if (the_index.cache_changed && index_fd >= 0) {
-               if (write_locked_index(&the_index, &index_lock, COMMIT_LOCK)) {
+       if (index_fd >= 0) {
+               if (write_locked_index(&the_index, &index_lock,
+                                      COMMIT_LOCK | SKIP_IF_UNCHANGED)) {
                        return error(_("git %s: failed to refresh the index"),
                                _(action_name(opts)));
                }
        }
-       rollback_lock_file(&index_lock);
        return 0;
 }
 
@@ -2044,6 +2047,11 @@ static int read_populate_opts(struct replay_opts *opts)
                if (file_exists(rebase_path_verbose()))
                        opts->verbose = 1;
 
+               if (file_exists(rebase_path_signoff())) {
+                       opts->allow_ff = 0;
+                       opts->signoff = 1;
+               }
+
                read_strategy_opts(opts, &buf);
                strbuf_release(&buf);
 
@@ -2108,16 +2116,14 @@ static int create_seq_dir(void)
 
 static int save_head(const char *head)
 {
-       static struct lock_file head_lock;
+       struct lock_file head_lock = LOCK_INIT;
        struct strbuf buf = STRBUF_INIT;
        int fd;
        ssize_t written;
 
        fd = hold_lock_file_for_update(&head_lock, git_path_head_file(), 0);
-       if (fd < 0) {
-               rollback_lock_file(&head_lock);
+       if (fd < 0)
                return error_errno(_("could not lock HEAD"));
-       }
        strbuf_addf(&buf, "%s\n", head);
        written = write_in_full(fd, buf.buf, buf.len);
        strbuf_release(&buf);
@@ -2126,10 +2132,8 @@ static int save_head(const char *head)
                return error_errno(_("could not write to '%s'"),
                                   git_path_head_file());
        }
-       if (commit_lock_file(&head_lock) < 0) {
-               rollback_lock_file(&head_lock);
-               return error(_("failed to finalize '%s'."), git_path_head_file());
-       }
+       if (commit_lock_file(&head_lock) < 0)
+               return error(_("failed to finalize '%s'"), git_path_head_file());
        return 0;
 }
 
@@ -2233,7 +2237,7 @@ int sequencer_rollback(struct replay_opts *opts)
 
 static int save_todo(struct todo_list *todo_list, struct replay_opts *opts)
 {
-       static struct lock_file todo_lock;
+       struct lock_file todo_lock = LOCK_INIT;
        const char *todo_path = get_todo_path(opts);
        int next = todo_list->current, offset, fd;
 
@@ -2253,7 +2257,7 @@ static int save_todo(struct todo_list *todo_list, struct replay_opts *opts)
                        todo_list->buf.len - offset) < 0)
                return error_errno(_("could not write to '%s'"), todo_path);
        if (commit_lock_file(&todo_lock) < 0)
-               return error(_("failed to finalize '%s'."), todo_path);
+               return error(_("failed to finalize '%s'"), todo_path);
 
        if (is_rebase_i(opts)) {
                const char *done_path = rebase_path_done();
@@ -2881,7 +2885,8 @@ int sequencer_pick_revisions(struct replay_opts *opts)
 
                if (!get_oid(name, &oid)) {
                        if (!lookup_commit_reference_gently(&oid, 1)) {
-                               enum object_type type = sha1_object_info(oid.hash, NULL);
+                               enum object_type type = oid_object_info(&oid,
+                                                                       NULL);
                                return error(_("%s: can't cherry-pick a %s"),
                                        name, type_name(type));
                        }
@@ -3005,7 +3010,7 @@ int sequencer_make_script(FILE *out, int argc, const char **argv,
        init_revisions(&revs, NULL);
        revs.verbose_header = 1;
        revs.max_parents = 1;
-       revs.cherry_pick = 1;
+       revs.cherry_mark = 1;
        revs.limited = 1;
        revs.reverse = 1;
        revs.right_only = 1;
@@ -3030,8 +3035,12 @@ int sequencer_make_script(FILE *out, int argc, const char **argv,
                return error(_("make_script: error preparing revisions"));
 
        while ((commit = get_revision(&revs))) {
+               int is_empty  = is_original_commit_empty(commit);
+
+               if (!is_empty && (commit->object.flags & PATCHSAME))
+                       continue;
                strbuf_reset(&buf);
-               if (!keep_empty && is_original_commit_empty(commit))
+               if (!keep_empty && is_empty)
                        strbuf_addf(&buf, "%c ", comment_line_char);
                strbuf_addf(&buf, "%s %s ", insn,
                            oid_to_hex(&commit->object.oid));
@@ -3152,6 +3161,7 @@ static enum check_level get_missing_commit_check_level(void)
        return CHECK_IGNORE;
 }
 
+define_commit_slab(commit_seen, unsigned char);
 /*
  * Check if the user dropped some commits by mistake
  * Behaviour determined by rebase.missingCommitsCheck.
@@ -3165,6 +3175,9 @@ int check_todo_list(void)
        struct todo_list todo_list = TODO_LIST_INIT;
        struct strbuf missing = STRBUF_INIT;
        int advise_to_edit_todo = 0, res = 0, i;
+       struct commit_seen commit_seen;
+
+       init_commit_seen(&commit_seen);
 
        strbuf_addstr(&todo_file, rebase_path_todo());
        if (strbuf_read_file_or_whine(&todo_list.buf, todo_file.buf) < 0) {
@@ -3181,7 +3194,7 @@ int check_todo_list(void)
        for (i = 0; i < todo_list.nr; i++) {
                struct commit *commit = todo_list.items[i].commit;
                if (commit)
-                       commit->util = (void *)1;
+                       *commit_seen_at(&commit_seen, commit) = 1;
        }
 
        todo_list_release(&todo_list);
@@ -3197,11 +3210,11 @@ int check_todo_list(void)
        for (i = todo_list.nr - 1; i >= 0; i--) {
                struct todo_item *item = todo_list.items + i;
                struct commit *commit = item->commit;
-               if (commit && !commit->util) {
+               if (commit && !*commit_seen_at(&commit_seen, commit)) {
                        strbuf_addf(&missing, " - %s %.*s\n",
                                    short_commit_name(commit),
                                    item->arg_len, item->arg);
-                       commit->util = (void *)1;
+                       *commit_seen_at(&commit_seen, commit) = 1;
                }
        }
 
@@ -3227,6 +3240,7 @@ int check_todo_list(void)
                "The possible behaviours are: ignore, warn, error.\n\n"));
 
 leave_check:
+       clear_commit_seen(&commit_seen);
        strbuf_release(&todo_file);
        todo_list_release(&todo_list);
 
@@ -3348,6 +3362,8 @@ static int subject2item_cmp(const void *fndata,
        return key ? strcmp(a->subject, key) : strcmp(a->subject, b->subject);
 }
 
+define_commit_slab(commit_todo_item, struct todo_item *);
+
 /*
  * Rearrange the todo list that has both "pick commit-id msg" and "pick
  * commit-id fixup!/squash! msg" in it so that the latter is put immediately
@@ -3364,6 +3380,7 @@ int rearrange_squash(void)
        struct hashmap subject2item;
        int res = 0, rearranged = 0, *next, *tail, i;
        char **subjects;
+       struct commit_todo_item commit_todo;
 
        if (strbuf_read_file_or_whine(&todo_list.buf, todo_file) < 0)
                return -1;
@@ -3372,6 +3389,7 @@ int rearrange_squash(void)
                return -1;
        }
 
+       init_commit_todo_item(&commit_todo);
        /*
         * The hashmap maps onelines to the respective todo list index.
         *
@@ -3402,10 +3420,11 @@ int rearrange_squash(void)
 
                if (is_fixup(item->command)) {
                        todo_list_release(&todo_list);
+                       clear_commit_todo_item(&commit_todo);
                        return error(_("the script was already rearranged."));
                }
 
-               item->commit->util = item;
+               *commit_todo_item_at(&commit_todo, item->commit) = item;
 
                parse_commit(item->commit);
                commit_buffer = get_commit_buffer(item->commit, NULL);
@@ -3432,9 +3451,9 @@ int rearrange_squash(void)
                        else if (!strchr(p, ' ') &&
                                 (commit2 =
                                  lookup_commit_reference_by_name(p)) &&
-                                commit2->util)
+                                *commit_todo_item_at(&commit_todo, commit2))
                                /* found by commit name */
-                               i2 = (struct todo_item *)commit2->util
+                               i2 = *commit_todo_item_at(&commit_todo, commit2)
                                        - todo_list.items;
                        else {
                                /* copy can be a prefix of the commit subject */
@@ -3513,5 +3532,6 @@ int rearrange_squash(void)
        hashmap_free(&subject2item, 1);
        todo_list_release(&todo_list);
 
+       clear_commit_todo_item(&commit_todo);
        return res;
 }