diff: -N, --unidirectional-new-file now compare to "-" too

* NEWS: Document this.
* doc/diffutils.texi (Comparing Directories): Likewise.
Also, document that these options work at the top level.
* src/diff.c (compare_files): Treat EBADF like ENOENT, to handle
the case where "-" is closed.  Allow the other file to be
STDIN_FILENO, in case it's "-".
* tests/Makefile.am (TESTS): Add new-file.
* tests/new-file: New file.
This commit is contained in:
Paul Eggert 2012-02-04 22:10:40 -08:00
parent 62ca21c8c1
commit 7f2f4bb365
5 changed files with 67 additions and 24 deletions

5
NEWS
View File

@ -2,6 +2,11 @@ GNU diffutils NEWS -*- outline -*-
* Noteworthy changes in release ?.? (????-??-??) [?]
** New features
--new-file (-N) and --unidirectional-new-file now allow comparisons to "-".
A standard input that's closed acts like a nonexistent file.
* Noteworthy changes in release 3.2 (2011-09-02) [stable]

View File

@ -1784,20 +1784,23 @@ subdirectories' files, but if you use the @option{-r} or
@option{--recursive} option, it compares every corresponding pair of files
in the directory trees, as many levels deep as they go.
For file names that are in only one of the directories, @command{diff}
normally does not show the contents of the file that exists; it reports
only that the file exists in that directory and not in the other. You
can make @command{diff} act as though the file existed but was empty in the
other directory, so that it outputs the entire contents of the file that
If only one file exists, @command{diff} normally does not show its
contents; it merely reports that one file exists but the other does
not. You can make @command{diff} act as though the missing file is
empty, so that it outputs the entire contents of the file that
actually exists. (It is output as either an insertion or a
deletion, depending on whether it is in the first or the second
directory given.) To do this, use the @option{--new-file} (@option{-N})
option.
deletion, depending on whether the missing file is in the first or the
second position.) To do this, use the @option{--new-file}
(@option{-N}) option. This option affects command-line arguments as
well as files found via directory traversal; for example, @samp{diff
-N a b} treats @file{a} as empty if @file{a} does not exist but
@file{b} does, and similarly @samp{diff -N - b} treats standard input
as empty if it is closed but @file{b} exists.
If the older directory contains one or more large files that are not in
If the older directory contains large files that are not in
the newer directory, you can make the patch smaller by using the
@option{--unidirectional-new-file} option instead of @option{-N}.
This option is like @option{-N} except that it only inserts the contents
This option is like @option{-N} except that it inserts the contents only
of files that appear in the second directory but not the first (that is,
files that were added). At the top of the patch, write instructions for
the user applying the patch to remove the files that were deleted before
@ -3843,9 +3846,8 @@ specifies the number of lines affected. @xref{RCS}.
@item -N
@itemx --new-file
In directory comparison, if a file is found in only one directory,
treat it as present but empty in the other directory. @xref{Comparing
Directories}.
If one file is missing, treat it as present but empty.
@xref{Comparing Directories}.
@item --new-group-format=@var{format}
Use @var{format} to output a group of lines taken from just the second
@ -3937,8 +3939,7 @@ Use @var{format} to output a line common to both files in if-then-else
format. @xref{Line Formats}.
@item --unidirectional-new-file
When comparing directories, if a file appears only in the second
directory of the two, treat it as present but empty in the other.
If a first file is missing, treat it as present but empty.
@xref{Comparing Directories}.
@item -U @var{lines}

View File

@ -92,15 +92,11 @@ static bool binary;
enum { binary = true };
#endif
/* When comparing directories, if a file appears only in one
directory, treat it as present but empty in the other (-N).
Then 'patch' would create the file with appropriate contents. */
/* If one file is missing, treat it as present but empty (-N). */
static bool new_file;
/* When comparing directories, if a file appears only in the second
directory of the two, treat it as present but empty in the other
(--unidirectional-new-file).
Then 'patch' would create the file with appropriate contents. */
/* If the first file is missing, treat it as present but empty
(--unidirectional-new-file). */
static bool unidirectional_new_file;
/* Report files compared that are the same (-s).
@ -1155,9 +1151,11 @@ compare_files (struct comparison const *parent,
? (S_ISREG (cmp.file[f].stat.st_mode)
&& ! (cmp.file[f].stat.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO))
&& cmp.file[f].stat.st_size == 0)
: (cmp.file[f].desc == ERRNO_ENCODE (ENOENT)
: ((cmp.file[f].desc == ERRNO_ENCODE (ENOENT)
|| cmp.file[f].desc == ERRNO_ENCODE (EBADF))
&& ! parent
&& cmp.file[1 - f].desc == UNOPENED)))
&& (cmp.file[1 - f].desc == UNOPENED
|| cmp.file[1 - f].desc == STDIN_FILENO))))
cmp.file[f].desc = NONEXISTENT;
for (f = 0; f < 2; f++)

View File

@ -8,6 +8,7 @@ TESTS = \
help-version \
function-line-vs-leading-space \
label-vs-func \
new-file \
no-dereference \
no-newline-at-eof \
stdin

38
tests/new-file Executable file
View File

@ -0,0 +1,38 @@
#!/bin/sh
# Test --new-file (-N) and --unidirectional-new-file.
. "${srcdir=.}/init.sh"; path_prepend_ ../src
fail=0
echo a > a || fail=1
echo '0a1
> a' > exp || fail=1
diff -N - a <&- > out; test $? = 1 || fail=1
compare exp out || fail=1
diff --unidirectional-new-file - a <&- > out; test $? = 1 || fail=1
compare exp out || fail=1
diff -N b - < a > out; test $? = 1 || fail=1
compare exp out || fail=1
diff --unidirectional-new-file b - < a > out; test $? = 1 || fail=1
compare exp out || fail=1
echo '1d0
< a' > exp || fail=1
diff -N a - <&- > out; test $? = 1 || fail=1
compare exp out || fail=1
diff --unidirectional-new-file a - <&- > out; test $? = 2 || fail=1
diff -N - b < a > out; test $? = 1 || fail=1
compare exp out || fail=1
diff --unidirectional-new-file - b < a > out; test $? = 2 || fail=1
Exit $fail