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>
Alban Gruin committed
Jan 29, 2019 at 16:01 UTC
6ca89c6f399b86983c7e93a3c5b918cad8292b47
5 files changed
+117
-108
builtin/rebase--interactive.c
+1
-1
@@ -256,7 +256,7 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
256
ret = transform_todo_file(the_repository, flags);
257
break;
258
case CHECK_TODO_LIST:
259
- ret = check_todo_list(the_repository);
259
+ ret = check_todo_list_from_file(the_repository);
260
break;
261
case REARRANGE_SQUASH:
262
ret = rearrange_squash(the_repository);
rebase-interactive.c
+90
-1
@@ -1,8 +1,32 @@
1
#include "cache.h"
2
#include "commit.h"
3
-#include "rebase-interactive.h"
3
#include "sequencer.h"
4
+#include "rebase-interactive.h"
5
#include "strbuf.h"
6
+#include "commit-slab.h"
7
+#include "config.h"
8
+
9
+enum missing_commit_check_level {
10
+ MISSING_COMMIT_CHECK_IGNORE = 0,
11
+ MISSING_COMMIT_CHECK_WARN,
12
+ MISSING_COMMIT_CHECK_ERROR
13
+};
14
+
15
+static enum missing_commit_check_level get_missing_commit_check_level(void)
16
+{
17
+ const char *value;
18
+
19
+ if (git_config_get_value("rebase.missingcommitscheck", &value) ||
20
+ !strcasecmp("ignore", value))
21
+ return MISSING_COMMIT_CHECK_IGNORE;
22
+ if (!strcasecmp("warn", value))
23
+ return MISSING_COMMIT_CHECK_WARN;
24
+ if (!strcasecmp("error", value))
25
+ return MISSING_COMMIT_CHECK_ERROR;
26
+ warning(_("unrecognized setting %s for option "
27
+ "rebase.missingCommitsCheck. Ignoring."), value);
28
+ return MISSING_COMMIT_CHECK_IGNORE;
29
+}
30
31
void append_todo_help(unsigned edit_todo, unsigned keep_empty,
32
struct strbuf *buf)
@@ -89,3 +113,68 @@ int edit_todo_list(struct repository *r, unsigned flags)
113
114
return 0;
115
}
116
+
117
+define_commit_slab(commit_seen, unsigned char);
118
+/*
119
+ * Check if the user dropped some commits by mistake
120
+ * Behaviour determined by rebase.missingCommitsCheck.
121
+ * Check if there is an unrecognized command or a
122
+ * bad SHA-1 in a command.
123
+ */
124
+int todo_list_check(struct todo_list *old_todo, struct todo_list *new_todo)
125
+{
126
+ enum missing_commit_check_level check_level = get_missing_commit_check_level();
127
+ struct strbuf missing = STRBUF_INIT;
128
+ int res = 0, i;
129
+ struct commit_seen commit_seen;
130
+
131
+ init_commit_seen(&commit_seen);
132
+
133
+ if (check_level == MISSING_COMMIT_CHECK_IGNORE)
134
+ goto leave_check;
135
+
136
+ /* Mark the commits in git-rebase-todo as seen */
137
+ for (i = 0; i < new_todo->nr; i++) {
138
+ struct commit *commit = new_todo->items[i].commit;
139
+ if (commit)
140
+ *commit_seen_at(&commit_seen, commit) = 1;
141
+ }
142
+
143
+ /* Find commits in git-rebase-todo.backup yet unseen */
144
+ for (i = old_todo->nr - 1; i >= 0; i--) {
145
+ struct todo_item *item = old_todo->items + i;
146
+ struct commit *commit = item->commit;
147
+ if (commit && !*commit_seen_at(&commit_seen, commit)) {
148
+ strbuf_addf(&missing, " - %s %.*s\n",
149
+ find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV),
150
+ item->arg_len,
151
+ todo_item_get_arg(old_todo, item));
152
+ *commit_seen_at(&commit_seen, commit) = 1;
153
+ }
154
+ }
155
+
156
+ /* Warn about missing commits */
157
+ if (!missing.len)
158
+ goto leave_check;
159
+
160
+ if (check_level == MISSING_COMMIT_CHECK_ERROR)
161
+ res = 1;
162
+
163
+ fprintf(stderr,
164
+ _("Warning: some commits may have been dropped accidentally.\n"
165
+ "Dropped commits (newer to older):\n"));
166
+
167
+ /* Make the list user-friendly and display */
168
+ fputs(missing.buf, stderr);
169
+ strbuf_release(&missing);
170
+
171
+ fprintf(stderr, _("To avoid this message, use \"drop\" to "
172
+ "explicitly remove a commit.\n\n"
173
+ "Use 'git config rebase.missingCommitsCheck' to change "
174
+ "the level of warnings.\n"
175
+ "The possible behaviours are: ignore, warn, error.\n\n"));
176
+
177
+leave_check:
178
+ clear_commit_seen(&commit_seen);
179
+ return res;
180
+}
rebase-interactive.h
+2
@@ -3,9 +3,11 @@
3
4
struct strbuf;
5
struct repository;
6
+struct todo_list;
7
8
void append_todo_help(unsigned edit_todo, unsigned keep_empty,
9
struct strbuf *buf);
10
int edit_todo_list(struct repository *r, unsigned flags);
11
+int todo_list_check(struct todo_list *old_todo, struct todo_list *new_todo);
12
13
#endif
sequencer.c
+23
-98
@@ -4660,112 +4660,37 @@ int transform_todo_file(struct repository *r, unsigned flags)
4660
return 0;
4661
}
4662
4663
-enum missing_commit_check_level get_missing_commit_check_level(void)
4664
-{
4665
- const char *value;
4666
-
4667
- if (git_config_get_value("rebase.missingcommitscheck", &value) ||
4668
- !strcasecmp("ignore", value))
4669
- return MISSING_COMMIT_CHECK_IGNORE;
4670
- if (!strcasecmp("warn", value))
4671
- return MISSING_COMMIT_CHECK_WARN;
4672
- if (!strcasecmp("error", value))
4673
- return MISSING_COMMIT_CHECK_ERROR;
4674
- warning(_("unrecognized setting %s for option "
4675
- "rebase.missingCommitsCheck. Ignoring."), value);
4676
- return MISSING_COMMIT_CHECK_IGNORE;
4677
-}
4663
+static const char edit_todo_list_advice[] =
4664
+N_("You can fix this with 'git rebase --edit-todo' "
4665
+"and then run 'git rebase --continue'.\n"
4666
+"Or you can abort the rebase with 'git rebase"
4667
+" --abort'.\n");
4668
4679
-define_commit_slab(commit_seen, unsigned char);
4680
-/*
4681
- * Check if the user dropped some commits by mistake
4682
- * Behaviour determined by rebase.missingCommitsCheck.
4683
- * Check if there is an unrecognized command or a
4684
- * bad SHA-1 in a command.
4685
- */
4686
-int check_todo_list(struct repository *r)
4669
+int check_todo_list_from_file(struct repository *r)
4670
{
4688
- enum missing_commit_check_level check_level = get_missing_commit_check_level();
4689
- struct strbuf todo_file = STRBUF_INIT;
4690
- struct todo_list todo_list = TODO_LIST_INIT;
4691
- struct strbuf missing = STRBUF_INIT;
4692
- int advise_to_edit_todo = 0, res = 0, i;
4693
- struct commit_seen commit_seen;
4694
-
4695
- init_commit_seen(&commit_seen);
4671
+ struct todo_list old_todo = TODO_LIST_INIT, new_todo = TODO_LIST_INIT;
4672
+ int res = 0;
4673
4697
- strbuf_addstr(&todo_file, rebase_path_todo());
4698
- if (strbuf_read_file_or_whine(&todo_list.buf, todo_file.buf) < 0) {
4674
+ if (strbuf_read_file_or_whine(&new_todo.buf, rebase_path_todo()) < 0) {
4675
res = -1;
4700
- goto leave_check;
4701
- }
4702
- advise_to_edit_todo = res =
4703
- todo_list_parse_insn_buffer(r, todo_list.buf.buf, &todo_list);
4704
-
4705
- if (res || check_level == MISSING_COMMIT_CHECK_IGNORE)
4706
- goto leave_check;
4707
-
4708
- /* Mark the commits in git-rebase-todo as seen */
4709
- for (i = 0; i < todo_list.nr; i++) {
4710
- struct commit *commit = todo_list.items[i].commit;
4711
- if (commit)
4712
- *commit_seen_at(&commit_seen, commit) = 1;
4676
+ goto out;
4677
}
4678
4715
- todo_list_release(&todo_list);
4716
- strbuf_addstr(&todo_file, ".backup");
4717
- if (strbuf_read_file_or_whine(&todo_list.buf, todo_file.buf) < 0) {
4679
+ if (strbuf_read_file_or_whine(&old_todo.buf, rebase_path_todo_backup()) < 0) {
4680
res = -1;
4719
- goto leave_check;
4720
- }
4721
- strbuf_release(&todo_file);
4722
- res = !!todo_list_parse_insn_buffer(r, todo_list.buf.buf, &todo_list);
4723
-
4724
- /* Find commits in git-rebase-todo.backup yet unseen */
4725
- for (i = todo_list.nr - 1; i >= 0; i--) {
4726
- struct todo_item *item = todo_list.items + i;
4727
- struct commit *commit = item->commit;
4728
- if (commit && !*commit_seen_at(&commit_seen, commit)) {
4729
- strbuf_addf(&missing, " - %s %.*s\n",
4730
- short_commit_name(commit),
4731
- item->arg_len,
4732
- todo_item_get_arg(&todo_list, item));
4733
- *commit_seen_at(&commit_seen, commit) = 1;
4734
- }
4681
+ goto out;
4682
}
4683
4737
- /* Warn about missing commits */
4738
- if (!missing.len)
4739
- goto leave_check;
4740
-
4741
- if (check_level == MISSING_COMMIT_CHECK_ERROR)
4742
- advise_to_edit_todo = res = 1;
4743
-
4744
- fprintf(stderr,
4745
- _("Warning: some commits may have been dropped accidentally.\n"
4746
- "Dropped commits (newer to older):\n"));
4747
-
4748
- /* Make the list user-friendly and display */
4749
- fputs(missing.buf, stderr);
4750
- strbuf_release(&missing);
4751
-
4752
- fprintf(stderr, _("To avoid this message, use \"drop\" to "
4753
- "explicitly remove a commit.\n\n"
4754
- "Use 'git config rebase.missingCommitsCheck' to change "
4755
- "the level of warnings.\n"
4756
- "The possible behaviours are: ignore, warn, error.\n\n"));
4757
-
4758
-leave_check:
4759
- clear_commit_seen(&commit_seen);
4760
- strbuf_release(&todo_file);
4761
- todo_list_release(&todo_list);
4762
-
4763
- if (advise_to_edit_todo)
4764
- fprintf(stderr,
4765
- _("You can fix this with 'git rebase --edit-todo' "
4766
- "and then run 'git rebase --continue'.\n"
4767
- "Or you can abort the rebase with 'git rebase"
4768
- " --abort'.\n"));
4684
+ res = todo_list_parse_insn_buffer(r, old_todo.buf.buf, &old_todo);
4685
+ if (!res)
4686
+ res = todo_list_parse_insn_buffer(r, new_todo.buf.buf, &new_todo);
4687
+ if (!res)
4688
+ res = todo_list_check(&old_todo, &new_todo);
4689
+ if (res)
4690
+ fprintf(stderr, _(edit_todo_list_advice));
4691
+out:
4692
+ todo_list_release(&old_todo);
4693
+ todo_list_release(&new_todo);
4694
4695
return res;
4696
}
@@ -4943,7 +4868,7 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla
4868
4869
todo_list_release(&todo_list);
4870
4946
- if (check_todo_list(r)) {
4871
+ if (check_todo_list_from_file(r)) {
4872
checkout_onto(opts, onto_name, onto, orig_head);
4873
return -1;
4874
}
sequencer.h
+1
-8
@@ -64,12 +64,6 @@ struct replay_opts {
64
};
65
#define REPLAY_OPTS_INIT { .action = -1, .current_fixups = STRBUF_INIT }
66
67
-enum missing_commit_check_level {
68
- MISSING_COMMIT_CHECK_IGNORE = 0,
69
- MISSING_COMMIT_CHECK_WARN,
70
- MISSING_COMMIT_CHECK_ERROR
71
-};
72
-
67
int write_message(const void *buf, size_t len, const char *filename,
68
int append_eol);
69
@@ -154,8 +148,7 @@ int sequencer_make_script(struct repository *r, FILE *out, int argc,
148
149
int sequencer_add_exec_commands(struct repository *r, const char *command);
150
int transform_todo_file(struct repository *r, unsigned flags);
157
-enum missing_commit_check_level get_missing_commit_check_level(void);
158
-int check_todo_list(struct repository *r);
151
+int check_todo_list_from_file(struct repository *r);
152
int complete_action(struct repository *r, struct replay_opts *opts, unsigned flags,
153
const char *shortrevisions, const char *onto_name,
154
const char *onto, const char *orig_head, const char *cmd,