#include "cache.h"
#include "add-interactive.h"
#include "strbuf.h"
#include "run-command.h"
#include "argv-array.h"
#include "pathspec.h"
#include "color.h"
#include "diff.h"
enum prompt_mode_type {
PROMPT_MODE_CHANGE = 0, PROMPT_DELETION, PROMPT_HUNK,
PROMPT_MODE_MAX, /* must be last */
};
struct patch_mode {
/*
* The magic constant 4 is chosen such that all patch modes
* provide enough space for three command-line arguments followed by a
* trailing `NULL`.
*/
const char *diff_cmd[4], *apply_args[4], *apply_check_args[4];
unsigned is_reverse:1, apply_for_checkout:1;
const char *prompt_mode[PROMPT_MODE_MAX];
const char *edit_hunk_hint, *help_patch_text;
};
static struct patch_mode patch_mode_add = {
.diff_cmd = { "diff-files", NULL },
.apply_args = { "--cached", NULL },
.apply_check_args = { "--cached", NULL },
.prompt_mode = {
N_("Stage mode change [y,n,q,a,d%s,?]? "),
N_("Stage deletion [y,n,q,a,d%s,?]? "),
N_("Stage this hunk [y,n,q,a,d%s,?]? ")
},
.edit_hunk_hint = N_("If the patch applies cleanly, the edited hunk "
"will immediately be marked for staging."),
.help_patch_text =
N_("y - stage this hunk\n"
"n - do not stage this hunk\n"
"q - quit; do not stage this hunk or any of the remaining "
"ones\n"
"a - stage this hunk and all later hunks in the file\n"
"d - do not stage this hunk or any of the later hunks in "
"the file\n")
};
struct hunk_header {
unsigned long old_offset, old_count, new_offset, new_count;
/*
* Start/end offsets to the extra text after the second `@@` in the
* hunk header, e.g. the function signature. This is expected to
* include the newline.
*/
size_t extra_start, extra_end, colored_extra_start, colored_extra_end;
};
struct hunk {
size_t start, end, colored_start, colored_end, splittable_into;
ssize_t delta;
enum { UNDECIDED_HUNK = 0, SKIP_HUNK, USE_HUNK } use;
struct hunk_header header;
};
struct add_p_state {
struct add_i_state s;
struct strbuf answer, buf;
/* parsed diff */
struct strbuf plain, colored;
struct file_diff {
struct hunk head;
struct hunk *hunk;
size_t hunk_nr, hunk_alloc;
unsigned deleted:1, mode_change:1,binary:1;
} *file_diff;
size_t file_diff_nr;
/* patch mode */
struct patch_mode *mode;
const char *revision;
};
static void err(struct add_p_state *s, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
fputs(s->s.error_color, stderr);
vfprintf(stderr, fmt, args);
fputs(s->s.reset_color, stderr);
fputc('\n', stderr);
va_end(args);
}
static void setup_child_process(struct add_p_state *s,
struct child_process *cp, ...)
{
va_list ap;
const char *arg;
va_start(ap, cp);
while<
|