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