Code

Sync with 1.7.8.5
authorJunio C Hamano <gitster@pobox.com>
Mon, 27 Feb 2012 00:42:35 +0000 (16:42 -0800)
committerJunio C Hamano <gitster@pobox.com>
Mon, 27 Feb 2012 00:42:35 +0000 (16:42 -0800)
1  2 
Makefile
grep.c
t/t4150-am.sh

diff --combined Makefile
index 99a7a2b972502411a3dae5e05f6cbcf35a1720c6,3031be5ee63facad10da45271ab04a4be4f3bb68..e4f8e0ef08b9f3f4eb5035f20421ee035127fdf2
+++ b/Makefile
@@@ -43,26 -43,6 +43,26 @@@ all:
  # Define EXPATDIR=/foo/bar if your expat header and library files are in
  # /foo/bar/include and /foo/bar/lib directories.
  #
 +# Define NO_GETTEXT if you don't want Git output to be translated.
 +# A translated Git requires GNU libintl or another gettext implementation,
 +# plus libintl-perl at runtime.
 +#
 +# Define HAVE_LIBCHARSET_H if you haven't set NO_GETTEXT and you can't
 +# trust the langinfo.h's nl_langinfo(CODESET) function to return the
 +# current character set. GNU and Solaris have a nl_langinfo(CODESET),
 +# FreeBSD can use either, but MinGW and some others need to use
 +# libcharset.h's locale_charset() instead.
 +#
 +# Define CHARSET_LIB to you need to link with library other than -liconv to
 +# use locale_charset() function.  On some platforms this needs to set to
 +# -lcharset
 +#
 +# Define LIBC_CONTAINS_LIBINTL if your gettext implementation doesn't
 +# need -lintl when linking.
 +#
 +# Define NO_MSGFMT_EXTENDED_OPTIONS if your implementation of msgfmt
 +# doesn't support GNU extensions like --check and --statistics
 +#
  # Define HAVE_PATHS_H if you have paths.h and want to use the default PATH
  # it specifies.
  #
  #
  # Define NO_IPV6 if you lack IPv6 support and getaddrinfo().
  #
 +# Define NO_UNIX_SOCKETS if your system does not offer unix sockets.
 +#
  # Define NO_SOCKADDR_STORAGE if your platform does not have struct
  # sockaddr_storage.
  #
  #
  # Define NO_REGEX if you have no or inferior regex support in your C library.
  #
 +# Define HAVE_DEV_TTY if your system can open /dev/tty to interact with the
 +# user.
 +#
  # Define GETTEXT_POISON if you are debugging the choice of strings marked
  # for translation.  In a GETTEXT_POISON build, you can turn all strings marked
  # for translation into gibberish by setting the GIT_GETTEXT_POISON variable
@@@ -332,7 -307,6 +332,7 @@@ gitexecdir = libexec/git-cor
  mergetoolsdir = $(gitexecdir)/mergetools
  sharedir = $(prefix)/share
  gitwebdir = $(sharedir)/gitweb
 +localedir = $(sharedir)/locale
  template_dir = share/git-core/templates
  htmldir = share/doc/git-doc
  ETC_GITCONFIG = $(sysconfdir)/gitconfig
@@@ -341,9 -315,9 +341,9 @@@ lib = li
  # DESTDIR=
  pathsep = :
  
 -export prefix bindir sharedir sysconfdir gitwebdir
 +export prefix bindir sharedir sysconfdir gitwebdir localedir
  
 -CC = gcc
 +CC = cc
  AR = ar
  RM = rm -f
  DIFF = diff
@@@ -354,7 -328,6 +354,7 @@@ RPMBUILD = rpmbuil
  TCL_PATH = tclsh
  TCLTK_PATH = wish
  XGETTEXT = xgettext
 +MSGFMT = msgfmt
  PTHREAD_LIBS = -lpthread
  PTHREAD_CFLAGS =
  GCOV = gcov
@@@ -454,20 -427,14 +454,20 @@@ PROGRAM_OBJS += show-index.
  PROGRAM_OBJS += upload-pack.o
  PROGRAM_OBJS += http-backend.o
  PROGRAM_OBJS += sh-i18n--envsubst.o
 +PROGRAM_OBJS += credential-store.o
 +
 +# Binary suffix, set to .exe for Windows builds
 +X =
  
  PROGRAMS += $(patsubst %.o,git-%$X,$(PROGRAM_OBJS))
  
  TEST_PROGRAMS_NEED_X += test-chmtime
 +TEST_PROGRAMS_NEED_X += test-credential
  TEST_PROGRAMS_NEED_X += test-ctype
  TEST_PROGRAMS_NEED_X += test-date
  TEST_PROGRAMS_NEED_X += test-delta
  TEST_PROGRAMS_NEED_X += test-dump-cache-tree
 +TEST_PROGRAMS_NEED_X += test-scrap-cache-tree
  TEST_PROGRAMS_NEED_X += test-genrandom
  TEST_PROGRAMS_NEED_X += test-index-version
  TEST_PROGRAMS_NEED_X += test-line-buffer
@@@ -544,7 -511,6 +544,7 @@@ LIB_H += argv-array.
  LIB_H += attr.h
  LIB_H += blob.h
  LIB_H += builtin.h
 +LIB_H += bulk-checkin.h
  LIB_H += cache.h
  LIB_H += cache-tree.h
  LIB_H += color.h
