Merge branch 'nd/no-more-fnmatch'
authorJunio C Hamano <gitster@pobox.com>
Fri, 14 Mar 2014 21:25:31 +0000 (14:25 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 14 Mar 2014 21:25:31 +0000 (14:25 -0700)
We started using wildmatch() in place of fnmatch(3); complete the
process and stop using fnmatch(3).

* nd/no-more-fnmatch:
actually remove compat fnmatch source code
stop using fnmatch (either native or compat)
Revert "test-wildmatch: add "perf" command to compare wildmatch and fnmatch"
use wildmatch() directly without fnmatch() wrapper

1  2 
Makefile
builtin/apply.c
builtin/describe.c
diffcore-order.c
dir.c
git-compat-util.h
revision.c
diff --combined Makefile
index d4ce53a71b3ffd3b2a9d115279880d3e1aeb03a6,ca38f994043faf8749928c6cf55426a2af46e3d7..a20fbafd6249e13af9d6eb63e5626c0d32fb69b8
+++ b/Makefile
@@@ -101,14 -101,6 +101,6 @@@ all:
  #
  # Define NO_MKSTEMPS if you don't have mkstemps in the C library.
  #
- # Define NO_FNMATCH if you don't have fnmatch in the C library.
- #
- # Define NO_FNMATCH_CASEFOLD if your fnmatch function doesn't have the
- # FNM_CASEFOLD GNU extension.
- #
- # Define NO_WILDMATCH if you do not want to use Git's wildmatch
- # implementation as fnmatch
- #
  # Define NO_GECOS_IN_PWENT if you don't have pw_gecos in struct passwd
  # in the C library.
  #
@@@ -555,7 -547,6 +547,7 @@@ TEST_PROGRAMS_NEED_X += test-dat
  TEST_PROGRAMS_NEED_X += test-delta
  TEST_PROGRAMS_NEED_X += test-dump-cache-tree
  TEST_PROGRAMS_NEED_X += test-genrandom
 +TEST_PROGRAMS_NEED_X += test-hashmap
  TEST_PROGRAMS_NEED_X += test-index-version
  TEST_PROGRAMS_NEED_X += test-line-buffer
  TEST_PROGRAMS_NEED_X += test-match-trees
@@@ -664,8 -655,6 +656,8 @@@ LIB_H += diff.
  LIB_H += diffcore.h
  LIB_H += dir.h
  LIB_H += exec_cmd.h
 +LIB_H += ewah/ewok.h
 +LIB_H += ewah/ewok_rlw.h
  LIB_H += fetch-pack.h
  LIB_H += fmt-merge-msg.h
  LIB_H += fsck.h
@@@ -674,7 -663,7 +666,7 @@@ LIB_H += git-compat-util.
  LIB_H += gpg-interface.h
  LIB_H += graph.h
  LIB_H += grep.h
 -LIB_H += hash.h
 +LIB_H += hashmap.h
  LIB_H += help.h
  LIB_H += http.h
  LIB_H += kwset.h
@@@ -693,10 -682,8 +685,10 @@@ LIB_H += notes-merge.
  LIB_H += notes-utils.h
  LIB_H += notes.h
  LIB_H += object.h
 +LIB_H += pack-objects.h
  LIB_H += pack-revindex.h
  LIB_H += pack.h
 +LIB_H += pack-bitmap.h
  LIB_H += parse-options.h
  LIB_H += patch-ids.h
  LIB_H += pathspec.h
@@@ -800,10 -787,6 +792,10 @@@ LIB_OBJS += dir.
  LIB_OBJS += editor.o
  LIB_OBJS += entry.o
  LIB_OBJS += environment.o
 +LIB_OBJS += ewah/bitmap.o
 +LIB_OBJS += ewah/ewah_bitmap.o
 +LIB_OBJS += ewah/ewah_io.o
 +LIB_OBJS += ewah/ewah_rlw.o
  LIB_OBJS += exec_cmd.o
  LIB_OBJS += fetch-pack.o
  LIB_OBJS += fsck.o
@@@ -811,7 -794,7 +803,7 @@@ LIB_OBJS += gettext.
  LIB_OBJS += gpg-interface.o
  LIB_OBJS += graph.o
  LIB_OBJS += grep.o
 -LIB_OBJS += hash.o
 +LIB_OBJS += hashmap.o
  LIB_OBJS += help.o
  LIB_OBJS += hex.o
  LIB_OBJS += ident.o
@@@ -835,10 -818,7 +827,10 @@@ LIB_OBJS += notes-cache.
  LIB_OBJS += notes-merge.o
  LIB_OBJS += notes-utils.o
  LIB_OBJS += object.o
 +LIB_OBJS += pack-bitmap.o
 +LIB_OBJS += pack-bitmap-write.o
  LIB_OBJS += pack-check.o
 +LIB_OBJS += pack-objects.o
  LIB_OBJS += pack-revindex.o
  LIB_OBJS += pack-write.o
  LIB_OBJS += pager.o
@@@ -1283,20 -1263,6 +1275,6 @@@ endi
  ifdef NO_STRTOULL
        COMPAT_CFLAGS += -DNO_STRTOULL
  endif
- ifdef NO_FNMATCH
-       COMPAT_CFLAGS += -Icompat/fnmatch
-       COMPAT_CFLAGS += -DNO_FNMATCH
-       COMPAT_OBJS += compat/fnmatch/fnmatch.o
- else
- ifdef NO_FNMATCH_CASEFOLD
-       COMPAT_CFLAGS += -Icompat/fnmatch
-       COMPAT_CFLAGS += -DNO_FNMATCH_CASEFOLD
-       COMPAT_OBJS += compat/fnmatch/fnmatch.o
- endif
- endif
- ifndef NO_WILDMATCH
-       COMPAT_CFLAGS += -DUSE_WILDMATCH
- endif
  ifdef NO_SETENV
        COMPAT_CFLAGS += -DNO_SETENV
        COMPAT_OBJS += compat/setenv.o
@@@ -2491,9 -2457,8 +2469,9 @@@ profile-clean
        $(RM) $(addsuffix *.gcno,$(addprefix $(PROFILE_DIR)/, $(object_dirs)))
  
  clean: profile-clean coverage-clean
 -      $(RM) *.o *.res block-sha1/*.o ppc/*.o compat/*.o compat/*/*.o xdiff/*.o vcs-svn/*.o \
 -              builtin/*.o $(LIB_FILE) $(XDIFF_LIB) $(VCSSVN_LIB)
 +      $(RM) *.o *.res block-sha1/*.o ppc/*.o compat/*.o compat/*/*.o
 +      $(RM) xdiff/*.o vcs-svn/*.o ewah/*.o builtin/*.o
 +      $(RM) $(LIB_FILE) $(XDIFF_LIB) $(VCSSVN_LIB)
        $(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git$X
        $(RM) $(TEST_PROGRAMS) $(NO_INSTALL)
        $(RM) -r bin-wrappers $(dep_dirs)
diff --combined builtin/apply.c
index a7e72d57ab0d23ef3becb3fd7d4564d6050efe6e,66e2eed539ab663556b769d4eb02ad7cbb002287..0189523798f31711ad74eaf3dd90ece9c12fa61a
@@@ -1943,7 -1943,13 +1943,7 @@@ static int parse_chunk(char *buffer, un
                                       size - offset - hdrsize, patch);
  
        if (!patchsize) {
 -              static const char *binhdr[] = {
 -                      "Binary files ",
 -                      "Files ",
 -                      NULL,
 -              };
                static const char git_binary[] = "GIT binary patch\n";
 -              int i;
                int hd = hdrsize + offset;
                unsigned long llen = linelen(buffer + hd, size - hd);
  
                                patchsize = 0;
                }
                else if (!memcmp(" differ\n", buffer + hd + llen - 8, 8)) {
 +                      static const char *binhdr[] = {
 +                              "Binary files ",
 +                              "Files ",
 +                              NULL,
 +                      };
 +                      int i;
                        for (i = 0; binhdr[i]; i++) {
                                int len = strlen(binhdr[i]);
                                if (len < size - hd &&
@@@ -4152,7 -4152,7 +4152,7 @@@ static int use_patch(struct patch *p
        /* See if it matches any of exclude/include rule */
        for (i = 0; i < limit_by_name.nr; i++) {
                struct string_list_item *it = &limit_by_name.items[i];
-               if (!fnmatch(it->string, pathname, 0))
+               if (!wildmatch(it->string, pathname, 0, NULL))
                        return (it->util != NULL);
        }
  
diff --combined builtin/describe.c
index dadd999c41f6aebe488d057e94e239dfb7dffaec,848acdf299ea8d4751e44027ab8af182742a87ac..24d740c8b1705f9c8993bd808c9a618acecc300c
@@@ -6,7 -6,7 +6,7 @@@
  #include "exec_cmd.h"
  #include "parse-options.h"
  #include "diff.h"
 -#include "hash.h"
 +#include "hashmap.h"
  #include "argv-array.h"
  
  #define SEEN          (1u << 0)
@@@ -25,7 -25,7 +25,7 @@@ static int longformat
  static int first_parent;
  static int abbrev = -1; /* unspecified */
  static int max_candidates = 10;
 -static struct hash_table names;
 +static struct hashmap names;
  static int have_util;
  static const char *pattern;
  static int always;
@@@ -37,7 -37,7 +37,7 @@@ static const char *diff_index_args[] = 
  };
  
  struct commit_name {
 -      struct commit_name *next;
 +      struct hashmap_entry entry;
        unsigned char peeled[20];
        struct tag *tag;
        unsigned prio:2; /* annotated tag = 2, tag = 1, head = 0 */
@@@ -50,12 -50,6 +50,12 @@@ static const char *prio_names[] = 
        "head", "lightweight", "annotated",
  };
  
 +static int commit_name_cmp(const struct commit_name *cn1,
 +              const struct commit_name *cn2, const void *peeled)
 +{
 +      return hashcmp(cn1->peeled, peeled ? peeled : cn2->peeled);
 +}
 +
  static inline unsigned int hash_sha1(const unsigned char *sha1)
  {
        unsigned int hash;
  
  static inline struct commit_name *find_commit_name(const unsigned char *peeled)
  {
 -      struct commit_name *n = lookup_hash(hash_sha1(peeled), &names);
 -      while (n && !!hashcmp(peeled, n->peeled))
 -              n = n->next;
 -      return n;
 -}
 -
 -static int set_util(void *chain, void *data)
 -{
 -      struct commit_name *n;
 -      for (n = chain; n; n = n->next) {
 -              struct commit *c = lookup_commit_reference_gently(n->peeled, 1);
 -              if (c)
 -                      c->util = n;
 -      }
 -      return 0;
 +      struct commit_name key;
 +      hashmap_entry_init(&key, hash_sha1(peeled));
 +      return hashmap_get(&names, &key, peeled);
  }
  
  static int replace_name(struct commit_name *e,
@@@ -112,10 -118,16 +112,10 @@@ static void add_to_known_names(const ch
        struct tag *tag = NULL;
        if (replace_name(e, prio, sha1, &tag)) {
                if (!e) {
 -                      void **pos;
                        e = xmalloc(sizeof(struct commit_name));
                        hashcpy(e->peeled, peeled);
 -                      pos = insert_hash(hash_sha1(peeled), e, &names);
 -                      if (pos) {
 -                              e->next = *pos;
 -                              *pos = e;
 -                      } else {
 -                              e->next = NULL;
 -                      }
 +                      hashmap_entry_init(e, hash_sha1(peeled));
 +                      hashmap_add(&names, e);
                        e->path = NULL;
                }
                e->tag = tag;
@@@ -138,7 -150,7 +138,7 @@@ static int get_name(const char *path, c
                return 0;
  
        /* Accept only tags that match the pattern, if given */
-       if (pattern && (!is_tag || fnmatch(pattern, path + 10, 0)))
+       if (pattern && (!is_tag || wildmatch(pattern, path + 10, 0, NULL)))
                return 0;
  
        /* Is it annotated? */
@@@ -280,14 -292,7 +280,14 @@@ static void describe(const char *arg, i
                fprintf(stderr, _("searching to describe %s\n"), arg);
  
        if (!have_util) {
 -              for_each_hash(&names, set_util, NULL);
 +              struct hashmap_iter iter;
 +              struct commit *c;
 +              struct commit_name *n = hashmap_iter_first(&names, &iter);
 +              for (; n; n = hashmap_iter_next(&iter)) {
 +                      c = lookup_commit_reference_gently(n->peeled, 1);
 +                      if (c)
 +                              c->util = n;
 +              }
                have_util = 1;
        }
  
@@@ -458,9 -463,9 +458,9 @@@ int cmd_describe(int argc, const char *
                return cmd_name_rev(args.argc, args.argv, prefix);
        }
  
 -      init_hash(&names);
 +      hashmap_init(&names, (hashmap_cmp_fn) commit_name_cmp, 0);
        for_each_rawref(get_name, NULL);
 -      if (!names.nr && !always)
 +      if (!names.size && !always)
                die(_("No names found, cannot describe anything."));
  
        if (argc == 0) {
diff --combined diffcore-order.c
index 1bfcc39f904898b488b5ea0dad1ef3bcb81466ce,53ea4d14c2e3a79f05d4c77895e4e60b507f5820..97dd3d0095723c194288db0da1b9cfbf400e7e26
@@@ -57,6 -57,12 +57,6 @@@ static void prepare_order(const char *o
        }
  }
  
 -struct pair_order {
 -      struct diff_filepair *pair;
 -      int orig_order;
 -      int order;
 -};
 -
  static int match_order(const char *path)
  {
        int i;
@@@ -67,7 -73,7 +67,7 @@@
                strbuf_addstr(&p, path);
                while (p.buf[0]) {
                        char *cp;
-                       if (!fnmatch(order[i], p.buf, 0))
+                       if (!wildmatch(order[i], p.buf, 0, NULL))
                                return i;
                        cp = strrchr(p.buf, '/');
                        if (!cp)
        return order_cnt;
  }
  
 -static int compare_pair_order(const void *a_, const void *b_)
 +static int compare_objs_order(const void *a_, const void *b_)
  {
 -      struct pair_order const *a, *b;
 -      a = (struct pair_order const *)a_;
 -      b = (struct pair_order const *)b_;
 +      struct obj_order const *a, *b;
 +      a = (struct obj_order const *)a_;
 +      b = (struct obj_order const *)b_;
        if (a->order != b->order)
                return a->order - b->order;
        return a->orig_order - b->orig_order;
  }
  
 +void order_objects(const char *orderfile, obj_path_fn_t obj_path,
 +                 struct obj_order *objs, int nr)
 +{
 +      int i;
 +
 +      if (!nr)
 +              return;
 +
 +      prepare_order(orderfile);
 +      for (i = 0; i < nr; i++) {
 +              objs[i].orig_order = i;
 +              objs[i].order = match_order(obj_path(objs[i].obj));
 +      }
 +      qsort(objs, nr, sizeof(*objs), compare_objs_order);
 +}
 +
 +static const char *pair_pathtwo(void *obj)
 +{
 +      struct diff_filepair *pair = (struct diff_filepair *)obj;
 +
 +      return pair->two->path;
 +}
 +
  void diffcore_order(const char *orderfile)
  {
        struct diff_queue_struct *q = &diff_queued_diff;
 -      struct pair_order *o;
 +      struct obj_order *o;
        int i;
  
        if (!q->nr)
                return;
  
        o = xmalloc(sizeof(*o) * q->nr);
 -      prepare_order(orderfile);
 -      for (i = 0; i < q->nr; i++) {
 -              o[i].pair = q->queue[i];
 -              o[i].orig_order = i;
 -              o[i].order = match_order(o[i].pair->two->path);
 -      }
 -      qsort(o, q->nr, sizeof(*o), compare_pair_order);
        for (i = 0; i < q->nr; i++)
 -              q->queue[i] = o[i].pair;
 +              o[i].obj = q->queue[i];
 +      order_objects(orderfile, pair_pathtwo, o, q->nr);
 +      for (i = 0; i < q->nr; i++)
 +              q->queue[i] = o[i].obj;
        free(o);
        return;
  }
diff --combined dir.c
index 6c6a5d13c2e65b02bfd9e3201c35b3a9f270d093,59ccb5218ad27f35093b1f9abced9bf8a7dd9374..70eefdd350429cc2a9a9238449b315512d189451
--- 1/dir.c
--- 2/dir.c
+++ b/dir.c
@@@ -49,7 -49,9 +49,9 @@@ int strncmp_icase(const char *a, const 
  
  int fnmatch_icase(const char *pattern, const char *string, int flags)
  {
-       return fnmatch(pattern, string, flags | (ignore_case ? FNM_CASEFOLD : 0));
+       return wildmatch(pattern, string,
+                        flags | (ignore_case ? WM_CASEFOLD : 0),
+                        NULL);
  }
  
  inline int git_fnmatch(const struct pathspec_item *item,
@@@ -58,7 -60,7 +60,7 @@@
  {
        if (prefix > 0) {
                if (ps_strncmp(item, pattern, string, prefix))
-                       return FNM_NOMATCH;
+                       return WM_NOMATCH;
                pattern += prefix;
                string += prefix;
        }
@@@ -76,8 -78,9 +78,9 @@@
                                 NULL);
        else
                /* wildmatch has not learned no FNM_PATHNAME mode yet */
-               return fnmatch(pattern, string,
-                              item->magic & PATHSPEC_ICASE ? FNM_CASEFOLD : 0);
+               return wildmatch(pattern, string,
+                                item->magic & PATHSPEC_ICASE ? WM_CASEFOLD : 0,
+                                NULL);
  }
  
  static int fnmatch_icase_mem(const char *pattern, int patternlen,
@@@ -195,9 -198,6 +198,9 @@@ int within_depth(const char *name, int 
        return 1;
  }
  
 +#define DO_MATCH_EXCLUDE   1
 +#define DO_MATCH_DIRECTORY 2
 +
  /*
   * Does 'match' match the given name?
   * A match is found if
   * It returns 0 when there is no match.
   */
  static int match_pathspec_item(const struct pathspec_item *item, int prefix,
 -                             const char *name, int namelen)
 +                             const char *name, int namelen, unsigned flags)
  {
        /* name/namelen has prefix cut off by caller */
        const char *match = item->match + prefix;
         * The normal call pattern is:
         * 1. prefix = common_prefix_len(ps);
         * 2. prune something, or fill_directory
 -       * 3. match_pathspec_depth()
 +       * 3. match_pathspec()
         *
         * 'prefix' at #1 may be shorter than the command's prefix and
         * it's ok for #2 to match extra files. Those extras will be
  
                if (match[matchlen-1] == '/' || name[matchlen] == '/')
                        return MATCHED_RECURSIVELY;
 -      }
 +      } else if ((flags & DO_MATCH_DIRECTORY) &&
 +                 match[matchlen - 1] == '/' &&
 +                 namelen == matchlen - 1 &&
 +                 !ps_strncmp(item, match, name, namelen))
 +              return MATCHED_EXACTLY;
  
        if (item->nowildcard_len < item->len &&
            !git_fnmatch(item, match, name,
   * pathspec did not match any names, which could indicate that the
   * user mistyped the nth pathspec.
   */
 -static int match_pathspec_depth_1(const struct pathspec *ps,
 -                                const char *name, int namelen,
 -                                int prefix, char *seen,
 -                                int exclude)
 +static int do_match_pathspec(const struct pathspec *ps,
 +                           const char *name, int namelen,
 +                           int prefix, char *seen,
 +                           unsigned flags)
  {
 -      int i, retval = 0;
 +      int i, retval = 0, exclude = flags & DO_MATCH_EXCLUDE;
  
        GUARD_PATHSPEC(ps,
                       PATHSPEC_FROMTOP |
                 */
                if (seen && ps->items[i].magic & PATHSPEC_EXCLUDE)
                        seen[i] = MATCHED_FNMATCH;
 -              how = match_pathspec_item(ps->items+i, prefix, name, namelen);
 +              how = match_pathspec_item(ps->items+i, prefix, name,
 +                                        namelen, flags);
                if (ps->recursive &&
                    (ps->magic & PATHSPEC_MAXDEPTH) &&
                    ps->max_depth != -1 &&
        return retval;
  }
  
 -int match_pathspec_depth(const struct pathspec *ps,
 -                       const char *name, int namelen,
 -                       int prefix, char *seen)
 +int match_pathspec(const struct pathspec *ps,
 +                 const char *name, int namelen,
 +                 int prefix, char *seen, int is_dir)
  {
        int positive, negative;
 -      positive = match_pathspec_depth_1(ps, name, namelen, prefix, seen, 0);
 +      unsigned flags = is_dir ? DO_MATCH_DIRECTORY : 0;
 +      positive = do_match_pathspec(ps, name, namelen,
 +                                   prefix, seen, flags);
        if (!(ps->magic & PATHSPEC_EXCLUDE) || !positive)
                return positive;
 -      negative = match_pathspec_depth_1(ps, name, namelen, prefix, seen, 1);
 +      negative = do_match_pathspec(ps, name, namelen,
 +                                   prefix, seen,
 +                                   flags | DO_MATCH_EXCLUDE);
        return negative ? 0 : positive;
  }
  
@@@ -503,25 -494,6 +506,25 @@@ void clear_exclude_list(struct exclude_
        el->filebuf = NULL;
  }
  
 +static void trim_trailing_spaces(char *buf)
 +{
 +      int i, last_space = -1, nr_spaces, len = strlen(buf);
 +      for (i = 0; i < len; i++)
 +              if (buf[i] == '\\')
 +                      i++;
 +              else if (buf[i] == ' ') {
 +                      if (last_space == -1) {
 +                              last_space = i;
 +                              nr_spaces = 1;
 +                      } else
 +                              nr_spaces++;
 +              } else
 +                      last_space = -1;
 +
 +      if (last_space != -1 && last_space + nr_spaces == len)
 +              buf[last_space] = '\0';
 +}
 +
  int add_excludes_from_file_to_list(const char *fname,
                                   const char *base,
                                   int baselen,
                if (buf[i] == '\n') {
                        if (entry != buf + i && entry[0] != '#') {
                                buf[i - (i && buf[i-1] == '\r')] = 0;
 +                              trim_trailing_spaces(entry);
                                add_exclude(entry, base, baselen, el, lineno);
                        }
                        lineno++;
diff --combined git-compat-util.h
index 082eb0d1b7ddbf831a5754d617f1c7aafaa04ae6,eaee4381f273d1d1ae26e761b7ea88cbec9a7030..585ef8a79bd9fa66a34a840eae30658894a213f1
  #include <sys/time.h>
  #include <time.h>
  #include <signal.h>
- #ifndef USE_WILDMATCH
- #include <fnmatch.h>
- #endif
  #include <assert.h>
  #include <regex.h>
  #include <utime.h>
@@@ -304,16 -301,7 +301,7 @@@ extern char *gitbasename(char *)
  
  #include "compat/bswap.h"
  
- #ifdef USE_WILDMATCH
  #include "wildmatch.h"
- #define FNM_PATHNAME WM_PATHNAME
- #define FNM_CASEFOLD WM_CASEFOLD
- #define FNM_NOMATCH  WM_NOMATCH
- static inline int fnmatch(const char *pattern, const char *string, int flags)
- {
-       return wildmatch(pattern, string, flags, NULL);
- }
- #endif
  
  /* General helper functions */
  extern void vreportf(const char *prefix, const char *err, va_list params);
@@@ -351,7 -339,9 +339,7 @@@ extern void set_error_routine(void (*ro
  extern void set_die_is_recursing_routine(int (*routine)(void));
  
  extern int starts_with(const char *str, const char *prefix);
 -extern int prefixcmp(const char *str, const char *prefix);
  extern int ends_with(const char *str, const char *suffix);
 -extern int suffixcmp(const char *str, const char *suffix);
  
  static inline const char *skip_prefix(const char *str, const char *prefix)
  {
@@@ -478,15 -468,9 +466,15 @@@ extern FILE *git_fopen(const char*, con
  #endif
  
  #ifdef SNPRINTF_RETURNS_BOGUS
 +#ifdef snprintf
 +#undef snprintf
 +#endif
  #define snprintf git_snprintf
  extern int git_snprintf(char *str, size_t maxsize,
                        const char *format, ...);
 +#ifdef vsnprintf
 +#undef vsnprintf
 +#endif
  #define vsnprintf git_vsnprintf
  extern int git_vsnprintf(char *str, size_t maxsize,
                         const char *format, va_list ap);
diff --combined revision.c
index bd027bc0152a59ac0c4584ab752ff70bee5abbfa,6addff1b5fcbfbffe6e30b9f72eea75d8bf755bc..78b5c3ac0b2d7d436b35a69a3cf6c1b023c96dd5
@@@ -16,7 -16,6 +16,7 @@@
  #include "line-log.h"
  #include "mailmap.h"
  #include "commit-slab.h"
 +#include "dir.h"
  
  volatile show_early_output_fn_t show_early_output;
  
@@@ -497,14 -496,24 +497,14 @@@ static int rev_compare_tree(struct rev_
  static int rev_same_tree_as_empty(struct rev_info *revs, struct commit *commit)
  {
        int retval;
 -      void *tree;
 -      unsigned long size;
 -      struct tree_desc empty, real;
        struct tree *t1 = commit->tree;
  
        if (!t1)
                return 0;
  
 -      tree = read_object_with_reference(t1->object.sha1, tree_type, &size, NULL);
 -      if (!tree)
 -              return 0;
 -      init_tree_desc(&real, tree, size);
 -      init_tree_desc(&empty, "", 0);
 -
        tree_difference = REV_TREE_SAME;
        DIFF_OPT_CLR(&revs->pruning, HAS_CHANGES);
 -      retval = diff_tree(&empty, &real, "", &revs->pruning);
 -      free(tree);
 +      retval = diff_tree_sha1(NULL, t1->object.sha1, "", &revs->pruning);
  
        return retval >= 0 && (tree_difference == REV_TREE_SAME);
  }
@@@ -774,10 -783,6 +774,10 @@@ static int add_parents_to_list(struct r
                return 0;
        commit->object.flags |= ADDED;
  
 +      if (revs->include_check &&
 +          !revs->include_check(commit, revs->include_check_data))
 +              return 0;
 +
        /*
         * If the commit is uninteresting, don't try to
         * prune parents - we want the maximal uninteresting
@@@ -1186,7 -1191,7 +1186,7 @@@ int ref_excluded(struct string_list *re
        if (!ref_excludes)
                return 0;
        for_each_string_list_item(item, ref_excludes) {
-               if (!fnmatch(item->string, path, 0))
+               if (!wildmatch(item->string, path, 0, NULL))
                        return 1;
        }
        return 0;
@@@ -1395,7 -1400,7 +1395,7 @@@ static void prepare_show_merge(struct r
                const struct cache_entry *ce = active_cache[i];
                if (!ce_stage(ce))
                        continue;
 -              if (ce_path_match(ce, &revs->prune_data)) {
 +              if (ce_path_match(ce, &revs->prune_data, NULL)) {
                        prune_num++;
                        prune = xrealloc(prune, sizeof(*prune) * prune_num);
                        prune[prune_num-2] = ce->name;