#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
};
static const char *prompt_mode[] = {
N_("Stage mode change [y,n,a,q,d%s,?]? "),
N_("Stage deletion [y,n,a,q,d%s,?]? "),
N_("Stage this hunk [y,n,a,q,d%s,?]? ")
};
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;
};
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 ((arg = va_arg(ap, const char *)))
argv_array_push(&cp->args, arg);
va_end(ap);
cp->git_cmd = 1;
argv_array_pushf(&cp->env_array,
INDEX_ENVIRONMENT "=%s", s->s.r->index_file);
}
static int parse_range(const char **p,
unsigned long *offset, unsigned long *count)
{
char *pend;
*offset = strtoul(*p, &pend, 10);
if (pend == *p)
return -1;
if (*pend != ',') {
*count = 1;
*p = pend;
return 0;
}
*count = strtoul(pend + 1, (char **)p, 10);
return *p == pend + 1 ? -1 : 0;
}
static int parse_hunk_header(struct add_p_state *s, struct hunk *hunk)
{
struct hunk_header *header = &hunk->header;
const char *line = s->plain.buf + hunk->start, *p = line;
char *eol = memchr(p, '\n', s->plain.len - hunk->start);
if (!eol)
eol = s->plain.buf + s->plain.len;
if (!skip_prefix(p, "@@ -", &p) ||
parse_range(&p, &header->old_offset, &header->old_count) < 0 ||
!skip_prefix(p, " +", &p) ||
parse_range(&p, &header->new_offset, &header->new_count) < 0 ||
!skip_prefix(p, " @@", &p))
return error(_("could not parse hunk header '%.*s'"),
(int)(eol - line), line);
hunk->start = eol - s->plain.buf + (*eol == '\n');
header->extra_start = p - s->plain.buf;
|