sequencer (rebase -i): implement the 'exec' command

The 'exec' command is a little special among rebase -i's commands, as it
does *not* have a SHA-1 as first parameter. Instead, everything after the
`exec` command is treated as command-line to execute.

Let's reuse the arg/arg_len fields of the todo_item structure (which hold
the oneline for pick/edit commands) to point to the command-line.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
Johannes Schindelin
2016-04-13 14:08:01 +02:00
parent 6ec43bcbfb
commit 494747e7a1

View File

@@ -17,6 +17,7 @@
#include "argv-array.h"
#include "quote.h"
#include "log-tree.h"
#include "wt-status.h"
#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
@@ -667,6 +668,8 @@ enum todo_command {
TODO_PICK = 0,
TODO_REVERT,
TODO_EDIT,
/* commands that do something else than handling a single commit */
TODO_EXEC,
/* commands that do nothing but are counted for reporting progress */
TODO_NOOP
};
@@ -675,6 +678,7 @@ static const char *todo_command_strings[] = {
"pick",
"revert",
"edit",
"exec",
"noop"
};
@@ -969,6 +973,12 @@ static int parse_insn_line(struct todo_item *item, const char *bol, char *eol)
return -1;
bol += padding;
if (item->command == TODO_EXEC) {
item->arg = bol;
item->arg_len = (int)(eol - bol);
return 0;
}
end_of_object_name = (char *) bol + strcspn(bol, " \t\n");
saved = *end_of_object_name;
*end_of_object_name = '\0';
@@ -1383,6 +1393,47 @@ static int error_with_patch(struct commit *commit,
return exit_code;
}
static int do_exec(const char *command_line)
{
const char *child_argv[] = { NULL, NULL };
int dirty, status;
fprintf(stderr, "Executing: %s\n", command_line);
child_argv[0] = command_line;
status = run_command_v_opt(child_argv, RUN_USING_SHELL);
/* force re-reading of the cache */
if (discard_cache() < 0 || read_cache() < 0)
return error(_("Could not read index"));
dirty = require_clean_work_tree("rebase", NULL, 1, 1);
if (status) {
warning("Execution failed: %s\n%s"
"You can fix the problem, and then run\n"
"\n"
" git rebase --continue\n"
"\n",
command_line,
dirty ? "and made changes to the index and/or the "
"working tree\n" : "");
if (status == 127)
/* command not found */
status = 1;
}
else if (dirty) {
warning("Execution succeeded: %s\nbut "
"left changes to the index and/or the working tree\n"
"Commit or stash your changes, and then run\n"
"\n"
" git rebase --continue\n"
"\n", command_line);
status = 1;
}
return status;
}
static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
{
int res = 0;
@@ -1412,6 +1463,14 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
!res);
}
}
else if (item->command == TODO_EXEC) {
char *end_of_arg = (char *)(item->arg + item->arg_len);
int saved = *end_of_arg;
*end_of_arg = '\0';
res = do_exec(item->arg);
*end_of_arg = saved;
}
else if (item->command != TODO_NOOP)
return error("Unknown command %d", item->command);