Hello,
I would like to add a feature to the diff utility. The feature would allow
exclude patterns to match directories as well as base filenames so entire
directories can easily be ignored.
The feature adds the option `--exclude-directory` which is intended to be
used with `--exclude=PAT` or `--exclude-from=FILE`.
I've attached a patch file which adds this feature along with a couple of
tests and documentation.
Is this something that can be added to diff?
David
--
Securely sent with Tutanota. Claim your encrypted mailbox today!
https://tutanota.com
diff --git a/src/diff.c b/src/diff.c
index 9bc1d96..4420623 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -122,6 +122,7 @@ enum
NO_IGNORE_FILE_NAME_CASE_OPTION,
NORMAL_OPTION,
SDIFF_MERGE_ASSIST_OPTION,
+ EXCLUDE_DIRECTORY_OPTION,
STRIP_TRAILING_CR_OPTION,
SUPPRESS_BLANK_EMPTY_OPTION,
SUPPRESS_COMMON_LINES_OPTION,
@@ -208,6 +209,7 @@ static struct option const longopts[] =
{"show-function-line", 1, 0, 'F'},
{"side-by-side", 0, 0, 'y'},
{"speed-large-files", 0, 0, 'H'},
+ {"exclude-directory", 0, 0, EXCLUDE_DIRECTORY_OPTION},
{"starting-file", 1, 0, 'S'},
{"strip-trailing-cr", 0, 0, STRIP_TRAILING_CR_OPTION},
{"suppress-blank-empty", 0, 0, SUPPRESS_BLANK_EMPTY_OPTION},
@@ -592,6 +594,10 @@ main (int argc, char **argv)
sdiff_merge_assist = true;
break;
+ case EXCLUDE_DIRECTORY_OPTION:
+ exclude_directory = true;
+ break;
+
case STRIP_TRAILING_CR_OPTION:
strip_trailing_cr = true;
break;
@@ -911,6 +917,7 @@ static char const * const option_help_msgid[] = {
N_(" --no-ignore-file-name-case consider case when comparing file names"),
N_("-x, --exclude=PAT exclude files that match PAT"),
N_("-X, --exclude-from=FILE exclude files that match any pattern in FILE"),
+ N_(" --exclude-directory exclude directories matching exclude pattern"),
N_("-S, --starting-file=FILE start with FILE when comparing directories"),
N_(" --from-file=FILE1 compare FILE1 to all operands;\n"
" FILE1 can be a directory"),
diff --git a/src/diff.h b/src/diff.h
index 0983e7c..413790a 100644
--- a/src/diff.h
+++ b/src/diff.h
@@ -224,6 +224,9 @@ XTERN bool speed_large_files;
/* Patterns that match file names to be excluded. */
XTERN struct exclude *excluded;
+/* Include directory as part of exclude matching. */
+XTERN bool exclude_directory;
+
/* Don't discard lines. This makes things slower (sometimes much
slower) but will find a guaranteed minimal set of changes. */
XTERN bool minimal;
diff --git a/src/dir.c b/src/dir.c
index c8aa6a5..e9c70d6 100644
--- a/src/dir.c
+++ b/src/dir.c
@@ -96,8 +96,15 @@ dir_read (struct file_data const *dir, struct dirdata *dirdata)
&& (d_name[1] == 0 || (d_name[1] == '.' && d_name[2] == 0)))
continue;
- if (excluded_file_name (excluded, d_name))
- continue;
+ /* Exclude filename matches from diff */
+ if (exclude_directory) {
+ if (excluded_file_name (excluded,
+ file_name_concat(dir->name, d_name, NULL)))
+ continue;
+ } else {
+ if (excluded_file_name (excluded, d_name))
+ continue;
+ }
while (data_alloc < data_used + d_size)
{
diff --git a/tests/exclude-directory b/tests/exclude-directory
new file mode 100755
index 0000000..825154a
--- /dev/null
+++ b/tests/exclude-directory
@@ -0,0 +1,48 @@
+#!/bin/sh
+# exclude directory tests
+
+. "${srcdir=.}/init.sh"; path_prepend_ ../src
+
+TZ=UTC0
+export TZ
+
+fail=0
+
+# Generate directory structure
+mkdir a
+mkdir b
+echo ac > a/c
+echo bc > b/c
+
+epoch='1970-01-01 00:00:00'
+touch --date="$epoch" a b a/c b/c
+
+gen_exp_default()
+{
+ printf '%s' \
+"diff -r '--exclude=b/*' a/c b/c
+1c1
+< ac
+---
+> bc
+"
+}
+
+gen_exp_excluded()
+{
+ printf '%s' \
+"Only in a: c
+"
+}
+
+diff -r --exclude="b/*" a b > out
+test $? = 1 || fail=1
+gen_exp_default > exp || framework_failure_
+compare exp out || fail=1
+
+diff -r --exclude-directory --exclude="b/*" a b > out
+test $? = 1 || fail=1
+gen_exp_excluded > exp || framework_failure_
+compare exp out || fail=1
+
+Exit $fail