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> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
56dc3ab04b
commit
311af5266b
57
sequencer.c
57
sequencer.c
@ -18,6 +18,7 @@
|
|||||||
#include "quote.h"
|
#include "quote.h"
|
||||||
#include "trailer.h"
|
#include "trailer.h"
|
||||||
#include "log-tree.h"
|
#include "log-tree.h"
|
||||||
|
#include "wt-status.h"
|
||||||
|
|
||||||
#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
|
#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
|
||||||
|
|
||||||
@ -632,6 +633,8 @@ enum todo_command {
|
|||||||
TODO_PICK = 0,
|
TODO_PICK = 0,
|
||||||
TODO_REVERT,
|
TODO_REVERT,
|
||||||
TODO_EDIT,
|
TODO_EDIT,
|
||||||
|
/* commands that do something else than handling a single commit */
|
||||||
|
TODO_EXEC,
|
||||||
/* commands that do nothing but are counted for reporting progress */
|
/* commands that do nothing but are counted for reporting progress */
|
||||||
TODO_NOOP
|
TODO_NOOP
|
||||||
};
|
};
|
||||||
@ -640,6 +643,7 @@ static const char *todo_command_strings[] = {
|
|||||||
"pick",
|
"pick",
|
||||||
"revert",
|
"revert",
|
||||||
"edit",
|
"edit",
|
||||||
|
"exec",
|
||||||
"noop"
|
"noop"
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -938,6 +942,12 @@ static int parse_insn_line(struct todo_item *item, const char *bol, char *eol)
|
|||||||
return -1;
|
return -1;
|
||||||
bol += padding;
|
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");
|
end_of_object_name = (char *) bol + strcspn(bol, " \t\n");
|
||||||
saved = *end_of_object_name;
|
saved = *end_of_object_name;
|
||||||
*end_of_object_name = '\0';
|
*end_of_object_name = '\0';
|
||||||
@ -1397,6 +1407,46 @@ static int error_with_patch(struct commit *commit,
|
|||||||
return exit_code;
|
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 ? N_("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)
|
static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
|
||||||
{
|
{
|
||||||
int res = 0;
|
int res = 0;
|
||||||
@ -1425,6 +1475,13 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
|
|||||||
item->arg, item->arg_len, opts, res,
|
item->arg, item->arg_len, opts, res,
|
||||||
!res);
|
!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 (!is_noop(item->command))
|
} else if (!is_noop(item->command))
|
||||||
return error(_("unknown command %d"), item->command);
|
return error(_("unknown command %d"), item->command);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user