[HALF A PATCH] Teach the '--exclude' option to 'diff --no-index'

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



With this patch, it is possible to exclude files based on basename
patterns.  Example:

	$ git diff --no-index -x Makefile -x Makefile.in a/ b/

In this example, the recursive diff between a/ and b/ will be shown
modulo changes in files named 'Makefile' or 'Makefile.in'.

Signed-off-by: Johannes Schindelin <johannes.schindelin@xxxxxx>
---

	Michael wrote:

	> I can't think offhand of a more portable tool that could replace 
	> "diff -r -x" here (suggestions, anyone?).

	Maybe something like this?

	Note: before it can be included in git.git, documentation and 
	tests have to be added; also, it might be a good idea to extend it 
	to the "non-no-index" case (maybe I can beat Peff in the number of 
	double negations one day...)

	So why only half a patch?  From time to time, I have to remember 
	that I work on Git for fun.  And this was the fun part, as far as 
	I am concerned.

 diff-no-index.c |   50 ++++++++++++++++++++++++++++++++++++++++++++------
 diff.c          |    9 +++++++++
 diff.h          |    6 ++++++
 3 files changed, 59 insertions(+), 6 deletions(-)

diff --git a/diff-no-index.c b/diff-no-index.c
index 0a14268..0dc924a 100644
--- a/diff-no-index.c
+++ b/diff-no-index.c
@@ -16,7 +16,42 @@
 #include "builtin.h"
 #include "string-list.h"
 
-static int read_directory(const char *path, struct string_list *list)
+void add_basename_exclude(const char *exclude, struct diff_options *opts)
+{
+	if (!opts->basename_excludes) {
+		opts->basename_excludes =
+			xcalloc(sizeof(struct string_list), 1);
+		opts->basename_excludes->strdup_strings = 1;
+	}
+
+	string_list_append(exclude, opts->basename_excludes);
+}
+
+int basename_is_excluded(const char *basename, struct diff_options *options)
+{
+	int i;
+
+	if (!options->basename_excludes)
+		return 0;
+
+	for (i = 0; i < options->basename_excludes->nr; i++)
+		if (!fnmatch(options->basename_excludes->items[i].string,
+					basename, 0))
+			return 1;
+	return 0;
+}
+
+void free_basename_excludes(struct diff_options *options)
+{
+	if (!options->basename_excludes)
+		return;
+	string_list_clear(options->basename_excludes, 0);
+	free(options->basename_excludes);
+	options->basename_excludes = NULL;
+}
+
+static int read_directory(const char *path, struct string_list *list,
+	struct diff_options *options)
 {
 	DIR *dir;
 	struct dirent *e;
@@ -25,7 +60,8 @@ static int read_directory(const char *path, struct string_list *list)
 		return error("Could not open directory %s", path);
 
 	while ((e = readdir(dir)))
-		if (strcmp(".", e->d_name) && strcmp("..", e->d_name))
+		if (strcmp(".", e->d_name) && strcmp("..", e->d_name) &&
+				!basename_is_excluded(e->d_name, options))
 			string_list_insert(e->d_name, list);
 
 	closedir(dir);
@@ -63,9 +99,9 @@ static int queue_diff(struct diff_options *o,
 		struct string_list p1 = {NULL, 0, 0, 1}, p2 = {NULL, 0, 0, 1};
 		int len1 = 0, len2 = 0, i1, i2, ret = 0;
 
-		if (name1 && read_directory(name1, &p1))
+		if (name1 && read_directory(name1, &p1, o))
 			return -1;
-		if (name2 && read_directory(name2, &p2)) {
+		if (name2 && read_directory(name2, &p2, o)) {
 			string_list_clear(&p1, 0);
 			return -1;
 		}
@@ -177,10 +213,12 @@ void diff_no_index(struct rev_info *revs,
 			i++;
 			break;
 		}
-		if (!strcmp(argv[i], "--no-index"))
-			no_index = 1;
 		if (argv[i][0] != '-')
 			break;
+		if (!strcmp(argv[i], "--no-index"))
+			no_index = 1;
+		else if (!strcmp(argv[i], "-x"))
+			i++;
 	}
 
 	if (!no_index && !nongit) {
diff --git a/diff.c b/diff.c
index 55d73a1..29c0dd5 100644
--- a/diff.c
+++ b/diff.c
@@ -2653,6 +2653,14 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
 	else if (!prefixcmp(arg, "--output=")) {
 		options->file = fopen(arg + strlen("--output="), "w");
 		options->close_file = 1;
+	}
+	else if (!prefixcmp(arg, "--exclude="))
+		add_basename_exclude( arg + strlen("--exclude="), options);
+	else if (!strcmp(arg, "-x")) {
+		if (ac < 2)
+			die ("-x needs a parameter");
+		add_basename_exclude(av[1], options);
+		return 2;
 	} else
 		return 0;
 	return 1;
@@ -3306,6 +3314,7 @@ free_queue:
 	q->nr = q->alloc = 0;
 	if (options->close_file)
 		fclose(options->file);
+	free_basename_excludes(options);
 }
 
 static void diffcore_apply_filter(const char *filter)
diff --git a/diff.h b/diff.h
index 6703a4f..38f3acd 100644
--- a/diff.h
+++ b/diff.h
@@ -113,6 +113,7 @@ struct diff_options {
 	add_remove_fn_t add_remove;
 	diff_format_fn_t format_callback;
 	void *format_callback_data;
+	struct string_list *basename_excludes;
 };
 
 enum color_diff {
@@ -267,4 +268,9 @@ extern void diff_no_index(struct rev_info *, int, const char **, int, const char
 
 extern int index_differs_from(const char *def, int diff_flags);
 
+extern int basename_is_excluded(const char *path, struct diff_options *options);
+extern void add_basename_exclude(const char *exclude,
+		struct diff_options *options);
+extern void free_basename_excludes(struct diff_options *options);
+
 #endif /* DIFF_H */
-- 
1.6.2.rc1.350.g6caf6
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux