Skip to content

Commit 8824689

Browse files
dschoJunio C Hamano
authored andcommitted
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>
1 parent 845ae27 commit 8824689

File tree

2 files changed

+115
-1
lines changed

2 files changed

+115
-1
lines changed

diff.c

Lines changed: 114 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,46 @@ static void show_stats(struct diffstat_t* data)
397397
total_files, adds, dels);
398398
}
399399

400+
struct checkdiff_t {
401+
struct xdiff_emit_state xm;
402+
const char *filename;
403+
int lineno;
404+
};
405+
406+
static void checkdiff_consume(void *priv, char *line, unsigned long len)
407+
{
408+
struct checkdiff_t *data = priv;
409+
410+
if (line[0] == '+') {
411+
int i, spaces = 0;
412+
413+
data->lineno++;
414+
415+
/* check space before tab */
416+
for (i = 1; i < len && (line[i] == ' ' || line[i] == '\t'); i++)
417+
if (line[i] == ' ')
418+
spaces++;
419+
if (line[i - 1] == '\t' && spaces)
420+
printf("%s:%d: space before tab:%.*s\n",
421+
data->filename, data->lineno, (int)len, line);
422+
423+
/* check white space at line end */
424+
if (line[len - 1] == '\n')
425+
len--;
426+
if (isspace(line[len - 1]))
427+
printf("%s:%d: white space at end: %.*s\n",
428+
data->filename, data->lineno, (int)len, line);
429+
} else if (line[0] == ' ')
430+
data->lineno++;
431+
else if (line[0] == '@') {
432+
char *plus = strchr(line, '+');
433+
if (plus)
434+
data->lineno = strtol(plus, line + len, 10);
435+
else
436+
die("invalid diff");
437+
}
438+
}
439+
400440
static unsigned char *deflate_it(char *data,
401441
unsigned long size,
402442
unsigned long *result_size)
@@ -624,6 +664,41 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
624664
}
625665
}
626666

667+
static void builtin_checkdiff(const char *name_a, const char *name_b,
668+
struct diff_filespec *one,
669+
struct diff_filespec *two)
670+
{
671+
mmfile_t mf1, mf2;
672+
struct checkdiff_t data;
673+
674+
if (!two)
675+
return;
676+
677+
memset(&data, 0, sizeof(data));
678+
data.xm.consume = checkdiff_consume;
679+
data.filename = name_b ? name_b : name_a;
680+
data.lineno = 0;
681+
682+
if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
683+
die("unable to read files to diff");
684+
685+
if (mmfile_is_binary(&mf2))
686+
return;
687+
else {
688+
/* Crazy xdl interfaces.. */
689+
xpparam_t xpp;
690+
xdemitconf_t xecfg;
691+
xdemitcb_t ecb;
692+
693+
xpp.flags = XDF_NEED_MINIMAL;
694+
xecfg.ctxlen = 0;
695+
xecfg.flags = 0;
696+
ecb.outf = xdiff_outf;
697+
ecb.priv = &data;
698+
xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
699+
}
700+
}
701+
627702
struct diff_filespec *alloc_filespec(const char *path)
628703
{
629704
int namelen = strlen(path);
@@ -1180,6 +1255,25 @@ static void run_diffstat(struct diff_filepair *p, struct diff_options *o,
11801255
builtin_diffstat(name, other, p->one, p->two, diffstat, complete_rewrite);
11811256
}
11821257

1258+
static void run_checkdiff(struct diff_filepair *p, struct diff_options *o)
1259+
{
1260+
const char *name;
1261+
const char *other;
1262+
1263+
if (DIFF_PAIR_UNMERGED(p)) {
1264+
/* unmerged */
1265+
return;
1266+
}
1267+
1268+
name = p->one->path;
1269+
other = (strcmp(name, p->two->path) ? p->two->path : NULL);
1270+
1271+
diff_fill_sha1_info(p->one);
1272+
diff_fill_sha1_info(p->two);
1273+
1274+
builtin_checkdiff(name, other, p->one, p->two);
1275+
}
1276+
11831277
void diff_setup(struct diff_options *options)
11841278
{
11851279
memset(options, 0, sizeof(*options));
@@ -1205,7 +1299,8 @@ int diff_setup_done(struct diff_options *options)
12051299
* recursive bits for other formats here.
12061300
*/
12071301
if ((options->output_format == DIFF_FORMAT_PATCH) ||
1208-
(options->output_format == DIFF_FORMAT_DIFFSTAT))
1302+
(options->output_format == DIFF_FORMAT_DIFFSTAT) ||
1303+
(options->output_format == DIFF_FORMAT_CHECKDIFF))
12091304
options->recursive = 1;
12101305

12111306
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)
12881383
}
12891384
else if (!strcmp(arg, "--stat"))
12901385
options->output_format = DIFF_FORMAT_DIFFSTAT;
1386+
else if (!strcmp(arg, "--check"))
1387+
options->output_format = DIFF_FORMAT_CHECKDIFF;
12911388
else if (!strcmp(arg, "--summary"))
12921389
options->summary = 1;
12931390
else if (!strcmp(arg, "--patch-with-stat")) {
@@ -1610,6 +1707,19 @@ static void diff_flush_stat(struct diff_filepair *p, struct diff_options *o,
16101707
run_diffstat(p, o, diffstat);
16111708
}
16121709

1710+
static void diff_flush_checkdiff(struct diff_filepair *p,
1711+
struct diff_options *o)
1712+
{
1713+
if (diff_unmodified_pair(p))
1714+
return;
1715+
1716+
if ((DIFF_FILE_VALID(p->one) && S_ISDIR(p->one->mode)) ||
1717+
(DIFF_FILE_VALID(p->two) && S_ISDIR(p->two->mode)))
1718+
return; /* no tree diffs in patch format */
1719+
1720+
run_checkdiff(p, o);
1721+
}
1722+
16131723
int diff_queue_is_empty(void)
16141724
{
16151725
struct diff_queue_struct *q = &diff_queued_diff;
@@ -1740,6 +1850,9 @@ static void flush_one_pair(struct diff_filepair *p,
17401850
case DIFF_FORMAT_DIFFSTAT:
17411851
diff_flush_stat(p, options, diffstat);
17421852
break;
1853+
case DIFF_FORMAT_CHECKDIFF:
1854+
diff_flush_checkdiff(p, options);
1855+
break;
17431856
case DIFF_FORMAT_PATCH:
17441857
diff_flush_patch(p, options);
17451858
break;

diff.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ extern int diff_queue_is_empty(void);
153153
#define DIFF_FORMAT_NAME 4
154154
#define DIFF_FORMAT_NAME_STATUS 5
155155
#define DIFF_FORMAT_DIFFSTAT 6
156+
#define DIFF_FORMAT_CHECKDIFF 7
156157

157158
extern void diff_flush(struct diff_options*);
158159

0 commit comments

Comments
 (0)