Merge branch 'kb/checkout-optim'
authorJunio C Hamano <gitster@pobox.com>
Wed, 18 Mar 2009 01:54:31 +0000 (18:54 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 18 Mar 2009 01:54:31 +0000 (18:54 -0700)
* kb/checkout-optim:
  Revert "lstat_cache(): print a warning if doing ping-pong between cache types"
  checkout bugfix: use stat.mtime instead of stat.ctime in two places
  Makefile: Set compiler switch for USE_NSEC
  Create USE_ST_TIMESPEC and turn it on for Darwin
  Not all systems use st_[cm]tim field for ns resolution file timestamp
  Record ns-timestamps if possible, but do not use it without USE_NSEC
  write_index(): update index_state->timestamp after flushing to disk
  verify_uptodate(): add ce_uptodate(ce) test
  make USE_NSEC work as expected
  fix compile error when USE_NSEC is defined
  check_updates(): effective removal of cache entries marked CE_REMOVE
  lstat_cache(): print a warning if doing ping-pong between cache types
  show_patch_diff(): remove a call to fstat()
  write_entry(): use fstat() instead of lstat() when file is open
  write_entry(): cleanup of some duplicated code
  create_directories(): remove some memcpy() and strchr() calls
  unlink_entry(): introduce schedule_dir_for_removal()
  lstat_cache(): swap func(length, string) into func(string, length)
  lstat_cache(): generalise longest_match_lstat_cache()
  lstat_cache(): small cleanup and optimisation

1  2 
Makefile
builtin-add.c
builtin-fetch-pack.c
builtin-update-index.c
cache.h
combine-diff.c
diff-lib.c
dir.c
git-compat-util.h

diff --combined Makefile
index 1087884be691ed2e9a59dd6289b809496538bf8e,e8cdbfb3d0df0ba6ecfe60aa46914cf959165017..216adb9d051992b2474c952b4998b921ad081702
+++ b/Makefile
@@@ -126,6 -126,12 +126,12 @@@ all:
  # randomly break unless your underlying filesystem supports those sub-second
  # times (my ext3 doesn't).
  #
+ # Define USE_ST_TIMESPEC if your "struct stat" uses "st_ctimespec" instead of
+ # "st_ctim"
+ #
+ # Define NO_NSEC if your "struct stat" does not have "st_ctim.tv_nsec"
+ # available.  This automatically turns USE_NSEC off.
+ #
  # Define USE_STDEV below if you want git to care about the underlying device
  # change being considered an inode change from the update-index perspective.
  #
@@@ -228,7 -234,7 +234,7 @@@ GITWEB_FAVICON = git-favicon.pn
  GITWEB_SITE_HEADER =
  GITWEB_SITE_FOOTER =
  
 -export prefix bindir sharedir htmldir sysconfdir
 +export prefix bindir sharedir sysconfdir
  
  CC = gcc
  AR = ar
@@@ -265,6 -271,7 +271,6 @@@ SCRIPT_SH += git-merge-octopus.s
  SCRIPT_SH += git-merge-one-file.sh
  SCRIPT_SH += git-merge-resolve.sh
  SCRIPT_SH += git-mergetool.sh
 -SCRIPT_SH += git-notes.sh
  SCRIPT_SH += git-parse-remote.sh
  SCRIPT_SH += git-pull.sh
  SCRIPT_SH += git-quiltimport.sh
@@@ -317,8 -324,8 +323,8 @@@ PROGRAMS += git-var$
  # builtin-$C.o but is linked in as part of some other command.
  BUILT_INS += $(patsubst builtin-%.o,git-%$X,$(BUILTIN_OBJS))
  
 -BUILT_INS += git-cherry-pick$X
  BUILT_INS += git-cherry$X
 +BUILT_INS += git-cherry-pick$X
  BUILT_INS += git-format-patch$X
  BUILT_INS += git-fsck-objects$X
  BUILT_INS += git-get-tar-commit-id$X
@@@ -357,8 -364,8 +363,8 @@@ LIB_H += builtin.
  LIB_H += cache.h
  LIB_H += cache-tree.h
  LIB_H += commit.h
 -LIB_H += compat/mingw.h
  LIB_H += compat/cygwin.h
 +LIB_H += compat/mingw.h
  LIB_H += csum-file.h
  LIB_H += decorate.h
  LIB_H += delta.h
@@@ -377,12 -384,14 +383,12 @@@ LIB_H += ll-merge.
  LIB_H += log-tree.h
  LIB_H += mailmap.h
  LIB_H += merge-recursive.h
 -LIB_H += notes.h
  LIB_H += object.h
  LIB_H += pack.h
  LIB_H += pack-refs.h
  LIB_H += pack-revindex.h
  LIB_H += parse-options.h
  LIB_H += patch-ids.h
 -LIB_H += string-list.h
  LIB_H += pkt-line.h
  LIB_H += progress.h
  LIB_H += quote.h
@@@ -396,7 -405,6 +402,7 @@@ LIB_H += sha1-lookup.
  LIB_H += sideband.h
  LIB_H += sigchain.h
  LIB_H += strbuf.h
 +LIB_H += string-list.h
  LIB_H += tag.h
  LIB_H += transport.h
  LIB_H += tree.h
@@@ -435,8 -443,8 +441,8 @@@ LIB_OBJS += diffcore-order.
  LIB_OBJS += diffcore-pickaxe.o
  LIB_OBJS += diffcore-rename.o
  LIB_OBJS += diff-delta.o
 -LIB_OBJS += diff-no-index.o
  LIB_OBJS += diff-lib.o
 +LIB_OBJS += diff-no-index.o
  LIB_OBJS += diff.o
  LIB_OBJS += dir.o
  LIB_OBJS += editor.o
@@@ -459,6 -467,7 +465,6 @@@ LIB_OBJS += match-trees.
  LIB_OBJS += merge-file.o
  LIB_OBJS += merge-recursive.o
  LIB_OBJS += name-hash.o
 -LIB_OBJS += notes.o
  LIB_OBJS += object.o
  LIB_OBJS += pack-check.o
  LIB_OBJS += pack-refs.o
@@@ -468,9 -477,9 +474,9 @@@ LIB_OBJS += pager.
  LIB_OBJS += parse-options.o
  LIB_OBJS += patch-delta.o
  LIB_OBJS += patch-ids.o
 -LIB_OBJS += string-list.o
  LIB_OBJS += path.o
  LIB_OBJS += pkt-line.o
 +LIB_OBJS += preload-index.o
  LIB_OBJS += pretty.o
  LIB_OBJS += progress.o
  LIB_OBJS += quote.o
@@@ -484,14 -493,13 +490,14 @@@ LIB_OBJS += revision.
  LIB_OBJS += run-command.o
  LIB_OBJS += server-info.o
  LIB_OBJS += setup.o
 -LIB_OBJS += sha1_file.o
  LIB_OBJS += sha1-lookup.o
 +LIB_OBJS += sha1_file.o
  LIB_OBJS += sha1_name.o
  LIB_OBJS += shallow.o
  LIB_OBJS += sideband.o
  LIB_OBJS += sigchain.o
  LIB_OBJS += strbuf.o
 +LIB_OBJS += string-list.o
  LIB_OBJS += symlinks.o
  LIB_OBJS += tag.o
  LIB_OBJS += trace.o
@@@ -500,8 -508,8 +506,8 @@@ LIB_OBJS += tree-diff.
  LIB_OBJS += tree.o
  LIB_OBJS += tree-walk.o
  LIB_OBJS += unpack-trees.o
 -LIB_OBJS += userdiff.o
  LIB_OBJS += usage.o
 +LIB_OBJS += userdiff.o
  LIB_OBJS += utf8.o
  LIB_OBJS += walker.o
  LIB_OBJS += wrapper.o
@@@ -509,6 -517,7 +515,6 @@@ LIB_OBJS += write_or_die.
  LIB_OBJS += ws.o
  LIB_OBJS += wt-status.o
  LIB_OBJS += xdiff-interface.o
 -LIB_OBJS += preload-index.o
  
  BUILTIN_OBJS += builtin-add.o
  BUILTIN_OBJS += builtin-annotate.o
@@@ -657,6 -666,7 +663,7 @@@ ifeq ($(uname_S),Darwin
        endif
        NO_MEMMEM = YesPlease
        THREADED_DELTA_SEARCH = YesPlease
+       USE_ST_TIMESPEC = YesPlease
  endif
  ifeq ($(uname_S),SunOS)
        NEEDS_SOCKET = YesPlease
@@@ -734,6 -744,7 +741,7 @@@ ifeq ($(uname_S),AIX
        NO_MEMMEM = YesPlease
        NO_MKDTEMP = YesPlease
        NO_STRLCPY = YesPlease
+       NO_NSEC = YesPlease
        FREAD_READS_DIRECTORIES = UnfortunatelyYes
        INTERNAL_QSORT = UnfortunatelyYes
        NEEDS_LIBICONV=YesPlease
@@@ -799,6 -810,7 +807,7 @@@ ifneq (,$(findstring MINGW,$(uname_S))
        RUNTIME_PREFIX = YesPlease
        NO_POSIX_ONLY_PROGRAMS = YesPlease
        NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
+       NO_NSEC = YesPlease
        COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/regex -Icompat/fnmatch
        COMPAT_CFLAGS += -DSNPRINTF_SIZE_CORR=1
        COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
@@@ -920,6 -932,15 +929,15 @@@ endi
  ifdef NO_ST_BLOCKS_IN_STRUCT_STAT
        BASIC_CFLAGS += -DNO_ST_BLOCKS_IN_STRUCT_STAT
  endif
+ ifdef USE_NSEC
+       BASIC_CFLAGS += -DUSE_NSEC
+ endif
+ ifdef USE_ST_TIMESPEC
+       BASIC_CFLAGS += -DUSE_ST_TIMESPEC
+ endif
+ ifdef NO_NSEC
+       BASIC_CFLAGS += -DNO_NSEC
+ endif
  ifdef NO_C99_FORMAT
        BASIC_CFLAGS += -DNO_C99_FORMAT
  endif
@@@ -1468,8 -1489,8 +1486,8 @@@ endi
        bindir=$$(cd '$(DESTDIR_SQ)$(bindir_SQ)' && pwd) && \
        execdir=$$(cd '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' && pwd) && \
        { $(RM) "$$execdir/git-add$X" && \
 -              ln git-add$X "$$execdir/git-add$X" 2>/dev/null || \
 -              cp git-add$X "$$execdir/git-add$X"; } && \
 +              ln "$$bindir/git$X" "$$execdir/git-add$X" 2>/dev/null || \
 +              cp "$$bindir/git$X" "$$execdir/git-add$X"; } && \
        { for p in $(filter-out git-add$X,$(BUILT_INS)); do \
                $(RM) "$$execdir/$$p" && \
                ln "$$execdir/git-add$X" "$$execdir/$$p" 2>/dev/null || \
@@@ -1640,27 -1661,3 +1658,27 @@@ check-docs:
  check-builtins::
        ./check-builtins.sh
  
 +### Test suite coverage testing
 +#
 +.PHONY: coverage coverage-clean coverage-build coverage-report
 +
 +coverage:
 +      $(MAKE) coverage-build
 +      $(MAKE) coverage-report
 +
 +coverage-clean:
 +      rm -f *.gcda *.gcno
 +
 +COVERAGE_CFLAGS = $(CFLAGS) -O0 -ftest-coverage -fprofile-arcs
 +COVERAGE_LDFLAGS = $(CFLAGS)  -O0 -lgcov
 +
 +coverage-build: coverage-clean
 +      $(MAKE) CFLAGS="$(COVERAGE_CFLAGS)" LDFLAGS="$(COVERAGE_LDFLAGS)" all
 +      $(MAKE) CFLAGS="$(COVERAGE_CFLAGS)" LDFLAGS="$(COVERAGE_LDFLAGS)" \
 +              -j1 test
 +
 +coverage-report:
 +      gcov -b *.c
 +      grep '^function.*called 0 ' *.c.gcov \
 +              | sed -e 's/\([^:]*\)\.gcov: *function \([^ ]*\) called.*/\1: \2/' \
 +              | tee coverage-untested-functions
diff --combined builtin-add.c
index 08443f2f1ecf7d9edd21cec11fa74548c3326df5,a23ad967737cc3473e28a954f5b2125b6aad794f..7ddb65932dd6ae11589c5063335b857ecd3298d9
@@@ -15,7 -15,7 +15,7 @@@ static const char * const builtin_add_u
        "git add [options] [--] <filepattern>...",
        NULL
  };
 -static int patch_interactive = 0, add_interactive = 0;
 +static int patch_interactive, add_interactive;
  static int take_worktree_changes;
  
  static void fill_pathspec_matches(const char **pathspec, char *seen, int specs)
@@@ -148,7 -148,7 +148,7 @@@ static const char **validate_pathspec(i
        if (pathspec) {
                const char **p;
                for (p = pathspec; *p; p++) {
-                       if (has_symlink_leading_path(strlen(*p), *p)) {
+                       if (has_symlink_leading_path(*p, strlen(*p))) {
                                int len = prefix ? strlen(prefix) : 0;
                                die("'%s' is beyond a symbolic link", *p + len);
                        }
diff --combined builtin-fetch-pack.c
index c2e5adc8847e8ffa94bd009121b7a295f3f0512e,8b3386168138691b2b3a3938156249cb00a3a714..29f4315e925f4c0d53c52aa114a0a314c2ea5165
@@@ -216,8 -216,9 +216,8 @@@ static int find_common(int fd[2], unsig
        if (args.depth > 0) {
                char line[1024];
                unsigned char sha1[20];
 -              int len;
  
 -              while ((len = packet_read_line(fd[0], line, sizeof(line)))) {
 +              while (packet_read_line(fd[0], line, sizeof(line))) {
                        if (!prefixcmp(line, "shallow ")) {
                                if (get_sha1_hex(line + 8, sha1))
                                        die("invalid shallow line: %s", line);
@@@ -800,15 -801,13 +800,13 @@@ struct ref *fetch_pack(struct fetch_pac
                int fd;
  
                mtime.sec = st.st_mtime;
- #ifdef USE_NSEC
-               mtime.usec = st.st_mtim.usec;
- #endif
+               mtime.nsec = ST_MTIME_NSEC(st);
                if (stat(shallow, &st)) {
                        if (mtime.sec)
                                die("shallow file was removed during fetch");
                } else if (st.st_mtime != mtime.sec
  #ifdef USE_NSEC
-                               || st.st_mtim.usec != mtime.usec
+                               || ST_MTIME_NSEC(st) != mtime.nsec
  #endif
                          )
                        die("shallow file was changed during fetch");
diff --combined builtin-update-index.c
index dd43d5bef425af318a884bfc235a4aff40931633,6c55527513675ffd0dd70c294d8d4412af64ed93..1fde893cfa9f6318ae1e9958b2f61159b01c7c6a
@@@ -195,7 -195,7 +195,7 @@@ static int process_path(const char *pat
        struct stat st;
  
        len = strlen(path);
-       if (has_symlink_leading_path(len, path))
+       if (has_symlink_leading_path(path, len))
                return error("'%s' is beyond a symbolic link", path);
  
        /*
@@@ -742,7 -742,8 +742,7 @@@ int cmd_update_index(int argc, const ch
                if (newfd < 0) {
                        if (refresh_flags & REFRESH_QUIET)
                                exit(128);
 -                      die("unable to create '%s.lock': %s",
 -                          get_index_file(), strerror(lock_error));
 +                      unable_to_lock_index_die(get_index_file(), lock_error);
                }
                if (write_cache(newfd, active_cache, active_nr) ||
                    commit_locked_index(lock_file))
diff --combined cache.h
index fdc4ada43a24fd64b93dc63589d13da911c70508,2f4f0549f930f11ded62e5efcb20a7fcb3362474..bd4c390d577f0ad1175afb868a0e4ef7a02006d1
+++ b/cache.h
@@@ -140,8 -140,8 +140,8 @@@ struct ondisk_cache_entry_extended 
  };
  
  struct cache_entry {
-       unsigned int ce_ctime;
-       unsigned int ce_mtime;
+       struct cache_time ce_ctime;
+       struct cache_time ce_mtime;
        unsigned int ce_dev;
        unsigned int ce_ino;
        unsigned int ce_mode;
@@@ -282,7 -282,7 +282,7 @@@ struct index_state 
        struct cache_entry **cache;
        unsigned int cache_nr, cache_alloc, cache_changed;
        struct cache_tree *cache_tree;
-       time_t timestamp;
+       struct cache_time timestamp;
        void *alloc;
        unsigned name_hash_initialized : 1,
                 initialized : 1;
@@@ -371,6 -371,8 +371,6 @@@ static inline enum object_type object_t
  #define GITATTRIBUTES_FILE ".gitattributes"
  #define INFOATTRIBUTES_FILE "info/attributes"
  #define ATTRIBUTE_MACRO_PREFIX "[attr]"
 -#define GIT_NOTES_REF_ENVIRONMENT "GIT_NOTES_REF"
 -#define GIT_NOTES_DEFAULT_REF "refs/notes/commits"
  
  extern int is_bare_repository_cfg;
  extern int is_bare_repository(void);
@@@ -428,7 -430,7 +428,7 @@@ extern int read_index_preload(struct in
  extern int read_index_from(struct index_state *, const char *path);
  extern int is_index_unborn(struct index_state *);
  extern int read_index_unmerged(struct index_state *);
- extern int write_index(const struct index_state *, int newfd);
+ extern int write_index(struct index_state *, int newfd);
  extern int discard_index(struct index_state *);
  extern int unmerged_index(const struct index_state *);
  extern int verify_path(const char *path);
@@@ -443,6 -445,7 +443,7 @@@ extern int add_index_entry(struct index
  extern struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really);
  extern void rename_index_entry_at(struct index_state *, int pos, const char *new_name);
  extern int remove_index_entry_at(struct index_state *, int pos);
+ extern void remove_marked_cache_entries(struct index_state *istate);
  extern int remove_file_from_index(struct index_state *, const char *path);
  #define ADD_CACHE_VERBOSE 1
  #define ADD_CACHE_PRETEND 2
@@@ -484,7 -487,6 +485,7 @@@ struct lock_file 
  };
  #define LOCK_DIE_ON_ERROR 1
  #define LOCK_NODEREF 2
 +extern NORETURN void unable_to_lock_index_die(const char *path, int err);
  extern int hold_lock_file_for_update(struct lock_file *, const char *path, int);
  extern int hold_lock_file_for_append(struct lock_file *, const char *path, int);
  extern int commit_lock_file(struct lock_file *);
@@@ -543,6 -545,7 +544,6 @@@ enum rebase_setup_type 
  
  extern enum branch_track git_branch_track;
  extern enum rebase_setup_type autorebase;
 -extern char *notes_ref_name;
  
  #define GIT_REPO_VERSION 0
  extern int repository_format_version;
@@@ -625,9 -628,8 +626,9 @@@ int is_directory(const char *)
  const char *make_absolute_path(const char *path);
  const char *make_nonrelative_path(const char *path);
  const char *make_relative_path(const char *abs, const char *base);
 -int normalize_absolute_path(char *buf, const char *path);
 +int normalize_path_copy(char *dst, const char *src);
  int longest_ancestor_length(const char *path, const char *prefix_list);
 +char *strip_path_suffix(const char *path, const char *suffix);
  
  /* Read and unpack a sha1 file into memory, write memory to a sha1 file */
  extern int sha1_object_info(const unsigned char *, unsigned long *);
@@@ -644,8 -646,7 +645,8 @@@ extern int check_sha1_signature(const u
  
  extern int move_temp_to_file(const char *tmpfile, const char *filename);
  
 -extern int has_sha1_pack(const unsigned char *sha1, const char **ignore);
 +extern int has_sha1_pack(const unsigned char *sha1);
 +extern int has_sha1_kept_pack(const unsigned char *sha1);
  extern int has_sha1_file(const unsigned char *sha1);
  extern int has_loose_object_nonlocal(const unsigned char *sha1);
  
@@@ -697,8 -698,7 +698,8 @@@ enum date_mode 
        DATE_SHORT,
        DATE_LOCAL,
        DATE_ISO8601,
 -      DATE_RFC2822
 +      DATE_RFC2822,
 +      DATE_RAW
  };
  
  const char *show_date(unsigned long time, int timezone, enum date_mode mode);
@@@ -725,11 -725,13 +726,13 @@@ struct checkout 
  };
  
  extern int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath);
- extern int has_symlink_leading_path(int len, const char *name);
- extern int has_symlink_or_noent_leading_path(int len, const char *name);
- extern int has_dirs_only_path(int len, const char *name, int prefix_len);
- extern void invalidate_lstat_cache(int len, const char *name);
+ extern int has_symlink_leading_path(const char *name, int len);
+ extern int has_symlink_or_noent_leading_path(const char *name, int len);
+ extern int has_dirs_only_path(const char *name, int len, int prefix_len);
+ extern void invalidate_lstat_cache(const char *name, int len);
  extern void clear_lstat_cache(void);
+ extern void schedule_dir_for_removal(const char *name, int len);
+ extern void remove_scheduled_dirs(void);
  
  extern struct alternate_object_database {
        struct alternate_object_database *next;
@@@ -831,7 -833,6 +834,7 @@@ extern unsigned char* use_pack(struct p
  extern void close_pack_windows(struct packed_git *);
  extern void unuse_pack(struct pack_window **);
  extern void free_pack_by_name(const char *);
 +extern void clear_delta_base_cache(void);
  extern struct packed_git *add_packed_git(const char *, int, int);
  extern const unsigned char *nth_packed_object_sha1(struct packed_git *, uint32_t);
  extern off_t nth_packed_object_offset(const struct packed_git *, uint32_t);
@@@ -840,6 -841,7 +843,6 @@@ extern void *unpack_entry(struct packed
  extern unsigned long unpack_object_header_buffer(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep);
  extern unsigned long get_size_from_delta(struct packed_git *, struct pack_window **, off_t);
  extern const char *packed_object_info_detail(struct packed_git *, off_t, unsigned long *, unsigned long *, unsigned int *, unsigned char *);
 -extern int matches_pack_name(struct packed_git *p, const char *name);
  
  /* Dumb servers support */
  extern int update_server_info(int);
@@@ -871,7 -873,6 +874,7 @@@ extern int user_ident_explicitly_given
  
  extern const char *git_commit_encoding;
  extern const char *git_log_output_encoding;
 +extern const char *git_mailmap_file;
  
  /* IO helper functions */
  extern void maybe_flush_or_die(FILE *, const char *);
diff --combined combine-diff.c
index b3b86aebcb81972ca50a031f4e15bb7a905101e0,4300319cc0fefe0d6f4eb599e24d89e0d01b8985..066ce841ed76e03dd87e789f6688cc3f5411ba64
@@@ -526,6 -526,7 +526,6 @@@ static void dump_sline(struct sline *sl
                return; /* result deleted */
  
        while (1) {
 -              struct sline *sl = &sline[lno];
                unsigned long hunk_end;
                unsigned long rlines;
                const char *hunk_comment = NULL;
                        struct lline *ll;
                        int j;
                        unsigned long p_mask;
 -                      sl = &sline[lno++];
 +                      struct sline *sl = &sline[lno++];
                        ll = (sl->flag & no_pre_delete) ? NULL : sl->lost_head;
                        while (ll) {
                                fputs(c_old, stdout);
@@@ -712,9 -713,7 +712,7 @@@ static void show_patch_diff(struct comb
                        result_size = buf.len;
                        result = strbuf_detach(&buf, NULL);
                        elem->mode = canon_mode(st.st_mode);
-               }
-               else if (0 <= (fd = open(elem->path, O_RDONLY)) &&
-                        !fstat(fd, &st)) {
+               } else if (0 <= (fd = open(elem->path, O_RDONLY))) {
                        size_t len = xsize_t(st.st_size);
                        ssize_t done;
                        int is_file, i;
diff --combined diff-lib.c
index 79d06068344f5a602f6c8799f6671ccbf98cf49c,a3ba20ee294df4c68599e73fd6a350d4166340bb..a310fb2ad08cfb5fac01f5519e8b95b2338b07db
@@@ -31,7 -31,7 +31,7 @@@ static int check_removed(const struct c
                        return -1;
                return 1;
        }
-       if (has_symlink_leading_path(ce_namelen(ce), ce->name))
+       if (has_symlink_leading_path(ce->name, ce_namelen(ce)))
                return 1;
        if (S_ISDIR(st->st_mode)) {
                unsigned char sub[20];
@@@ -513,18 -513,3 +513,18 @@@ int do_diff_cache(const unsigned char *
                exit(128);
        return 0;
  }
 +
 +int index_differs_from(const char *def, int diff_flags)
 +{
 +      struct rev_info rev;
 +
 +      init_revisions(&rev, NULL);
 +      setup_revisions(0, NULL, &rev, def);
 +      DIFF_OPT_SET(&rev.diffopt, QUIET);
 +      DIFF_OPT_SET(&rev.diffopt, EXIT_WITH_STATUS);
 +      rev.diffopt.flags |= diff_flags;
 +      run_diff_index(&rev, 1);
 +      if (rev.pending.alloc)
 +              free(rev.pending.objects);
 +      return (DIFF_OPT_TST(&rev.diffopt, HAS_CHANGES) != 0);
 +}
diff --combined dir.c
index 2245749b3fe74f793bd1997d2238883abe61fc07,8fb52265424c2003bb4bb35390aa4f6d2b491614..371bcf7cfbc0b3ae7693fb129a6082924c84194d
--- 1/dir.c
--- 2/dir.c
+++ b/dir.c
@@@ -137,7 -137,7 +137,7 @@@ int match_pathspec(const char **pathspe
  
  static int no_wildcard(const char *string)
  {
 -      return string[strcspn(string, "*?[{")] == '\0';
 +      return string[strcspn(string, "*?[{\\")] == '\0';
  }
  
  void add_exclude(const char *string, const char *base,
@@@ -720,7 -720,7 +720,7 @@@ int read_directory(struct dir_struct *d
  {
        struct path_simplify *simplify;
  
-       if (has_symlink_leading_path(strlen(path), path))
+       if (has_symlink_leading_path(path, strlen(path)))
                return dir->nr;
  
        simplify = create_simplify(pathspec);
diff --combined git-compat-util.h
index 878d83dd0863570042af80919899b4d6aa57e35b,c915752a241397b3ba0310fec347c2042ed5e2af..19062534a1d8c8e46e77045cb9e67f437f619133
@@@ -303,8 -303,6 +303,8 @@@ extern ssize_t xwrite(int fd, const voi
  extern int xdup(int fd);
  extern FILE *xfdopen(int fd, const char *mode);
  extern int xmkstemp(char *template);
 +extern int odb_mkstemp(char *template, size_t limit, const char *pattern);
 +extern int odb_pack_keep(char *name, size_t namesz, unsigned char *sha1);
  
  static inline size_t xsize_t(off_t len)
  {
@@@ -319,7 -317,6 +319,7 @@@ static inline int has_extension(const c
  }
  
  /* Sane ctype - no locale, and works with signed chars */
 +#undef isascii
  #undef isspace
  #undef isdigit
  #undef isalpha
@@@ -333,7 -330,6 +333,7 @@@ extern unsigned char sane_ctype[256]
  #define GIT_GLOB_SPECIAL 0x08
  #define GIT_REGEX_SPECIAL 0x10
  #define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0)
 +#define isascii(x) (((x) & ~0x7f) == 0)
  #define isspace(x) sane_istest(x,GIT_SPACE)
  #define isdigit(x) sane_istest(x,GIT_DIGIT)
  #define isalpha(x) sane_istest(x,GIT_ALPHA)
@@@ -388,4 -384,18 +388,18 @@@ void git_qsort(void *base, size_t nmemb
  # define FORCE_DIR_SET_GID 0
  #endif
  
+ #ifdef NO_NSEC
+ #undef USE_NSEC
+ #define ST_CTIME_NSEC(st) 0
+ #define ST_MTIME_NSEC(st) 0
+ #else
+ #ifdef USE_ST_TIMESPEC
+ #define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctimespec.tv_nsec))
+ #define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtimespec.tv_nsec))
+ #else
+ #define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctim.tv_nsec))
+ #define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtim.tv_nsec))
+ #endif
+ #endif
  #endif