diff options
author | Alban Gruin <alban.gruin@gmail.com> | 2019-01-29 16:01:49 +0100 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2019-01-29 12:09:24 -0800 |
commit | 6ca89c6f399b86983c7e93a3c5b918cad8292b47 (patch) | |
tree | 96779580d35445f2e7170db354f85397c99fcea1 /rebase-interactive.c | |
parent | sequencer: introduce todo_list_write_to_file() (diff) | |
download | tgif-6ca89c6f399b86983c7e93a3c5b918cad8292b47.tar.xz |
sequencer: refactor check_todo_list() to work on a todo_list
This refactors check_todo_list() to work on a todo_list to avoid
redundant reads and writes to the disk. The function is renamed
todo_list_check(). The parsing of the two todo lists is left to the
caller.
As rebase -p still need to check the todo list from the disk, a new
function is introduced, check_todo_list_from_file(). It reads the file
from the disk, parses it, pass the todo_list to todo_list_check(), and
writes it back to the disk.
As get_missing_commit_check_level() and the enum
missing_commit_check_level are no longer needed inside of sequencer.c,
they are moved to rebase-interactive.c, and made static again.
Signed-off-by: Alban Gruin <alban.gruin@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'rebase-interactive.c')
-rw-r--r-- | rebase-interactive.c | 91 |
1 files changed, 90 insertions, 1 deletions
diff --git a/rebase-interactive.c b/rebase-interactive.c index 842fa07e7e..dfa6dd530f 100644 --- a/rebase-interactive.c +++ b/rebase-interactive.c @@ -1,8 +1,32 @@ #include "cache.h" #include "commit.h" -#include "rebase-interactive.h" #include "sequencer.h" +#include "rebase-interactive.h" #include "strbuf.h" +#include "commit-slab.h" +#include "config.h" + +enum missing_commit_check_level { + MISSING_COMMIT_CHECK_IGNORE = 0, + MISSING_COMMIT_CHECK_WARN, + MISSING_COMMIT_CHECK_ERROR +}; + +static enum missing_commit_check_level get_missing_commit_check_level(void) +{ + const char *value; + + if (git_config_get_value("rebase.missingcommitscheck", &value) || + !strcasecmp("ignore", value)) + return MISSING_COMMIT_CHECK_IGNORE; + if (!strcasecmp("warn", value)) + return MISSING_COMMIT_CHECK_WARN; + if (!strcasecmp("error", value)) + return MISSING_COMMIT_CHECK_ERROR; + warning(_("unrecognized setting %s for option " + "rebase.missingCommitsCheck. Ignoring."), value); + return MISSING_COMMIT_CHECK_IGNORE; +} void append_todo_help(unsigned edit_todo, unsigned keep_empty, struct strbuf *buf) @@ -89,3 +113,68 @@ int edit_todo_list(struct repository *r, unsigned flags) return 0; } + +define_commit_slab(commit_seen, unsigned char); +/* + * Check if the user dropped some commits by mistake + * Behaviour determined by rebase.missingCommitsCheck. + * Check if there is an unrecognized command or a + * bad SHA-1 in a command. + */ +int todo_list_check(struct todo_list *old_todo, struct todo_list *new_todo) +{ + enum missing_commit_check_level check_level = get_missing_commit_check_level(); + struct strbuf missing = STRBUF_INIT; + int res = 0, i; + struct commit_seen commit_seen; + + init_commit_seen(&commit_seen); + + if (check_level == MISSING_COMMIT_CHECK_IGNORE) + goto leave_check; + + /* Mark the commits in git-rebase-todo as seen */ + for (i = 0; i < new_todo->nr; i++) { + struct commit *commit = new_todo->items[i].commit; + if (commit) + *commit_seen_at(&commit_seen, commit) = 1; + } + + /* Find commits in git-rebase-todo.backup yet unseen */ + for (i = old_todo->nr - 1; i >= 0; i--) { + struct todo_item *item = old_todo->items + i; + struct commit *commit = item->commit; + if (commit && !*commit_seen_at(&commit_seen, commit)) { + strbuf_addf(&missing, " - %s %.*s\n", + find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV), + item->arg_len, + todo_item_get_arg(old_todo, item)); + *commit_seen_at(&commit_seen, commit) = 1; + } + } + + /* Warn about missing commits */ + if (!missing.len) + goto leave_check; + + if (check_level == MISSING_COMMIT_CHECK_ERROR) + res = 1; + + fprintf(stderr, + _("Warning: some commits may have been dropped accidentally.\n" + "Dropped commits (newer to older):\n")); + + /* Make the list user-friendly and display */ + fputs(missing.buf, stderr); + strbuf_release(&missing); + + fprintf(stderr, _("To avoid this message, use \"drop\" to " + "explicitly remove a commit.\n\n" + "Use 'git config rebase.missingCommitsCheck' to change " + "the level of warnings.\n" + "The possible behaviours are: ignore, warn, error.\n\n")); + +leave_check: + clear_commit_seen(&commit_seen); + return res; +} |