bug-diffutils
[Top][All Lists]
Advanced

[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;
+}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]