@@@ -553,14 -519,12 +553,14 @@@ LIB_H += compat/bswap.
  LIB_H += compat/cygwin.h
  LIB_H += compat/mingw.h
  LIB_H += compat/obstack.h
 +LIB_H += compat/terminal.h
  LIB_H += compat/win32/pthread.h
  LIB_H += compat/win32/syslog.h
  LIB_H += compat/win32/poll.h
  LIB_H += compat/win32/dirent.h
  LIB_H += connected.h
  LIB_H += convert.h
 +LIB_H += credential.h
  LIB_H += csum-file.h
  LIB_H += decorate.h
  LIB_H += delta.h
@@@ -568,11 -532,9 +568,11 @@@ LIB_H += diffcore.
  LIB_H += diff.h
  LIB_H += dir.h
  LIB_H += exec_cmd.h
 +LIB_H += fmt-merge-msg.h
  LIB_H += fsck.h
  LIB_H += gettext.h
  LIB_H += git-compat-util.h
 +LIB_H += gpg-interface.h
  LIB_H += graph.h
  LIB_H += grep.h
  LIB_H += hash.h
@@@ -596,7 -558,6 +596,7 @@@ LIB_H += parse-options.
  LIB_H += patch-ids.h
  LIB_H += pkt-line.h
  LIB_H += progress.h
 +LIB_H += prompt.h
  LIB_H += quote.h
  LIB_H += reflog-walk.h
  LIB_H += refs.h
@@@ -615,6 -576,7 +615,7 @@@ LIB_H += streaming.
  LIB_H += string-list.h
  LIB_H += submodule.h
  LIB_H += tag.h
+ LIB_H += thread-utils.h
  LIB_H += transport.h
  LIB_H += tree.h
  LIB_H += tree-walk.h
@@@ -637,20 -599,17 +638,20 @@@ LIB_OBJS += base85.
  LIB_OBJS += bisect.o
  LIB_OBJS += blob.o
  LIB_OBJS += branch.o
 +LIB_OBJS += bulk-checkin.o
  LIB_OBJS += bundle.o
  LIB_OBJS += cache-tree.o
  LIB_OBJS += color.o
  LIB_OBJS += combine-diff.o
  LIB_OBJS += commit.o
  LIB_OBJS += compat/obstack.o
 +LIB_OBJS += compat/terminal.o
  LIB_OBJS += config.o
  LIB_OBJS += connect.o
  LIB_OBJS += connected.o
  LIB_OBJS += convert.o
  LIB_OBJS += copy.o
 +LIB_OBJS += credential.o
  LIB_OBJS += csum-file.o
  LIB_OBJS += ctype.o
  LIB_OBJS += date.o
@@@ -670,8 -629,6 +671,8 @@@ LIB_OBJS += entry.
  LIB_OBJS += environment.o
  LIB_OBJS += exec_cmd.o
  LIB_OBJS += fsck.o
 +LIB_OBJS += gpg-interface.o
 +LIB_OBJS += gettext.o
  LIB_OBJS += graph.o
  LIB_OBJS += grep.o
  LIB_OBJS += hash.o
@@@ -707,7 -664,6 +708,7 @@@ LIB_OBJS += pkt-line.
  LIB_OBJS += preload-index.o
  LIB_OBJS += pretty.o
  LIB_OBJS += progress.o
 +LIB_OBJS += prompt.o
  LIB_OBJS += quote.o
  LIB_OBJS += reachable.o
  LIB_OBJS += read-cache.o
