|
16 | 16 | #include "refs.h" |
17 | 17 | #include "argv-array.h" |
18 | 18 | #include "log-tree.h" |
| 19 | +#include "wt-status.h" |
19 | 20 |
|
20 | 21 | #define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION" |
21 | 22 |
|
@@ -504,13 +505,15 @@ enum todo_command { |
504 | 505 | TODO_PICK, |
505 | 506 | TODO_REVERT, |
506 | 507 | TODO_EDIT, |
| 508 | + TODO_EXEC, |
507 | 509 | TODO_NOOP |
508 | 510 | }; |
509 | 511 |
|
510 | 512 | static const char *todo_command_strings[] = { |
511 | 513 | "pick", |
512 | 514 | "revert", |
513 | 515 | "edit", |
| 516 | + "exec", |
514 | 517 | "noop" |
515 | 518 | }; |
516 | 519 |
|
@@ -798,6 +801,12 @@ static int parse_insn_line(struct todo_item *item, |
798 | 801 | return -1; |
799 | 802 | bol += padding; |
800 | 803 |
|
| 804 | + if (item->command == TODO_EXEC) { |
| 805 | + item->arg = bol; |
| 806 | + item->arg_len = (int)(eol - bol); |
| 807 | + return 0; |
| 808 | + } |
| 809 | + |
801 | 810 | end_of_object_name = (char *) bol + strcspn(bol, " \t\n"); |
802 | 811 | saved = *end_of_object_name; |
803 | 812 | *end_of_object_name = '\0'; |
@@ -1139,6 +1148,43 @@ static int error_with_patch(struct commit *commit, |
1139 | 1148 | return exit_code; |
1140 | 1149 | } |
1141 | 1150 |
|
| 1151 | +static int do_exec(const char *command_line) |
| 1152 | +{ |
| 1153 | + const char *child_argv[] = { NULL, NULL }; |
| 1154 | + int dirty, status; |
| 1155 | + |
| 1156 | + child_argv[0] = command_line; |
| 1157 | + status = run_command_v_opt(child_argv, RUN_USING_SHELL); |
| 1158 | + |
| 1159 | + discard_cache(); /* force re-reading of the cache */ |
| 1160 | + dirty = require_clean_work_tree("rebase", NULL, 1); |
| 1161 | + |
| 1162 | + if (status) { |
| 1163 | + warning("Execution failed: %s\n%s" |
| 1164 | + "You can fix the problem, and then run\n" |
| 1165 | + "\n" |
| 1166 | + " git rebase --continue\n" |
| 1167 | + "\n", |
| 1168 | + command_line, |
| 1169 | + dirty ? "and made changes to the index and/or the " |
| 1170 | + "working tree\n" : ""); |
| 1171 | + if (status == 127) |
| 1172 | + /* command not found */ |
| 1173 | + status = 1; |
| 1174 | + } |
| 1175 | + else if (dirty) { |
| 1176 | + warning("Execution succeeded: %s\nbut " |
| 1177 | + "left changes to the index and/or the working tree\n" |
| 1178 | + "Commit or stash your changes, and then run\n" |
| 1179 | + "\n" |
| 1180 | + " git rebase --continue\n" |
| 1181 | + "\n", command_line); |
| 1182 | + status = 1; |
| 1183 | + } |
| 1184 | + |
| 1185 | + return status; |
| 1186 | +} |
| 1187 | + |
1142 | 1188 | static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts) |
1143 | 1189 | { |
1144 | 1190 | int res = 0; |
@@ -1166,6 +1212,14 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts) |
1166 | 1212 | return error_with_patch(commit, opts, res); |
1167 | 1213 | } |
1168 | 1214 | } |
| 1215 | + else if (item->command == TODO_EXEC) { |
| 1216 | + char *end_of_arg = (char *)(item->arg + item->arg_len); |
| 1217 | + int saved = *end_of_arg; |
| 1218 | + |
| 1219 | + *end_of_arg = '\0'; |
| 1220 | + res = do_exec(item->arg); |
| 1221 | + *end_of_arg = saved; |
| 1222 | + } |
1169 | 1223 | else if (item->command != TODO_NOOP) |
1170 | 1224 | return error("Unknown command %d", item->command); |
1171 | 1225 |
|
|
0 commit comments