Thanks for following up on this. I looked at the patch more carefully and found a few minor problems:
* The documentation in NEWS and in diffutils.texi could use an example or two, for clarity. * The setjmp business wasn't quite right. locale_specific_sorting should always be 1 the 1st time through. There's no need for a 2nd time through, in this function, as the code can fall back on just using the file. * if (X) /* do nothing; /*; else Y -> if (! X) Y * Memory leak if dir_read returns 0. * When doing "diff --ignore-file-name-case DIR FILE", if several file names in DIR match FILE, but one matches exactly, use the exact match. * In find_dir_file_pathname, if the directory can't be read, fall back on just using the file. Here's what I pushed. Comments are welcome and please give it a try if you have the time. diff: --ignore-file-name-case now applies at top level too Derived from Tim Waugh's patch in: http://lists.gnu.org/archive/html/bug-diffutils/2011-08/msg00034.html * NEWS, doc/diffutils.texi (diff Options): Document this. * src/diff.c (compare_files): Implement this, by using find_dir_file_pathname. * src/diff.h (find_dir_file_pathname): New decl. * src/dir.c: Include filenamecat.h. (find_dir_file_pathname): New function. diff --git a/NEWS b/NEWS index 42d9358..72f6395 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ GNU diffutils NEWS -*- outline -*- * Noteworthy changes in release ?.? (????-??-??) [?] +** Changes in behavior + + --ignore-file-name-case now applies at the top level too. + For example, "diff dir inIt" might compare "dir/Init" to "inIt". * Noteworthy changes in release 3.1 (2011-08-10) [stable] diff --git a/doc/diffutils.texi b/doc/diffutils.texi index ee419a1..f29e9a1 100644 --- a/doc/diffutils.texi +++ b/doc/diffutils.texi @@ -3802,7 +3802,10 @@ Ignore changes that just insert or delete lines that match @var{regexp}. @xref{Specified Lines}. @item --ignore-file-name-case -Ignore case when comparing file names during recursive comparison. +Ignore case when comparing file names. For example, recursive +comparison of @file{d} to @file{e} might compare the contents of +@file{d/Init} and @file{e/inIt}. At the top level, @samp{diff d inIt} +might compare the contents of @file{d/Init} and @file{inIt}. @xref{Comparing Directories}. @item -l diff --git a/src/diff.c b/src/diff.c index 6a08f36..1e334b7 100644 --- a/src/diff.c +++ b/src/diff.c @@ -1170,7 +1170,7 @@ compare_files (struct comparison const *parent, char const *fnm = cmp.file[fnm_arg].name; char const *dir = cmp.file[dir_arg].name; char const *filename = cmp.file[dir_arg].name = free0 - = file_name_concat (dir, last_component (fnm), NULL); + = find_dir_file_pathname (dir, last_component (fnm)); if (STREQ (fnm, "-")) fatal ("cannot compare `-' to a directory"); diff --git a/src/diff.h b/src/diff.h index 88332a5..b1c90c7 100644 --- a/src/diff.h +++ b/src/diff.h @@ -327,6 +327,7 @@ extern void print_context_script (struct change *, bool); extern int diff_dirs (struct comparison const *, int (*) (struct comparison const *, char const *, char const *)); +char *find_dir_file_pathname (char const *, char const *); /* ed.c */ extern void print_ed_script (struct change *); diff --git a/src/dir.c b/src/dir.c index 30bef2c..20626d1 100644 --- a/src/dir.c +++ b/src/dir.c @@ -21,6 +21,7 @@ #include "diff.h" #include <error.h> #include <exclude.h> +#include <filenamecat.h> #include <setjmp.h> #include <xalloc.h> @@ -316,3 +317,48 @@ dir_loop (struct comparison const *cmp, int i) return true; return false; } + +/* Find a matching filename in a directory. */ + +char * +find_dir_file_pathname (char const *dir, char const *file) +{ + char *val; + char const *match = file; + struct dirdata dirdata; + dirdata.names = NULL; + dirdata.data = NULL; + + if (ignore_file_name_case) + { + struct file_data filedata; + filedata.name = dir; + filedata.desc = 0; + + if (dir_read (&filedata, &dirdata)) + { + locale_specific_sorting = true; + if (setjmp (failed_locale_specific_sorting)) + match = file; /* longjmp may mess up MATCH. */ + else + { + for (char const **p = dirdata.names; *p; p++) + if (compare_names (*p, file) == 0) + { + if (file_name_cmp (*p, file) == 0) + { + match = *p; + break; + } + if (match == file) + match = *p; + } + } + } + } + + val = file_name_concat (dir, match, NULL); + free (dirdata.names); + free (dirdata.data); + return val; +}
