aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Schindelin <Johannes.Schindelin@gmx.de>2006-05-20 23:43:13 +0200
committerJunio C Hamano <junkio@cox.net>2006-05-21 01:16:09 -0700
commit8824689884a5673f803d77cda499f83b84145a06 (patch)
tree80b6437ce3928cf4e299c7ecd52d52e3e18a6eb5
parent845ae27bf8161063d7e2e1ca2a76b05bf5d07192 (diff)
downloadgit-8824689884a5673f803d77cda499f83b84145a06.tar.gz
git-8824689884a5673f803d77cda499f83b84145a06.tar.xz
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>
-rw-r--r--diff.c115
-rw-r--r--diff.h1
2 files changed, 115 insertions, 1 deletions
diff --git a/diff.c b/diff.c
index e16e0bfc0..af5db0ec1 100644
--- a/diff.c
+++ b/diff.c
@@ -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,
}
}
+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,
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)
* 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)
}
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,
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,
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;
diff --git a/diff.h b/diff.h
index 3027974c1..c672277df 100644
--- a/diff.h
+++ b/diff.h
@@ -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*);