Hello,

I propose the attached patch. GNU tar needs it to fully implement
gitignore excludes.

Best regards,
Sergey

PS: Please Cc: I'm not subscribed.

>From 8d8198fa1efa3e33f3712afff2e99f98d44db468 Mon Sep 17 00:00:00 2001
From: Sergey Poznyakoff <[email protected]>
Date: Sun, 16 Aug 2026 21:27:04 +0300
Subject: [PATCH] exclude: new function, excluded_file_name_ext

The new function is similar to excluded_file_name, except that in
addition to returning the boolean status, it returns also, in memory
location passed as its last argument, a boolean indicating whether
a matching entry was actually found in one of the exclusion segments.

* lib/exclude.c (excluded_file_name_ext): New function, derived from
the original excluded_file_name.
* lib/exclude.h (excluded_file_name_ext): New proto.
(excluded_file_name): Rewrite as a wrapper over excluded_file_name_ext.
---
 lib/exclude.c | 16 +++++++++-------
 lib/exclude.h |  7 ++++++-
 2 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/lib/exclude.c b/lib/exclude.c
index 6a8604ec1b..0f5ebec2bc 100644
--- a/lib/exclude.c
+++ b/lib/exclude.c
@@ -458,7 +458,7 @@ file_name_matches (struct exclude_segment const *seg, char const *f,
 /* Return true if EX excludes F.  */

 bool
-excluded_file_name (struct exclude const *ex, char const *f)
+excluded_file_name_ext (struct exclude const *ex, char const *f, bool *pfound)
 {
   /* If no patterns are given, the default is to include.  */
   if (!ex->head)
@@ -466,6 +466,7 @@ excluded_file_name (struct exclude const *ex, char const *f)

   bool invert = false;
   char *filename = nullptr;
+  bool found = false;

   /* Scan through the segments, reporting the status of the first match.
      The segments are in reverse order, so this reports the status of
@@ -477,14 +478,13 @@ excluded_file_name (struct exclude const *ex, char const *f)
         {
           if (!filename)
             filename = xmalloc (strlen (f) + 1);
-          if (file_name_matches (seg, f, filename))
-            break;
+          found = file_name_matches (seg, f, filename);
         }
       else
-        {
-          if (file_pattern_matches (seg, f))
-            break;
-        }
+	found = file_pattern_matches (seg, f);
+
+      if (found)
+	break;

       if (! seg->next)
         {
@@ -500,6 +500,8 @@ excluded_file_name (struct exclude const *ex, char const *f)
     }

   free (filename);
+  if (pfound)
+    *pfound = found;
   return invert ^ ! (seg->options & EXCLUDE_INCLUDE);
 }

diff --git a/lib/exclude.h b/lib/exclude.h
index c217a1e4e6..7331003c70 100644
--- a/lib/exclude.h
+++ b/lib/exclude.h
@@ -68,7 +68,12 @@ int add_exclude_file (void (*) (struct exclude *, char const *, int),
                       struct exclude *, char const *, int, char);
 int add_exclude_fp (void (*) (struct exclude *, char const *, int, void *),
                     struct exclude *, FILE *, int, char, void *);
-bool excluded_file_name (struct exclude const *, char const *);
+bool excluded_file_name_ext (struct exclude const *, char const *, bool *);
+static inline bool
+excluded_file_name (struct exclude const *ex, char const *f)
+{
+  return excluded_file_name_ext (ex, f, NULL);
+}
 void exclude_add_pattern_buffer (struct exclude *ex, char *buf);
 bool exclude_fnmatch (char const *, char const *, int);

--
2.35.1

Reply via email to