@@@ -869,15 -825,12 +870,15 @@@ ifeq ($(uname_S),Linux
        NO_STRLCPY = YesPlease
        NO_MKSTEMPS = YesPlease
        HAVE_PATHS_H = YesPlease
 +      LIBC_CONTAINS_LIBINTL = YesPlease
 +      HAVE_DEV_TTY = YesPlease
  endif
  ifeq ($(uname_S),GNU/kFreeBSD)
        NO_STRLCPY = YesPlease
        NO_MKSTEMPS = YesPlease
        HAVE_PATHS_H = YesPlease
        DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease
 +      LIBC_CONTAINS_LIBINTL = YesPlease
  endif
  ifeq ($(uname_S),UnixWare)
        CC = cc
@@@ -932,7 -885,6 +933,7 @@@ ifeq ($(uname_S),Darwin
        endif
        NO_MEMMEM = YesPlease
        USE_ST_TIMESPEC = YesPlease
 +      HAVE_DEV_TTY = YesPlease
  endif
  ifeq ($(uname_S),SunOS)
        NEEDS_SOCKET = YesPlease
        NO_MKSTEMPS = YesPlease
        NO_REGEX = YesPlease
        NO_FNMATCH_CASEFOLD = YesPlease
 +      NO_MSGFMT_EXTENDED_OPTIONS = YesPlease
        ifeq ($(uname_R),5.6)
                SOCKLEN_T = int
                NO_HSTRERROR = YesPlease
@@@ -1069,7 -1020,6 +1070,7 @@@ ifeq ($(uname_S),GNU
        NO_STRLCPY=YesPlease
        NO_MKSTEMPS = YesPlease
        HAVE_PATHS_H = YesPlease
 +      LIBC_CONTAINS_LIBINTL = YesPlease
  endif
  ifeq ($(uname_S),IRIX)
        NO_SETENV = YesPlease
@@@ -1149,7 -1099,6 +1150,7 @@@ ifeq ($(uname_S),Windows
        NO_SYS_POLL_H = YesPlease
        NO_SYMLINK_HEAD = YesPlease
        NO_IPV6 = YesPlease
 +      NO_UNIX_SOCKETS = YesPlease
        NO_SETENV = YesPlease
        NO_UNSETENV = YesPlease
        NO_STRCASESTR = YesPlease
@@@ -1243,7 -1192,6 +1244,7 @@@ ifneq (,$(findstring MINGW,$(uname_S))
        NO_LIBGEN_H = YesPlease
        NO_SYS_POLL_H = YesPlease
        NO_SYMLINK_HEAD = YesPlease
 +      NO_UNIX_SOCKETS = YesPlease
        NO_SETENV = YesPlease
        NO_UNSETENV = YesPlease
        NO_STRCASESTR = YesPlease
@@@ -1288,7 -1236,6 +1289,7 @@@ ifneq (,$(wildcard ../THIS_IS_MSYSGIT)
        EXTLIBS += /mingw/lib/libz.a
        NO_R_TO_GCC_LINKER = YesPlease
        INTERNAL_QSORT = YesPlease
 +      HAVE_LIBCHARSET_H = YesPlease
  else
        NO_CURL = YesPlease
  endif
@@@ -1477,11 -1424,6 +1478,11 @@@ endi
  ifdef NEEDS_LIBGEN
        EXTLIBS += -lgen
  endif
 +ifndef NO_GETTEXT
 +ifndef LIBC_CONTAINS_LIBINTL
 +      EXTLIBS += -lintl
 +endif
 +endif
  ifdef NEEDS_SOCKET
        EXTLIBS += -lsocket
  endif
@@@ -1524,11 -1466,9 +1525,11 @@@ ifdef NO_SYMLINK_HEA
        BASIC_CFLAGS += -DNO_SYMLINK_HEAD
  endif
  ifdef GETTEXT_POISON
 -      LIB_OBJS += gettext.o
        BASIC_CFLAGS += -DGETTEXT_POISON
  endif
 +ifdef NO_GETTEXT
 +      BASIC_CFLAGS += -DNO_GETTEXT
 +endif
  ifdef NO_STRCASESTR
        COMPAT_CFLAGS += -DNO_STRCASESTR
        COMPAT_OBJS += compat/strcasestr.o
@@@ -1629,12 -1569,6 +1630,12 @@@ ifdef NO_INET_PTO
        LIB_OBJS += compat/inet_pton.o
        BASIC_CFLAGS += -DNO_INET_PTON
  endif
 +ifndef NO_UNIX_SOCKETS
 +      LIB_OBJS += unix-socket.o
 +      LIB_H += unix-socket.h
 +      PROGRAM_OBJS += credential-cache.o
 +      PROGRAM_OBJS += credential-cache--daemon.o
 +endif
  
  ifdef NO_ICONV
        BASIC_CFLAGS += -DNO_ICONV
@@@ -1697,15 -1631,6 +1698,15 @@@ ifdef HAVE_PATHS_
        BASIC_CFLAGS += -DHAVE_PATHS_H
  endif
  
 +ifdef HAVE_LIBCHARSET_H
 +      BASIC_CFLAGS += -DHAVE_LIBCHARSET_H
 +      EXTLIBS += $(CHARSET_LIB)
 +endif
 +
 +ifdef HAVE_DEV_TTY
 +      BASIC_CFLAGS += -DHAVE_DEV_TTY
 +endif
 +
  ifdef DIR_HAS_BSD_GROUP_SEMANTICS
        COMPAT_CFLAGS += -DDIR_HAS_BSD_GROUP_SEMANTICS
  endif
@@@ -1726,10 -1651,6 +1727,10 @@@ ifdef GIT_TEST_CMP_USE_COPIED_CONTEX
        export GIT_TEST_CMP_USE_COPIED_CONTEXT
  endif
  
 +ifndef NO_MSGFMT_EXTENDED_OPTIONS
 +      MSGFMT += --check --statistics
 +endif
 +
  ifeq ($(TCLTK_PATH),)
  NO_TCLTK=NoThanks
  endif
@@@ -1760,7 -1681,6 +1761,7 @@@ ifndef 
        QUIET_GEN      = @echo '   ' GEN $@;
        QUIET_LNCP     = @echo '   ' LN/CP $@;
        QUIET_XGETTEXT = @echo '   ' XGETTEXT $@;
 +      QUIET_MSGFMT   = @echo '   ' MSGFMT $@;
        QUIET_GCOV     = @echo '   ' GCOV $@;
        QUIET_SP       = @echo '   ' SP $<;
        QUIET_SUBDIR0  = +@subdir=
@@@ -1776,26 -1696,6 +1777,26 @@@ ifdef ASCIIDOC
        export ASCIIDOC7
  endif
  
 +### profile feedback build
 +#
 +
 +# Can adjust this to be a global directory if you want to do extended
 +# data gathering
 +PROFILE_DIR := $(CURDIR)
 +
 +ifeq ("$(PROFILE)","GEN")
 +      CFLAGS += -fprofile-generate=$(PROFILE_DIR) -DNO_NORETURN=1
 +      EXTLIBS += -lgcov
 +      export CCACHE_DISABLE=t
 +      V=1
 +else
 +ifneq ("$(PROFILE)","")
 +      CFLAGS += -fprofile-use=$(PROFILE_DIR) -fprofile-correction -DNO_NORETURN=1
 +      export CCACHE_DISABLE=t
 +      V=1
 +endif
 +endif
 +
  # Shell quote (do not use $(call) to accommodate ancient setups);
  
  SHA1_HEADER_SQ = $(subst ','\'',$(SHA1_HEADER))
@@@ -1807,7 -1707,6 +1808,7 @@@ bindir_SQ = $(subst ','\'',$(bindir)
  bindir_relative_SQ = $(subst ','\'',$(bindir_relative))
  mandir_SQ = $(subst ','\'',$(mandir))
  infodir_SQ = $(subst ','\'',$(infodir))
 +localedir_SQ = $(subst ','\'',$(localedir))
  gitexecdir_SQ = $(subst ','\'',$(gitexecdir))
  template_dir_SQ = $(subst ','\'',$(template_dir))
  htmldir_SQ = $(subst ','\'',$(htmldir))
@@@ -1852,17 -1751,7 +1853,17 @@@ export DIFF TAR INSTALL DESTDIR SHELL_P
  
  SHELL = $(SHELL_PATH)
  
 -all:: shell_compatibility_test $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) $(OTHER_PROGRAMS) GIT-BUILD-OPTIONS
 +all:: shell_compatibility_test
 +
 +ifeq "$(PROFILE)" "BUILD"
 +ifeq ($(filter all,$(MAKECMDGOALS)),all)
 +all:: profile-clean
 +      $(MAKE) PROFILE=GEN all
 +      $(MAKE) PROFILE=GEN -j1 test
 +endif
 +endif
 +
 +all:: $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) $(OTHER_PROGRAMS) GIT-BUILD-OPTIONS
  ifneq (,$X)
        $(QUIET_BUILT_IN)$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), test -d '$p' -o '$p' -ef '$p$X' || $(RM) '$p';)
  endif
@@@ -1873,7 -1762,7 +1874,7 @@@ ifndef NO_TCLT
        $(QUIET_SUBDIR0)gitk-git $(QUIET_SUBDIR1) all
  endif
  ifndef NO_PERL
 -      $(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' all
 +      $(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' localedir='$(localedir_SQ)' all
  endif
  ifndef NO_PYTHON
        $(QUIET_SUBDIR0)git_remote_helpers $(QUIET_SUBDIR1) PYTHON_PATH='$(PYTHON_PATH_SQ)' prefix='$(prefix_SQ)' all
@@@ -1923,7 -1812,6 +1924,7 @@@ sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|
      -e 's|@SHELL_PATH@|$(SHELL_PATH_SQ)|' \
      -e 's|@@DIFF@@|$(DIFF_SQ)|' \
      -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
 +    -e 's|@@LOCALEDIR@@|$(localedir_SQ)|g' \
      -e 's/@@NO_CURL@@/$(NO_CURL)/g' \
      -e $(BROKEN_PATH_FIX) \
      $@.sh >$@+
@@@ -2176,9 -2064,6 +2177,9 @@@ config.sp config.s config.o: EXTRA_CPPF
  attr.sp attr.s attr.o: EXTRA_CPPFLAGS = \
        -DETC_GITATTRIBUTES='"$(ETC_GITATTRIBUTES_SQ)"'
  
 +gettext.sp gettext.s gettext.o: EXTRA_CPPFLAGS = \
 +      -DGIT_LOCALE_PATH='"$(localedir_SQ)"'
 +
  http.sp http.s http.o: EXTRA_CPPFLAGS = \
        -DGIT_HTTP_USER_AGENT='"git/$(GIT_VERSION)"'
  
@@@ -2252,37 -2137,17 +2253,37 @@@ XGETTEXT_FLAGS = 
  XGETTEXT_FLAGS_C = $(XGETTEXT_FLAGS) --language=C \
        --keyword=_ --keyword=N_ --keyword="Q_:1,2"
  XGETTEXT_FLAGS_SH = $(XGETTEXT_FLAGS) --language=Shell
 +XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --keyword=__ --language=Perl
  LOCALIZED_C := $(C_OBJ:o=c)
  LOCALIZED_SH := $(SCRIPT_SH)
 +LOCALIZED_PERL := $(SCRIPT_PERL)
 +
 +ifdef XGETTEXT_INCLUDE_TESTS
 +LOCALIZED_C += t/t0200/test.c
 +LOCALIZED_SH += t/t0200/test.sh
 +LOCALIZED_PERL += t/t0200/test.perl
 +endif
  
  po/git.pot: $(LOCALIZED_C)
        $(QUIET_XGETTEXT)$(XGETTEXT) -o$@+ $(XGETTEXT_FLAGS_C) $(LOCALIZED_C)
        $(QUIET_XGETTEXT)$(XGETTEXT) -o$@+ --join-existing $(XGETTEXT_FLAGS_SH) \
                $(LOCALIZED_SH)
 +      $(QUIET_XGETTEXT)$(XGETTEXT) -o$@+ --join-existing $(XGETTEXT_FLAGS_PERL) \
 +              $(LOCALIZED_PERL)
        mv $@+ $@
  
  pot: po/git.pot
  
 +POFILES := $(wildcard po/*.po)
 +MOFILES := $(patsubst po/%.po,po/build/locale/%/LC_MESSAGES/git.mo,$(POFILES))
 +
 +ifndef NO_GETTEXT
 +all:: $(MOFILES)
 +endif
 +
 +po/build/locale/%/LC_MESSAGES/git.mo: po/%.po
 +      $(QUIET_MSGFMT)mkdir -p $(dir $@) && $(MSGFMT) -o $@ $<
 +
  FIND_SOURCE_FILES = ( git ls-files '*.[hcS]' 2>/dev/null || \
                        $(FIND) . \( -name .git -type d -prune \) \
                                -o \( -name '*.[hcS]' -type f -print \) )
@@@ -2301,8 -2166,7 +2302,8 @@@ cscope
  
  ### Detect prefix changes
  TRACK_CFLAGS = $(CC):$(subst ','\'',$(ALL_CFLAGS)):\
 -             $(bindir_SQ):$(gitexecdir_SQ):$(template_dir_SQ):$(prefix_SQ)
 +             $(bindir_SQ):$(gitexecdir_SQ):$(template_dir_SQ):$(prefix_SQ):\
 +             $(localedir_SQ)
  
  GIT-CFLAGS: FORCE
        @FLAGS='$(TRACK_CFLAGS)'; \
@@@ -2339,9 -2203,7 +2340,9 @@@ endi
  ifdef GIT_TEST_CMP_USE_COPIED_CONTEXT
        @echo GIT_TEST_CMP_USE_COPIED_CONTEXT=YesPlease >>$@
  endif
 +      @echo NO_GETTEXT=\''$(subst ','\'',$(subst ','\'',$(NO_GETTEXT)))'\' >>$@
        @echo GETTEXT_POISON=\''$(subst ','\'',$(subst ','\'',$(GETTEXT_POISON)))'\' >>$@
 +      @echo NO_UNIX_SOCKETS=\''$(subst ','\'',$(subst ','\'',$(NO_UNIX_SOCKETS)))'\' >>$@
  
  ### Detect Tck/Tk interpreter path changes
  ifndef NO_TCLTK
@@@ -2456,11 -2318,6 +2457,11 @@@ install: al
        $(MAKE) -C templates DESTDIR='$(DESTDIR_SQ)' install
        $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(mergetools_instdir_SQ)'
        $(INSTALL) -m 644 mergetools/* '$(DESTDIR_SQ)$(mergetools_instdir_SQ)'
 +ifndef NO_GETTEXT
 +      $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(localedir_SQ)'
 +      (cd po/build/locale && $(TAR) cf - .) | \
 +      (cd '$(DESTDIR_SQ)$(localedir_SQ)' && umask 022 && $(TAR) xof -)
 +endif
  ifndef NO_PERL
        $(MAKE) -C perl prefix='$(prefix_SQ)' DESTDIR='$(DESTDIR_SQ)' install
        $(MAKE) -C gitweb install
@@@ -2590,18 -2447,13 +2591,18 @@@ distclean: clea
        $(RM) configure
        $(RM) po/git.pot
  
 -clean:
 +profile-clean:
 +      $(RM) $(addsuffix *.gcda,$(addprefix $(PROFILE_DIR)/, $(object_dirs)))
 +      $(RM) $(addsuffix *.gcno,$(addprefix $(PROFILE_DIR)/, $(object_dirs)))
 +
 +clean: profile-clean
        $(RM) *.o block-sha1/*.o ppc/*.o compat/*.o compat/*/*.o xdiff/*.o vcs-svn/*.o \
                builtin/*.o $(LIB_FILE) $(XDIFF_LIB) $(VCSSVN_LIB)
        $(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git$X
        $(RM) $(TEST_PROGRAMS)
        $(RM) -r bin-wrappers
        $(RM) -r $(dep_dirs)
 +      $(RM) -r po/build/
        $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h $(ETAGS_TARGET) tags cscope*
        $(RM) -r autom4te.cache
        $(RM) config.log config.mak.autogen config.mak.append config.status config.cache
@@@ -2624,7 -2476,7 +2625,7 @@@ ifndef NO_TCLT
  endif
        $(RM) GIT-VERSION-FILE GIT-CFLAGS GIT-LDFLAGS GIT-GUI-VARS GIT-BUILD-OPTIONS
  
 -.PHONY: all install clean strip
 +.PHONY: all install profile-clean clean strip
  .PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
  .PHONY: FORCE cscope
  
@@@ -2734,3 -2586,18 +2735,3 @@@ cover_db: coverage-repor
  cover_db_html: cover_db
        cover -report html -outputdir cover_db_html cover_db
  
 -### profile feedback build
 -#
 -.PHONY: profile-all profile-clean
 -
 -PROFILE_GEN_CFLAGS := $(CFLAGS) -fprofile-generate -DNO_NORETURN=1
 -PROFILE_USE_CFLAGS := $(CFLAGS) -fprofile-use -fprofile-correction -DNO_NORETURN=1
 -
 -profile-clean:
 -      $(RM) $(addsuffix *.gcda,$(object_dirs))
 -      $(RM) $(addsuffix *.gcno,$(object_dirs))
 -
 -profile-all: profile-clean
 -      $(MAKE) CFLAGS="$(PROFILE_GEN_CFLAGS)" all
 -      $(MAKE) CFLAGS="$(PROFILE_GEN_CFLAGS)" -j1 test
 -      $(MAKE) CFLAGS="$(PROFILE_USE_CFLAGS)" all
diff --combined grep.c
index 3821400966823ff6bf877abf94f4edea9b6b80c6,9c5e1cd950c8d1d97290a047fb3780482f8eb8b7..f492d267cc157d46f899c70d01ea707d737d27ae
--- 1/grep.c
--- 2/grep.c
+++ b/grep.c
@@@ -79,7 -79,7 +79,7 @@@ static void compile_pcre_regexp(struct 
  {
        const char *error;
        int erroffset;
-       int options = 0;
+       int options = PCRE_MULTILINE;
  
        if (opt->ignore_case)
                options |= PCRE_CASELESS;
@@@ -806,51 -806,10 +806,51 @@@ static void show_line(struct grep_opt *
        opt->output(opt, "\n", 1);
  }
  
 -static int match_funcname(struct grep_opt *opt, char *bol, char *eol)
 +#ifndef NO_PTHREADS
 +int grep_use_locks;
 +
 +/*
 + * This lock protects access to the gitattributes machinery, which is
 + * not thread-safe.
 + */
 +pthread_mutex_t grep_attr_mutex;
 +
 +static inline void grep_attr_lock(void)
 +{
 +      if (grep_use_locks)
 +              pthread_mutex_lock(&grep_attr_mutex);
 +}
 +
 +static inline void grep_attr_unlock(void)
 +{
 +      if (grep_use_locks)
 +              pthread_mutex_unlock(&grep_attr_mutex);
 +}
 +
 +/*
 + * Same as git_attr_mutex, but protecting the thread-unsafe object db access.
 + */
 +pthread_mutex_t grep_read_mutex;
 +
 +#else
 +#define grep_attr_lock()
 +#define grep_attr_unlock()
 +#endif
 +
 +static int match_funcname(struct grep_opt *opt, struct grep_source *gs, char *bol, char *eol)
  {
        xdemitconf_t *xecfg = opt->priv;
 -      if (xecfg && xecfg->find_func) {
 +      if (xecfg && !xecfg->find_func) {
 +              grep_source_load_driver(gs);
 +              if (gs->driver->funcname.pattern) {
 +                      const struct userdiff_funcname *pe = &gs->driver->funcname;
 +                      xdiff_set_find_func(xecfg, pe->pattern, pe->cflags);
 +              } else {
 +                      xecfg = opt->priv = NULL;
 +              }
 +      }
 +
 +      if (xecfg) {
                char buf[1];
                return xecfg->find_func(bol, eol - bol, buf, 1,
                                        xecfg->find_func_priv) >= 0;
        return 0;
  }
  
 -static void show_funcname_line(struct grep_opt *opt, const char *name,
 -                             char *buf, char *bol, unsigned lno)
 +static void show_funcname_line(struct grep_opt *opt, struct grep_source *gs,
 +                             char *bol, unsigned lno)
  {
 -      while (bol > buf) {
 +      while (bol > gs->buf) {
                char *eol = --bol;
  
 -              while (bol > buf && bol[-1] != '\n')
 +              while (bol > gs->buf && bol[-1] != '\n')
                        bol--;
                lno--;
  
                if (lno <= opt->last_shown)
                        break;
  
 -              if (match_funcname(opt, bol, eol)) {
 -                      show_line(opt, bol, eol, name, lno, '=');
 +              if (match_funcname(opt, gs, bol, eol)) {
 +                      show_line(opt, bol, eol, gs->name, lno, '=');
                        break;
                }
        }
  }
  
 -static void show_pre_context(struct grep_opt *opt, const char *name, char *buf,
 +static void show_pre_context(struct grep_opt *opt, struct grep_source *gs,
                             char *bol, char *end, unsigned lno)
  {
        unsigned cur = lno, from = 1, funcname_lno = 0;
        int funcname_needed = !!opt->funcname;
  
 -      if (opt->funcbody && !match_funcname(opt, bol, end))
 +      if (opt->funcbody && !match_funcname(opt, gs, bol, end))
                funcname_needed = 2;
  
        if (opt->pre_context < lno)
                from = opt->last_shown + 1;
  
        /* Rewind. */
 -      while (bol > buf &&
 +      while (bol > gs->buf &&
               cur > (funcname_needed == 2 ? opt->last_shown + 1 : from)) {
                char *eol = --bol;
  
 -              while (bol > buf && bol[-1] != '\n')
 +              while (bol > gs->buf && bol[-1] != '\n')
                        bol--;
                cur--;
 -              if (funcname_needed && match_funcname(opt, bol, eol)) {
 +              if (funcname_needed && match_funcname(opt, gs, bol, eol)) {
                        funcname_lno = cur;
                        funcname_needed = 0;
                }
  
        /* We need to look even further back to find a function signature. */
        if (opt->funcname && funcname_needed)
 -              show_funcname_line(opt, name, buf, bol, cur);
 +              show_funcname_line(opt, gs, bol, cur);
  
        /* Back forward. */
        while (cur < lno) {
  
                while (*eol != '\n')
                        eol++;
 -              show_line(opt, bol, eol, name, cur, sign);
 +              show_line(opt, bol, eol, gs->name, cur, sign);
                bol = eol + 1;
                cur++;
        }
@@@ -983,15 -942,29 +983,15 @@@ static int look_ahead(struct grep_opt *
        return 0;
  }
  
 -int grep_threads_ok(const struct grep_opt *opt)
 -{
 -      /* If this condition is true, then we may use the attribute
 -       * machinery in grep_buffer_1. The attribute code is not
 -       * thread safe, so we disable the use of threads.
 -       */
 -      if (opt->funcname && !opt->unmatch_name_only && !opt->status_only &&
 -          !opt->name_only)
 -              return 0;
 -
 -      return 1;
 -}
 -
  static void std_output(struct grep_opt *opt, const void *buf, size_t size)
  {
        fwrite(buf, size, 1, stdout);
  }
  
 -static int grep_buffer_1(struct grep_opt *opt, const char *name,
 -                       char *buf, unsigned long size, int collect_hits)
 +static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int collect_hits)
  {
 -      char *bol = buf;
 -      unsigned long left = size;
 +      char *bol;
 +      unsigned long left;
        unsigned lno = 1;
        unsigned last_hit = 0;
        int binary_match_only = 0;
  
        switch (opt->binary) {
        case GREP_BINARY_DEFAULT:
 -              if (buffer_is_binary(buf, size))
 +              if (grep_source_is_binary(gs))
                        binary_match_only = 1;
                break;
        case GREP_BINARY_NOMATCH:
 -              if (buffer_is_binary(buf, size))
 +              if (grep_source_is_binary(gs))
                        return 0; /* Assume unmatch */
                break;
        case GREP_BINARY_TEXT:
        }
  
        memset(&xecfg, 0, sizeof(xecfg));
 -      if (opt->funcname && !opt->unmatch_name_only && !opt->status_only &&
 -          !opt->name_only && !binary_match_only && !collect_hits) {
 -              struct userdiff_driver *drv = userdiff_find_by_path(name);
 -              if (drv && drv->funcname.pattern) {
 -                      const struct userdiff_funcname *pe = &drv->funcname;
 -                      xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags);
 -                      opt->priv = &xecfg;
 -              }
 -      }
 +      opt->priv = &xecfg;
 +
        try_lookahead = should_lookahead(opt);
  
 +      if (grep_source_load(gs) < 0)
 +              return 0;
 +
 +      bol = gs->buf;
 +      left = gs->size;
        while (left) {
                char *eol, ch;
                int hit;
                        if (opt->status_only)
                                return 1;
                        if (opt->name_only) {
 -                              show_name(opt, name);
 +                              show_name(opt, gs->name);
                                return 1;
                        }
                        if (opt->count)
                                goto next_line;
                        if (binary_match_only) {
                                opt->output(opt, "Binary file ", 12);
 -                              output_color(opt, name, strlen(name),
 +                              output_color(opt, gs->name, strlen(gs->name),
                                             opt->color_filename);
                                opt->output(opt, " matches\n", 9);
                                return 1;
                         * pre-context lines, we would need to show them.
                         */
                        if (opt->pre_context || opt->funcbody)
 -                              show_pre_context(opt, name, buf, bol, eol, lno);
 +                              show_pre_context(opt, gs, bol, eol, lno);
                        else if (opt->funcname)
 -                              show_funcname_line(opt, name, buf, bol, lno);
 -                      show_line(opt, bol, eol, name, lno, ':');
 +                              show_funcname_line(opt, gs, bol, lno);
 +                      show_line(opt, bol, eol, gs->name, lno, ':');
                        last_hit = lno;
                        if (opt->funcbody)
                                show_function = 1;
                        goto next_line;
                }
 -              if (show_function && match_funcname(opt, bol, eol))
 +              if (show_function && match_funcname(opt, gs, bol, eol))
                        show_function = 0;
                if (show_function ||
                    (last_hit && lno <= last_hit + opt->post_context)) {
                        /* If the last hit is within the post context,
                         * we need to show this line.
                         */
 -                      show_line(opt, bol, eol, name, lno, '-');
 +                      show_line(opt, bol, eol, gs->name, lno, '-');
                }
  
        next_line:
                return 0;
        if (opt->unmatch_name_only) {
                /* We did not see any hit, so we want to show this */
 -              show_name(opt, name);
 +              show_name(opt, gs->name);
                return 1;
        }
  
         */
        if (opt->count && count) {
                char buf[32];
 -              output_color(opt, name, strlen(name), opt->color_filename);
 +              output_color(opt, gs->name, strlen(gs->name), opt->color_filename);
                output_sep(opt, ':');
                snprintf(buf, sizeof(buf), "%u\n", count);
                opt->output(opt, buf, strlen(buf));
@@@ -1191,174 -1166,23 +1191,174 @@@ static int chk_hit_marker(struct grep_e
        }
  }
  
 -int grep_buffer(struct grep_opt *opt, const char *name, char *buf, unsigned long size)
 +int grep_source(struct grep_opt *opt, struct grep_source *gs)
  {
        /*
         * we do not have to do the two-pass grep when we do not check
         * buffer-wide "all-match".
         */
        if (!opt->all_match)
 -              return grep_buffer_1(opt, name, buf, size, 0);
 +              return grep_source_1(opt, gs, 0);
  
        /* Otherwise the toplevel "or" terms hit a bit differently.
         * We first clear hit markers from them.
         */
        clr_hit_marker(opt->pattern_expression);
 -      grep_buffer_1(opt, name, buf, size, 1);
 +      grep_source_1(opt, gs, 1);
  
        if (!chk_hit_marker(opt->pattern_expression))
                return 0;
  
 -      return grep_buffer_1(opt, name, buf, size, 0);
 +      return grep_source_1(opt, gs, 0);
 +}
 +
 +int grep_buffer(struct grep_opt *opt, char *buf, unsigned long size)
 +{
 +      struct grep_source gs;
 +      int r;
 +
 +      grep_source_init(&gs, GREP_SOURCE_BUF, NULL, NULL);
 +      gs.buf = buf;
 +      gs.size = size;
 +
 +      r = grep_source(opt, &gs);
 +
 +      grep_source_clear(&gs);
 +      return r;
 +}
 +
 +void grep_source_init(struct grep_source *gs, enum grep_source_type type,
 +                    const char *name, const void *identifier)
 +{
 +      gs->type = type;
 +      gs->name = name ? xstrdup(name) : NULL;
 +      gs->buf = NULL;
 +      gs->size = 0;
 +      gs->driver = NULL;
 +
 +      switch (type) {
 +      case GREP_SOURCE_FILE:
 +              gs->identifier = xstrdup(identifier);
 +              break;
 +      case GREP_SOURCE_SHA1:
 +              gs->identifier = xmalloc(20);
 +              memcpy(gs->identifier, identifier, 20);
 +              break;
 +      case GREP_SOURCE_BUF:
 +              gs->identifier = NULL;
 +      }
 +}
 +
 +void grep_source_clear(struct grep_source *gs)
 +{
 +      free(gs->name);
 +      gs->name = NULL;
 +      free(gs->identifier);
 +      gs->identifier = NULL;
 +      grep_source_clear_data(gs);
 +}
 +
 +void grep_source_clear_data(struct grep_source *gs)
 +{
 +      switch (gs->type) {
 +      case GREP_SOURCE_FILE:
 +      case GREP_SOURCE_SHA1:
 +              free(gs->buf);
 +              gs->buf = NULL;
 +              gs->size = 0;
 +              break;
 +      case GREP_SOURCE_BUF:
 +              /* leave user-provided buf intact */
 +              break;
 +      }
 +}
 +
 +static int grep_source_load_sha1(struct grep_source *gs)
 +{
 +      enum object_type type;
 +
 +      grep_read_lock();
 +      gs->buf = read_sha1_file(gs->identifier, &type, &gs->size);
 +      grep_read_unlock();
 +
 +      if (!gs->buf)
 +              return error(_("'%s': unable to read %s"),
 +                           gs->name,
 +                           sha1_to_hex(gs->identifier));
 +      return 0;
 +}
 +
 +static int grep_source_load_file(struct grep_source *gs)
 +{
 +      const char *filename = gs->identifier;
 +      struct stat st;
 +      char *data;
 +      size_t size;
 +      int i;
 +
 +      if (lstat(filename, &st) < 0) {
 +      err_ret:
 +              if (errno != ENOENT)
 +                      error(_("'%s': %s"), filename, strerror(errno));
 +              return -1;
 +      }
 +      if (!S_ISREG(st.st_mode))
 +              return -1;
 +      size = xsize_t(st.st_size);
 +      i = open(filename, O_RDONLY);
 +      if (i < 0)
 +              goto err_ret;
 +      data = xmalloc(size + 1);
 +      if (st.st_size != read_in_full(i, data, size)) {
 +              error(_("'%s': short read %s"), filename, strerror(errno));
 +              close(i);
 +              free(data);
 +              return -1;
 +      }
 +      close(i);
 +      data[size] = 0;
 +
 +      gs->buf = data;
 +      gs->size = size;
 +      return 0;
 +}
 +
 +int grep_source_load(struct grep_source *gs)
 +{
 +      if (gs->buf)
 +              return 0;
 +
 +      switch (gs->type) {
 +      case GREP_SOURCE_FILE:
 +              return grep_source_load_file(gs);
 +      case GREP_SOURCE_SHA1:
 +              return grep_source_load_sha1(gs);
 +      case GREP_SOURCE_BUF:
 +              return gs->buf ? 0 : -1;
 +      }
 +      die("BUG: invalid grep_source type");
 +}
 +
 +void grep_source_load_driver(struct grep_source *gs)
 +{
 +      if (gs->driver)
 +              return;
 +
 +      grep_attr_lock();
 +      gs->driver = userdiff_find_by_path(gs->name);
 +      if (!gs->driver)
 +              gs->driver = userdiff_find_by_name("default");
 +      grep_attr_unlock();
 +}
 +
 +int grep_source_is_binary(struct grep_source *gs)
 +{
 +      grep_source_load_driver(gs);
 +      if (gs->driver->binary != -1)
 +              return gs->driver->binary;
 +
 +      if (!grep_source_load(gs))
 +              return buffer_is_binary(gs->buf, gs->size);
 +
 +      return 0;
  }
diff --combined t/t4150-am.sh
index 7e6e59aefe48aa41d23ddd0a82bbff18abd8705f,03eee07ffb3bcbcac3090eeb3a58e5dcbb66307f..00d669a3c9bbf3329cf800fc15147770a45e6a4b
@@@ -136,7 -136,7 +136,7 @@@ test_expect_success setup 
        git format-patch -M --stdout lorem^ >rename-add.patch &&
  
        # reset time
 -      unset test_tick &&
 +      sane_unset test_tick &&
        test_tick
  '
  
@@@ -495,4 -495,14 +495,14 @@@ test_expect_success 'am -q is quiet' 
        ! test -s output.out
  '
  
+ test_expect_success 'am empty-file does not infloop' '
+       rm -fr .git/rebase-apply &&
+       git reset --hard &&
+       touch empty-file &&
+       test_tick &&
+       { git am empty-file > actual 2>&1 && false || :; } &&
+       echo Patch format detection failed. >expected &&
+       test_cmp expected actual
+ '
  test_done