Browse Source

diff family: add --check option

Actually, it is a diff option now, so you can say

	git diff --check

to ask if what you are about to commit is a good patch.

[jc: this also would work for fmt-patch, but the point is that
 the check is done before making a commit.  format-patch is run
 from an already created commit, and that is too late to catch
 whitespace damaged change.]

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
maint
Johannes Schindelin 19 years ago committed by Junio C Hamano
parent
commit
8824689884
  1. 115
      diff.c
  2. 1
      diff.h

115
diff.c

@ -397,6 +397,46 @@ static void show_stats(struct diffstat_t* data) @@ -397,6 +397,46 @@ static void show_stats(struct diffstat_t* data)
total_files, adds, dels);
}

struct checkdiff_t {
struct xdiff_emit_state xm;
const char *filename;
int lineno;
};

static void checkdiff_consume(void *priv, char *line, unsigned long len)
{
struct checkdiff_t *data = priv;

if (line[0] == '+') {
int i, spaces = 0;

data->lineno++;

/* check space before tab */
for (i = 1; i < len && (line[i] == ' ' || line[i] == '\t'); i++)
if (line[i] == ' ')
spaces++;
if (line[i - 1] == '\t' && spaces)
printf("%s:%d: space before tab:%.*s\n",
data->filename, data->lineno, (int)len, line);

/* check white space at line end */
if (line[len - 1] == '\n')
len--;
if (isspace(line[len - 1]))
printf("%s:%d: white space at end: %.*s\n",
data->filename, data->lineno, (int)len, line);
} else if (line[0] == ' ')
data->lineno++;
else if (line[0] == '@') {
char *plus = strchr(line, '+');
if (plus)
data->lineno = strtol(plus, line + len, 10);
else
die("invalid diff");
}
}

static unsigned char *deflate_it(char *data,
unsigned long size,
unsigned long *result_size)
@ -624,6 +664,41 @@ static void builtin_diffstat(const char *name_a, const char *name_b, @@ -624,6 +664,41 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
}
}

static void builtin_checkdiff(const char *name_a, const char *name_b,
struct diff_filespec *one,
struct diff_filespec *two)
{
mmfile_t mf1, mf2;
struct checkdiff_t data;

if (!two)
return;

memset(&data, 0, sizeof(data));
data.xm.consume = checkdiff_consume;
data.filename = name_b ? name_b : name_a;
data.lineno = 0;

if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
die("unable to read files to diff");

if (mmfile_is_binary(&mf2))
return;
else {
/* Crazy xdl interfaces.. */
xpparam_t xpp;
xdemitconf_t xecfg;
xdemitcb_t ecb;

xpp.flags = XDF_NEED_MINIMAL;
xecfg.ctxlen = 0;
xecfg.flags = 0;
ecb.outf = xdiff_outf;
ecb.priv = &data;
xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
}
}

struct diff_filespec *alloc_filespec(const char *path)
{
int namelen = strlen(path);
@ -1180,6 +1255,25 @@ static void run_diffstat(struct diff_filepair *p, struct diff_options *o, @@ -1180,6 +1255,25 @@ static void run_diffstat(struct diff_filepair *p, struct diff_options *o,
builtin_diffstat(name, other, p->one, p->two, diffstat, complete_rewrite);
}

static void run_checkdiff(struct diff_filepair *p, struct diff_options *o)
{
const char *name;
const char *other;

if (DIFF_PAIR_UNMERGED(p)) {
/* unmerged */
return;
}

name = p->one->path;
other = (strcmp(name, p->two->path) ? p->two->path : NULL);

diff_fill_sha1_info(p->one);
diff_fill_sha1_info(p->two);

builtin_checkdiff(name, other, p->one, p->two);
}

void diff_setup(struct diff_options *options)
{
memset(options, 0, sizeof(*options));
@ -1205,7 +1299,8 @@ int diff_setup_done(struct diff_options *options) @@ -1205,7 +1299,8 @@ int diff_setup_done(struct diff_options *options)
* recursive bits for other formats here.
*/
if ((options->output_format == DIFF_FORMAT_PATCH) ||
(options->output_format == DIFF_FORMAT_DIFFSTAT))
(options->output_format == DIFF_FORMAT_DIFFSTAT) ||
(options->output_format == DIFF_FORMAT_CHECKDIFF))
options->recursive = 1;

if (options->detect_rename && options->rename_limit < 0)
@ -1288,6 +1383,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) @@ -1288,6 +1383,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
}
else if (!strcmp(arg, "--stat"))
options->output_format = DIFF_FORMAT_DIFFSTAT;
else if (!strcmp(arg, "--check"))
options->output_format = DIFF_FORMAT_CHECKDIFF;
else if (!strcmp(arg, "--summary"))
options->summary = 1;
else if (!strcmp(arg, "--patch-with-stat")) {
@ -1610,6 +1707,19 @@ static void diff_flush_stat(struct diff_filepair *p, struct diff_options *o, @@ -1610,6 +1707,19 @@ static void diff_flush_stat(struct diff_filepair *p, struct diff_options *o,
run_diffstat(p, o, diffstat);
}

static void diff_flush_checkdiff(struct diff_filepair *p,
struct diff_options *o)
{
if (diff_unmodified_pair(p))
return;

if ((DIFF_FILE_VALID(p->one) && S_ISDIR(p->one->mode)) ||
(DIFF_FILE_VALID(p->two) && S_ISDIR(p->two->mode)))
return; /* no tree diffs in patch format */

run_checkdiff(p, o);
}

int diff_queue_is_empty(void)
{
struct diff_queue_struct *q = &diff_queued_diff;
@ -1740,6 +1850,9 @@ static void flush_one_pair(struct diff_filepair *p, @@ -1740,6 +1850,9 @@ static void flush_one_pair(struct diff_filepair *p,
case DIFF_FORMAT_DIFFSTAT:
diff_flush_stat(p, options, diffstat);
break;
case DIFF_FORMAT_CHECKDIFF:
diff_flush_checkdiff(p, options);
break;
case DIFF_FORMAT_PATCH:
diff_flush_patch(p, options);
break;

1
diff.h

@ -153,6 +153,7 @@ extern int diff_queue_is_empty(void); @@ -153,6 +153,7 @@ extern int diff_queue_is_empty(void);
#define DIFF_FORMAT_NAME 4
#define DIFF_FORMAT_NAME_STATUS 5
#define DIFF_FORMAT_DIFFSTAT 6
#define DIFF_FORMAT_CHECKDIFF 7

extern void diff_flush(struct diff_options*);


Loading…
Cancel
Save