[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [bug-diffutils] [patch] --ignore-file-name-case
From: |
Paul Eggert |
Subject: |
Re: [bug-diffutils] [patch] --ignore-file-name-case |
Date: |
Sat, 13 Aug 2011 13:32:05 -0700 |
User-agent: |
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.18) Gecko/20110617 Thunderbird/3.1.11 |
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
address@hidden/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;
+}