Merge branch 'maint-1.6.0' into maint
authorJunio C Hamano <gitster@pobox.com>
Wed, 4 Feb 2009 07:50:09 +0000 (23:50 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 4 Feb 2009 07:50:09 +0000 (23:50 -0800)
* maint-1.6.0:
User-manual: "git stash <comment>" form is long gone
add test-dump-cache-tree in Makefile
fix typo in Documentation
apply: fix access to an uninitialized mode variable, found by valgrind

1  2 
Documentation/technical/api-strbuf.txt
Documentation/user-manual.txt
Makefile
builtin-apply.c
index a8ee2fe6a1504b943ff9c3c51807bf0f839182b1,4242dc01426b46d62bfb7da9f51100c23df2a972..985800e43a9b91256c35df60f67c36994142b94c
@@@ -21,7 -21,7 +21,7 @@@ allocated memory or not), use `strbuf_d
  buffer from its strbuf shell in a safe way. That is the sole supported
  way. This will give you a malloced buffer that you can later `free()`.
  +
- However, it it totally safe to modify anything in the string pointed by
+ However, it is totally safe to modify anything in the string pointed by
  the `buf` member, between the indices `0` and `len-1` (inclusive).
  
  . The `buf` member is a byte array that has at least `len + 1` bytes
@@@ -205,13 -205,6 +205,13 @@@ In order to facilitate caching and to m
  parameters to the callback, `strbuf_expand()` passes a context pointer,
  which can be used by the programmer of the callback as she sees fit.
  
 +`strbuf_expand_dict_cb`::
 +
 +      Used as callback for `strbuf_expand()`, expects an array of
 +      struct strbuf_expand_dict_entry as context, i.e. pairs of
 +      placeholder and replacement string.  The array needs to be
 +      terminated by an entry with placeholder set to NULL.
 +
  `strbuf_addf`::
  
        Add a formatted string to the buffer.
index 19f571ae3bcab2fd96288dfa156062a7fbf89b5e,2ae88c575d0828809aafa242881d0377f7b54726..96af8977f6cae5382728f13116ea24ba2d130bef
@@@ -18,22 -18,12 +18,22 @@@ People needing to do actual developmen
  Further chapters cover more specialized topics.
  
  Comprehensive reference documentation is available through the man
 -pages.  For a command such as "git clone <repo>", just use
 +pages, or linkgit:git-help[1] command.  For example, for the command
 +"git clone <repo>", you can either use:
  
  ------------------------------------------------
  $ man git-clone
  ------------------------------------------------
  
 +or:
 +
 +------------------------------------------------
 +$ git help clone
 +------------------------------------------------
 +
 +With the latter, you can use the manual viewer of your choice; see
 +linkgit:git-help[1] for more information.
 +
  See also <<git-quick-start>> for a brief overview of git commands,
  without any explanation.
  
@@@ -59,7 -49,7 +59,7 @@@ project in mind, here are some interest
  ------------------------------------------------
        # git itself (approx. 10MB download):
  $ git clone git://git.kernel.org/pub/scm/git/git.git
 -      # the linux kernel (approx. 150MB download):
 +      # the Linux kernel (approx. 150MB download):
  $ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
  ------------------------------------------------
  
@@@ -1009,7 -999,7 +1009,7 @@@ $ git ini
  If you have some initial content (say, a tarball):
  
  -------------------------------------------------
 -$ tar -xzvf project.tar.gz
 +$ tar xzvf project.tar.gz
  $ cd project
  $ git init
  $ git add . # include everything below ./ in the first commit:
@@@ -1340,7 -1330,7 +1340,7 @@@ These will display all commits which ex
  MERGE_HEAD, and which touch an unmerged file.
  
  You may also use linkgit:git-mergetool[1], which lets you merge the
 -unmerged files using external tools such as emacs or kdiff3.
 +unmerged files using external tools such as Emacs or kdiff3.
  
  Each time you resolve the conflicts in a file and update the index:
  
@@@ -1507,7 -1497,7 +1507,7 @@@ so on a different branch and then comin
  work-in-progress changes.
  
  ------------------------------------------------
- $ git stash "work in progress for foo feature"
+ $ git stash save "work in progress for foo feature"
  ------------------------------------------------
  
  This command will save your changes away to the `stash`, and
@@@ -4366,9 -4356,7 +4366,9 @@@ $ git remote show example       # get detail
  * remote example
    URL: git://example.com/project.git
    Tracked remote branches
 -    master next ...
 +    master
 +    next
 +    ...
  $ git fetch example           # update branches from example
  $ git branch -r                       # list all remote branches
  -----------------------------------------------
diff --combined Makefile
index aabf0130b99bee5204c8e668ba8f40caea77dae2,5de4247fbd88c0ae45bf4d825b901ea92fb12483..01242889eb888d35e28249a78d54584ebca4bb24
+++ b/Makefile
@@@ -90,8 -90,6 +90,8 @@@ all:
  #
  # Define NO_MMAP if you want to avoid mmap.
  #
 +# Define NO_PTHREADS if you do not have or do not want to use Pthreads.
 +#
  # Define NO_PREAD if you have a problem with pread() system call (e.g.
  # cygwin.dll before v1.5.22).
  #
  # 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.
  #
 +# Define NO_ST_BLOCKS_IN_STRUCT_STAT if your platform does not have st_blocks
 +# field that counts the on-disk footprint in 512-byte blocks.
 +#
  # Define ASCIIDOC8 if you want to format documentation with AsciiDoc 8
  #
  # Define DOCBOOK_XSL_172 if you want to format man pages with DocBook XSL v1.72.
@@@ -166,7 -161,6 +166,7 @@@ uname_M := $(shell sh -c 'uname -m 2>/d
  uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not')
  uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not')
  uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not')
 +uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not')
  
  # CFLAGS and LDFLAGS are for the users to override from the command line.
  
@@@ -232,7 -226,6 +232,7 @@@ INSTALL = instal
  RPMBUILD = rpmbuild
  TCL_PATH = tclsh
  TCLTK_PATH = wish
 +PTHREAD_LIBS = -lpthread
  
  export TCL_PATH TCLTK_PATH
  
@@@ -298,8 -291,8 +298,8 @@@ PROGRAMS += git-mktag$
  PROGRAMS += git-mktree$X
  PROGRAMS += git-pack-redundant$X
  PROGRAMS += git-patch-id$X
 -PROGRAMS += git-receive-pack$X
  PROGRAMS += git-send-pack$X
 +PROGRAMS += git-shell$X
  PROGRAMS += git-show-index$X
  PROGRAMS += git-unpack-file$X
  PROGRAMS += git-update-server-info$X
@@@ -320,7 -313,6 +320,7 @@@ BUILT_INS += git-merge-subtree$
  BUILT_INS += git-peek-remote$X
  BUILT_INS += git-repo-config$X
  BUILT_INS += git-show$X
 +BUILT_INS += git-stage$X
  BUILT_INS += git-status$X
  BUILT_INS += git-whatchanged$X
  
@@@ -351,7 -343,6 +351,7 @@@ LIB_H += cache.
  LIB_H += cache-tree.h
  LIB_H += commit.h
  LIB_H += compat/mingw.h
 +LIB_H += compat/cygwin.h
  LIB_H += csum-file.h
  LIB_H += decorate.h
  LIB_H += delta.h
@@@ -363,8 -354,6 +363,8 @@@ LIB_H += git-compat-util.
  LIB_H += graph.h
  LIB_H += grep.h
  LIB_H += hash.h
 +LIB_H += help.h
 +LIB_H += levenshtein.h
  LIB_H += list-objects.h
  LIB_H += ll-merge.h
  LIB_H += log-tree.h
@@@ -394,7 -383,6 +394,7 @@@ LIB_H += transport.
  LIB_H += tree.h
  LIB_H += tree-walk.h
  LIB_H += unpack-trees.h
 +LIB_H += userdiff.h
  LIB_H += utf8.h
  LIB_H += wt-status.h
  
@@@ -441,7 -429,7 +441,7 @@@ LIB_OBJS += grep.
  LIB_OBJS += hash.o
  LIB_OBJS += help.o
  LIB_OBJS += ident.o
 -LIB_OBJS += interpolate.o
 +LIB_OBJS += levenshtein.o
  LIB_OBJS += list-objects.o
  LIB_OBJS += ll-merge.o
  LIB_OBJS += lockfile.o
@@@ -449,7 -437,6 +449,7 @@@ LIB_OBJS += log-tree.
  LIB_OBJS += mailmap.o
  LIB_OBJS += match-trees.o
  LIB_OBJS += merge-file.o
 +LIB_OBJS += merge-recursive.o
  LIB_OBJS += name-hash.o
  LIB_OBJS += object.o
  LIB_OBJS += pack-check.o
@@@ -490,7 -477,6 +490,7 @@@ 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 += utf8.o
  LIB_OBJS += walker.o
@@@ -499,7 -485,6 +499,7 @@@ 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
@@@ -533,7 -518,6 +533,7 @@@ BUILTIN_OBJS += builtin-for-each-ref.
  BUILTIN_OBJS += builtin-fsck.o
  BUILTIN_OBJS += builtin-gc.o
  BUILTIN_OBJS += builtin-grep.o
 +BUILTIN_OBJS += builtin-help.o
  BUILTIN_OBJS += builtin-init-db.o
  BUILTIN_OBJS += builtin-log.o
  BUILTIN_OBJS += builtin-ls-files.o
@@@ -554,7 -538,6 +554,7 @@@ BUILTIN_OBJS += builtin-prune-packed.
  BUILTIN_OBJS += builtin-prune.o
  BUILTIN_OBJS += builtin-push.o
  BUILTIN_OBJS += builtin-read-tree.o
 +BUILTIN_OBJS += builtin-receive-pack.o
  BUILTIN_OBJS += builtin-reflog.o
  BUILTIN_OBJS += builtin-remote.o
  BUILTIN_OBJS += builtin-rerere.o
@@@ -592,11 -575,9 +592,11 @@@ EXTLIBS 
  
  ifeq ($(uname_S),Linux)
        NO_STRLCPY = YesPlease
 +      THREADED_DELTA_SEARCH = YesPlease
  endif
  ifeq ($(uname_S),GNU/kFreeBSD)
        NO_STRLCPY = YesPlease
 +      THREADED_DELTA_SEARCH = YesPlease
  endif
  ifeq ($(uname_S),UnixWare)
        CC = cc
@@@ -645,7 -626,8 +645,7 @@@ ifeq ($(uname_S),Darwin
        endif
        NO_STRLCPY = YesPlease
        NO_MEMMEM = YesPlease
 -      COMPAT_CFLAGS += -Icompat/regex
 -      COMPAT_OBJS += compat/regex/regex.o
 +      THREADED_DELTA_SEARCH = YesPlease
  endif
  ifeq ($(uname_S),SunOS)
        NEEDS_SOCKET = YesPlease
@@@ -695,12 -677,8 +695,12 @@@ ifeq ($(uname_S),FreeBSD
        BASIC_CFLAGS += -I/usr/local/include
        BASIC_LDFLAGS += -L/usr/local/lib
        DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease
 -      COMPAT_CFLAGS += -Icompat/regex
 -      COMPAT_OBJS += compat/regex/regex.o
 +      THREADED_DELTA_SEARCH = YesPlease
 +      ifeq ($(shell expr "$(uname_R)" : '4\.'),2)
 +              PTHREAD_LIBS = -pthread
 +              NO_UINTMAX_T = YesPlease
 +              NO_STRTOUMAX = YesPlease
 +      endif
  endif
  ifeq ($(uname_S),OpenBSD)
        NO_STRCASESTR = YesPlease
        NEEDS_LIBICONV = YesPlease
        BASIC_CFLAGS += -I/usr/local/include
        BASIC_LDFLAGS += -L/usr/local/lib
 +      THREADED_DELTA_SEARCH = YesPlease
  endif
  ifeq ($(uname_S),NetBSD)
        ifeq ($(shell expr "$(uname_R)" : '[01]\.'),2)
                NEEDS_LIBICONV = YesPlease
        endif
        BASIC_CFLAGS += -I/usr/pkg/include
 -      BASIC_LDFLAGS += -L/usr/pkg/lib
 -      ALL_LDFLAGS += -Wl,-rpath,/usr/pkg/lib
 +      BASIC_LDFLAGS += -L/usr/pkg/lib $(CC_LD_DYNPATH)/usr/pkg/lib
 +      THREADED_DELTA_SEARCH = YesPlease
  endif
  ifeq ($(uname_S),AIX)
        NO_STRCASESTR=YesPlease
        INTERNAL_QSORT = UnfortunatelyYes
        NEEDS_LIBICONV=YesPlease
        BASIC_CFLAGS += -D_LARGE_FILES
 -      COMPAT_CFLAGS += -Icompat/regex
 -      COMPAT_OBJS += compat/regex/regex.o
 +      ifneq ($(shell expr "$(uname_V)" : '[1234]'),1)
 +              THREADED_DELTA_SEARCH = YesPlease
 +      else
 +              NO_PTHREADS = YesPlease
 +      endif
  endif
  ifeq ($(uname_S),GNU)
        # GNU/Hurd
@@@ -761,9 -735,6 +761,9 @@@ ifeq ($(uname_S),HP-UX
        NO_SYS_SELECT_H = YesPlease
        SNPRINTF_RETURNS_BOGUS = YesPlease
  endif
 +ifneq (,$(findstring CYGWIN,$(uname_S)))
 +      COMPAT_OBJS += compat/cygwin.o
 +endif
  ifneq (,$(findstring MINGW,$(uname_S)))
        NO_MMAP = YesPlease
        NO_PREAD = YesPlease
        NO_STRCASESTR = YesPlease
        NO_STRLCPY = YesPlease
        NO_MEMMEM = YesPlease
 +      NO_PTHREADS = YesPlease
        NEEDS_LIBICONV = YesPlease
        OLD_ICONV = YesPlease
        NO_C99_FORMAT = YesPlease
        NO_SVN_TESTS = YesPlease
        NO_PERL_MAKEMAKER = YesPlease
        NO_POSIX_ONLY_PROGRAMS = YesPlease
 +      NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
        COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/regex -Icompat/fnmatch
        COMPAT_CFLAGS += -DSNPRINTF_SIZE_CORR=1
        COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
@@@ -819,14 -788,12 +819,14 @@@ ifeq ($(uname_S),Darwin
        endif
  endif
  
 -ifdef NO_R_TO_GCC_LINKER
 -      # Some gcc does not accept and pass -R to the linker to specify
 -      # the runtime dynamic library path.
 -      CC_LD_DYNPATH = -Wl,-rpath=
 -else
 -      CC_LD_DYNPATH = -R
 +ifndef CC_LD_DYNPATH
 +      ifdef NO_R_TO_GCC_LINKER
 +              # Some gcc does not accept and pass -R to the linker to specify
 +              # the runtime dynamic library path.
 +              CC_LD_DYNPATH = -Wl,-rpath,
 +      else
 +              CC_LD_DYNPATH = -R
 +      endif
  endif
  
  ifdef NO_CURL
@@@ -862,6 -829,7 +862,6 @@@ EXTLIBS += -l
  ifndef NO_POSIX_ONLY_PROGRAMS
        PROGRAMS += git-daemon$X
        PROGRAMS += git-imap-send$X
 -      PROGRAMS += git-shell$X
  endif
  ifndef NO_OPENSSL
        OPENSSL_LIBSSL = -lssl
@@@ -902,9 -870,6 +902,9 @@@ endi
  ifdef NO_D_INO_IN_DIRENT
        BASIC_CFLAGS += -DNO_D_INO_IN_DIRENT
  endif
 +ifdef NO_ST_BLOCKS_IN_STRUCT_STAT
 +      BASIC_CFLAGS += -DNO_ST_BLOCKS_IN_STRUCT_STAT
 +endif
  ifdef NO_C99_FORMAT
        BASIC_CFLAGS += -DNO_C99_FORMAT
  endif
@@@ -966,9 -931,6 +966,9 @@@ endi
  ifdef NO_IPV6
        BASIC_CFLAGS += -DNO_IPV6
  endif
 +ifdef NO_UINTMAX_T
 +      BASIC_CFLAGS += -Duintmax_t=uint32_t
 +endif
  ifdef NO_SOCKADDR_STORAGE
  ifdef NO_IPV6
        BASIC_CFLAGS += -Dsockaddr_storage=sockaddr_in
@@@ -1028,15 -990,9 +1028,15 @@@ ifdef INTERNAL_QSOR
        COMPAT_OBJS += compat/qsort.o
  endif
  
 +ifdef NO_PTHREADS
 +      THREADED_DELTA_SEARCH =
 +      BASIC_CFLAGS += -DNO_PTHREADS
 +else
 +      EXTLIBS += $(PTHREAD_LIBS)
 +endif
 +
  ifdef THREADED_DELTA_SEARCH
        BASIC_CFLAGS += -DTHREADED_DELTA_SEARCH
 -      EXTLIBS += -lpthread
        LIB_OBJS += thread-utils.o
  endif
  ifdef DIR_HAS_BSD_GROUP_SEMANTICS
@@@ -1142,7 -1098,7 +1142,7 @@@ git$X: git.o $(BUILTIN_OBJS) $(GITLIBS
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ git.o \
                $(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS)
  
 -help.o: help.c common-cmds.h GIT-CFLAGS
 +builtin-help.o: builtin-help.c common-cmds.h GIT-CFLAGS
        $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) \
                '-DGIT_HTML_PATH="$(htmldir_SQ)"' \
                '-DGIT_MAN_PATH="$(mandir_SQ)"' \
@@@ -1269,9 -1225,7 +1269,9 @@@ endi
  git-%$X: %.o $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
  
 -git-imap-send$X: imap-send.o $(LIB_FILE)
 +git-imap-send$X: imap-send.o $(GITLIBS)
 +      $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
 +              $(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL)
  
  http.o http-walker.o http-push.o transport.o: http.h
  
@@@ -1298,12 -1252,6 +1298,12 @@@ $(XDIFF_LIB): $(XDIFF_OBJS
  doc:
        $(MAKE) -C Documentation all
  
 +man:
 +      $(MAKE) -C Documentation man
 +
 +html:
 +      $(MAKE) -C Documentation html
 +
  info:
        $(MAKE) -C Documentation info
  
@@@ -1353,7 -1301,7 +1353,7 @@@ endi
  
  ### Testing rules
  
- TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-parse-options$X test-path-utils$X
+ TEST_PROGRAMS = test-chmtime$X test-dump-cache-tree$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-parse-options$X test-path-utils$X
  
  all:: $(TEST_PROGRAMS)
  
@@@ -1440,9 -1388,6 +1440,9 @@@ endi
  install-doc:
        $(MAKE) -C Documentation install
  
 +install-man:
 +      $(MAKE) -C Documentation install-man
 +
  install-html:
        $(MAKE) -C Documentation install-html
  
@@@ -1452,12 -1397,6 +1452,12 @@@ install-info
  quick-install-doc:
        $(MAKE) -C Documentation quick-install
  
 +quick-install-man:
 +      $(MAKE) -C Documentation quick-install-man
 +
 +quick-install-html:
 +      $(MAKE) -C Documentation quick-install-html
 +
  
  
  ### Maintainer's dist rules
diff --combined builtin-apply.c
index a8f75ed3ed411d8cf7a3ec9dfefef7407c50f447,7a1ff041f15cd4e6ce2a5b1d1e3cb668f2f54f5e..3b6cd6dfaea0c8c427ab1a80ed11cabe60a5b32d
@@@ -321,12 -321,13 +321,12 @@@ static char *find_name(const char *line
        const char *start = line;
  
        if (*line == '"') {
 -              struct strbuf name;
 +              struct strbuf name = STRBUF_INIT;
  
                /*
                 * Proposed "new-style" GNU patch/diff format; see
                 * http://marc.theaimsgroup.com/?l=git&m=112927316408690&w=2
                 */
 -              strbuf_init(&name, 0);
                if (!unquote_c_style(&name, line, NULL)) {
                        char *cp;
  
@@@ -630,7 -631,7 +630,7 @@@ static int gitdiff_index(const char *li
        memcpy(patch->new_sha1_prefix, line, len);
        patch->new_sha1_prefix[len] = 0;
        if (*ptr == ' ')
 -              patch->new_mode = patch->old_mode = strtoul(ptr+1, NULL, 8);
 +              patch->old_mode = strtoul(ptr+1, NULL, 8);
        return 0;
  }
  
@@@ -674,8 -675,11 +674,8 @@@ static char *git_header_name(char *line
  
        if (*line == '"') {
                const char *cp;
 -              struct strbuf first;
 -              struct strbuf sp;
 -
 -              strbuf_init(&first, 0);
 -              strbuf_init(&sp, 0);
 +              struct strbuf first = STRBUF_INIT;
 +              struct strbuf sp = STRBUF_INIT;
  
                if (unquote_c_style(&first, line, &second))
                        goto free_and_fail1;
         */
        for (second = name; second < line + llen; second++) {
                if (*second == '"') {
 -                      struct strbuf sp;
 +                      struct strbuf sp = STRBUF_INIT;
                        const char *np;
  
 -                      strbuf_init(&sp, 0);
                        if (unquote_c_style(&sp, second, NULL))
                                goto free_and_fail2;
  
@@@ -1510,10 -1515,11 +1510,10 @@@ static const char minuses[]
  
  static void show_stats(struct patch *patch)
  {
 -      struct strbuf qname;
 +      struct strbuf qname = STRBUF_INIT;
        char *cp = patch->new_name ? patch->new_name : patch->old_name;
        int max, add, del;
  
 -      strbuf_init(&qname, 0);
        quote_c_style(cp, &qname, NULL, 0);
  
        /*
@@@ -1559,8 -1565,10 +1559,8 @@@ static int read_old_data(struct stat *s
  {
        switch (st->st_mode & S_IFMT) {
        case S_IFLNK:
 -              strbuf_grow(buf, st->st_size);
 -              if (readlink(path, buf->buf, st->st_size) != st->st_size)
 -                      return -1;
 -              strbuf_setlen(buf, st->st_size);
 +              if (strbuf_readlink(buf, path, st->st_size) < 0)
 +                      return error("unable to read symlink %s", path);
                return 0;
        case S_IFREG:
                if (strbuf_read_file(buf, path, st->st_size) != st->st_size)
@@@ -2291,12 -2299,14 +2291,12 @@@ static void add_to_fn_table(struct patc
  
  static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *ce)
  {
 -      struct strbuf buf;
 +      struct strbuf buf = STRBUF_INIT;
        struct image image;
        size_t len;
        char *img;
        struct patch *tpatch;
  
 -      strbuf_init(&buf, 0);
 -
        if (!(patch->is_copy || patch->is_rename) &&
            ((tpatch = in_fn_table(patch->old_name)) != NULL)) {
                if (tpatch == (struct patch *) -1) {
@@@ -2435,7 -2445,7 +2435,7 @@@ static int check_preimage(struct patch 
                return error("%s: %s", old_name, strerror(errno));
        }
  
-       if (!cached)
+       if (!cached && !tpatch)
                st_mode = ce_mode_from_stat(*ce, st->st_mode);
  
        if (patch->is_new < 0)
        if (st_mode != patch->old_mode)
                fprintf(stderr, "warning: %s has type %o, expected %o\n",
                        old_name, st_mode, patch->old_mode);
 +      if (!patch->new_mode)
 +              patch->new_mode = st_mode;
        return 0;
  
   is_new:
@@@ -2778,7 -2786,7 +2778,7 @@@ static void add_index_file(const char *
  static int try_create_file(const char *path, unsigned int mode, const char *buf, unsigned long size)
  {
        int fd;
 -      struct strbuf nbuf;
 +      struct strbuf nbuf = STRBUF_INIT;
  
        if (S_ISGITLINK(mode)) {
                struct stat st;
        if (fd < 0)
                return -1;
  
 -      strbuf_init(&nbuf, 0);
        if (convert_to_working_tree(path, buf, size, &nbuf)) {
                size = nbuf.len;
                buf  = nbuf.buf;
@@@ -2987,45 -2996,29 +2987,45 @@@ static int write_out_results(struct pat
  
  static struct lock_file lock_file;
  
 -static struct excludes {
 -      struct excludes *next;
 -      const char *path;
 -} *excludes;
 +static struct string_list limit_by_name;
 +static int has_include;
 +static void add_name_limit(const char *name, int exclude)
 +{
 +      struct string_list_item *it;
 +
 +      it = string_list_append(name, &limit_by_name);
 +      it->util = exclude ? NULL : (void *) 1;
 +}
  
  static int use_patch(struct patch *p)
  {
        const char *pathname = p->new_name ? p->new_name : p->old_name;
 -      struct excludes *x = excludes;
 -      while (x) {
 -              if (fnmatch(x->path, pathname, 0) == 0)
 -                      return 0;
 -              x = x->next;
 -      }
 +      int i;
 +
 +      /* Paths outside are not touched regardless of "--include" */
        if (0 < prefix_length) {
                int pathlen = strlen(pathname);
                if (pathlen <= prefix_length ||
                    memcmp(prefix, pathname, prefix_length))
                        return 0;
        }
 -      return 1;
 +
 +      /* 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))
 +                      return (it->util != NULL);
 +      }
 +
 +      /*
 +       * If we had any include, a path that does not match any rule is
 +       * not used.  Otherwise, we saw bunch of exclude rules (or none)
 +       * and such a path is used.
 +       */
 +      return !has_include;
  }
  
 +
  static void prefix_one(char **name)
  {
        char *old_name = *name;
@@@ -3058,12 -3051,13 +3058,12 @@@ static void prefix_patches(struct patc
  static int apply_patch(int fd, const char *filename, int options)
  {
        size_t offset;
 -      struct strbuf buf;
 +      struct strbuf buf = STRBUF_INIT;
        struct patch *list = NULL, **listp = &list;
        int skipped_patch = 0;
  
        /* FIXME - memory leak when using multiple patch files as inputs */
        memset(&fn_table, 0, sizeof(struct string_list));
 -      strbuf_init(&buf, 0);
        patch_input_file = filename;
        read_patch_file(&buf, fd);
        offset = 0;
@@@ -3165,12 -3159,10 +3165,12 @@@ int cmd_apply(int argc, const char **ar
                        continue;
                }
                if (!prefixcmp(arg, "--exclude=")) {
 -                      struct excludes *x = xmalloc(sizeof(*x));
 -                      x->path = arg + 10;
 -                      x->next = excludes;
 -                      excludes = x;
 +                      add_name_limit(arg + 10, 1);
 +                      continue;
 +              }
 +              if (!prefixcmp(arg, "--include=")) {
 +                      add_name_limit(arg + 10, 0);
 +                      has_include = 1;
                        continue;
                }
                if (!prefixcmp(arg, "-p")) {