Thanks for reporting that. I had forgotten about the GNU patch
convention. I installed the attached change to GNU diffutils; please
give it a try.
GNU patch still mishandles file names containing multi-byte characters
in some non-UTF-8 locales, but that can be fixed later when someone gets
around to it.From 774b942f700f0045d307923435d287c182364699 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Tue, 19 Sep 2023 23:34:43 -0700
Subject: [PATCH] diff: go back to C quoting for diff -c/-u headers
Gleb Fotengauer-Malinovskiy reported <https://bugs/gnu/org/66095>
that the recent change to quoting style broke GNU patch.
* src/util.c: Include quotearg.h.
(current_name): New static var, replacing the the old
current_name0 and current_name1. All uses changed.
(begin_output): Go back to quoting file names for C,
not for the shell, when they contain troublesome characters.
This is not a simple revert, as the revised code handles
multi-byte characters even in non-UTF-8 locales.
* tests/filename-quoting: Revert previous change to this file.
---
NEWS | 10 +++++-----
src/util.c | 16 ++++++++++------
tests/filename-quoting | 18 +++++++++---------
3 files changed, 24 insertions(+), 20 deletions(-)
diff --git a/NEWS b/NEWS
index df5c003..3638ee3 100644
--- a/NEWS
+++ b/NEWS
@@ -4,19 +4,19 @@ GNU diffutils NEWS -*- outline -*-
** Improvements
- Programs now quote file names more consistently.
+ Programs now quote file names more consistently in diagnostics.
For example; "cmp 'none of' /etc/passwd" now might output
"cmp: EOF on ‘none of’ which is empty" instead of outputting
"cmp: EOF on none of which is empty". In diagnostic messages
that traditionally omit quotes and where backward compatibility
- seems to be important, programs continue to omit quotes unless they
+ seems to be important, programs continue to omit quotes unless
a file name contains shell metacharacters, in which case programs
use shell quoting. For example, although diff continues to output
"Only in a: b" as before for most file names, it now outputs
"Only in 'a: b': 'c: d'" instead of "Only in a: b: c: d" because the
- file names 'a: b' and 'c: d' contain spaces. Lastly, diff -c and -u
- headers now quote file names for the shell when needed, instead of
- using their own idiosyncratic quoting style.
+ file names 'a: b' and 'c: d' contain spaces. For compatibility
+ with previous practice, diff -c and -u headers continue to quote for
+ C rather than for the shell.
diff now outputs more information when symbolic links differ, e.g.,
"Symbolic links ‘d/f’ -> ‘a’ and ‘e/f’ -> ‘b’ differ", not just
diff --git a/src/util.c b/src/util.c
index 9d6df25..c269918 100644
--- a/src/util.c
+++ b/src/util.c
@@ -26,6 +26,7 @@
#include <error.h>
#include <flexmember.h>
#include <mcel.h>
+#include <quotearg.h>
#include <system-quote.h>
#include <xalloc.h>
@@ -406,8 +407,7 @@ cleanup_signal_handlers (void)
}
}
-static char const *current_name0;
-static char const *current_name1;
+static char const *current_name[2];
static bool currently_recursive;
static bool colors_enabled;
@@ -819,8 +819,8 @@ check_color_output (bool is_pipe)
void
setup_output (char const *name0, char const *name1, bool recursive)
{
- current_name0 = name0;
- current_name1 = name1;
+ current_name[0] = name0;
+ current_name[1] = name1;
currently_recursive = recursive;
outfile = nullptr;
}
@@ -836,8 +836,12 @@ begin_output (void)
if (outfile)
return;
- char const *names[2] = {squote (0, current_name0),
- squote (1, current_name1)};
+ char const *names[2];
+ for (int f = 0; f < 2; f++)
+ names[f] = quotearg_n_style (f,
+ (strchr (current_name[f], ' ')
+ ? c_quoting_style : c_maybe_quoting_style),
+ current_name[f]);
/* Construct the header of this piece of diff. */
/* POSIX 1003.1-2017 specifies this format. But there are some bugs in
diff --git a/tests/filename-quoting b/tests/filename-quoting
index 21e8c81..2e75a03 100755
--- a/tests/filename-quoting
+++ b/tests/filename-quoting
@@ -6,23 +6,23 @@
fail=0
cat <<EOF > exp- || fail=1
-diff -N -r 'a/ ' 'b/ '
+diff -N -r "a/ " "b/ "
0a1
> space
EOF
cat <<EOF > exp--u || fail=1
-diff -N -r -u 'a/ ' 'b/ '
---- 'a/ '
-+++ 'b/ '
+diff -N -r -u "a/ " "b/ "
+--- "a/ "
++++ "b/ "
@@ -0,0 +1 @@
+space
EOF
cat <<EOF > exp--c || fail=1
-diff -N -r -c 'a/ ' 'b/ '
-*** 'a/ '
---- 'b/ '
+diff -N -r -c "a/ " "b/ "
+*** "a/ "
+--- "b/ "
***************
*** 0 ****
--- 1 ----
@@ -41,8 +41,8 @@ done
rm -f "b/ "
cat <<EOF > exp || fail=1
---- 'a/'$'\t'
-+++ 'b/'$'\001'
+--- "a/\t"
++++ "b/\001"
@@ -1 +1 @@
-tab
+one
--
2.39.2