Merge branch 'maint'

* maint:
  Documentation: tighten dependency for git.{html,txt}
  Makefile: iconv() on Darwin has the old interface
  t5300-pack-object.sh: portability issue using /usr/bin/stat
  t3200-branch.sh: small language nit
  usermanual.txt: some capitalization nits
  Make builtin-branch.c handle the git config file
  rename_ref(): only print a warning when config-file update fails
  Distinguish branches by more than case in tests.
  Avoid composing too long "References" header.
  cvsimport: Improve formating consistency
  cvsimport: Reorder options in documentation for better understanding
  cvsimport: Improve usage error reporting
  cvsimport: Improve documentation of CVSROOT and CVS module determination
  cvsimport: sync usage lines with existing options

Conflicts:

	Documentation/Makefile
diff --git a/.gitignore b/.gitignore
index e8d2731..b39f78f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
 GIT-CFLAGS
+GIT-GUI-VARS
 GIT-VERSION-FILE
 git
 git-add
@@ -141,6 +142,7 @@
 git-whatchanged
 git-write-tree
 git-core-*/?*
+gitk-wish
 gitweb/gitweb.cgi
 test-chmtime
 test-date
diff --git a/Documentation/Makefile b/Documentation/Makefile
index ad87736..a637d8d 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -65,6 +65,11 @@
 	$(INSTALL) -m644 $(DOC_MAN7) $(DESTDIR)$(man7dir)
 
 
+../GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
+	$(MAKE) -C ../ GIT-VERSION-FILE
+
+-include ../GIT-VERSION-FILE
+
 #
 # Determine "include::" file references in asciidoc files.
 #
@@ -94,17 +99,25 @@
 git.7 git.html: git.txt core-intro.txt
 
 clean:
-	rm -f *.xml *.html *.1 *.7 howto-index.txt howto/*.html doc.dep
+	rm -f *.xml *.xml+ *.html *.html+ *.1 *.7 howto-index.txt howto/*.html doc.dep
 	rm -f $(cmds_txt) *.made
 
 %.html : %.txt
-	$(ASCIIDOC) -b xhtml11 -d manpage -f asciidoc.conf $(ASCIIDOC_EXTRA) $<
+	rm -f $@+ $@
+	$(ASCIIDOC) -b xhtml11 -d manpage -f asciidoc.conf \
+		$(ASCIIDOC_EXTRA) -o - $< | \
+		sed -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' >$@+
+	mv $@+ $@
 
 %.1 %.7 : %.xml
 	xmlto -m callouts.xsl man $<
 
 %.xml : %.txt
-	$(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf $<
+	rm -f $@+ $@
+	$(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf \
+		$(ASCIIDOC_EXTRA) -o - $< | \
+		sed -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' >$@+
+	mv $@+ $@
 
 user-manual.xml: user-manual.txt user-manual.conf
 	$(ASCIIDOC) -b docbook -d book $<
@@ -135,3 +148,5 @@
 
 quick-install:
 	sh ./install-doc-quick.sh $(DOC_REF) $(mandir)
+
+.PHONY: .FORCE-GIT-VERSION-FILE
diff --git a/Documentation/asciidoc.conf b/Documentation/asciidoc.conf
index 44b1ce4..fa7dc94 100644
--- a/Documentation/asciidoc.conf
+++ b/Documentation/asciidoc.conf
@@ -31,6 +31,25 @@
 {title#}</example>
 endif::backend-docbook[]
 
+ifdef::doctype-manpage[]
+ifdef::backend-docbook[]
+[header]
+template::[header-declarations]
+<refentry>
+<refmeta>
+<refentrytitle>{mantitle}</refentrytitle>
+<manvolnum>{manvolnum}</manvolnum>
+<refmiscinfo class="source">Git</refmiscinfo>
+<refmiscinfo class="version">@@GIT_VERSION@@</refmiscinfo>
+<refmiscinfo class="manual">Git Manual</refmiscinfo>
+</refmeta>
+<refnamediv>
+  <refname>{manname}</refname>
+  <refpurpose>{manpurpose}</refpurpose>
+</refnamediv>
+endif::backend-docbook[]
+endif::doctype-manpage[]
+
 ifdef::backend-xhtml11[]
 [gitlink-inlinemacro]
 <a href="{target}.html">{target}{0?({0})}</a>
diff --git a/Documentation/git-fsck.txt b/Documentation/git-fsck.txt
index 058009d..8c68cf0 100644
--- a/Documentation/git-fsck.txt
+++ b/Documentation/git-fsck.txt
@@ -9,7 +9,7 @@
 SYNOPSIS
 --------
 [verse]
-'git-fsck' [--tags] [--root] [--unreachable] [--cache]
+'git-fsck' [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]
 		 [--full] [--strict] [<object>*]
 
 DESCRIPTION
@@ -38,6 +38,12 @@
 	Consider any object recorded in the index also as a head node for
 	an unreachability trace.
 
+--no-reflogs::
+	Do not consider commits that are referenced only by an
+	entry in a reflog to be reachable.  This option is meant
+	only to search for commits that used to be in a ref, but
+	now aren't, but are still in that corresponding reflog.
+
 --full::
 	Check not just objects in GIT_OBJECT_DIRECTORY
 	($GIT_DIR/objects), but also the ones found in alternate
diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt
index 11ce395..12b71ed 100644
--- a/Documentation/git-rev-list.txt
+++ b/Documentation/git-rev-list.txt
@@ -27,6 +27,7 @@
 	     [ [\--objects | \--objects-edge] [ \--unpacked ] ]
 	     [ \--pretty | \--header ]
 	     [ \--bisect ]
+	     [ \--bisect-vars ]
 	     [ \--merge ]
 	     [ \--reverse ]
 	     [ \--walk-reflogs ]
@@ -280,6 +281,18 @@
 generate and test new 'midpoint's until the commit chain is of length
 one.
 
+--bisect-vars::
+
+This calculates the same as `--bisect`, but outputs text ready
+to be eval'ed by the shell. These lines will assign the name of
+the midpoint revision to the variable `bisect_rev`, and the
+expected number of commits to be tested after `bisect_rev` is
+tested to `bisect_nr`, the expected number of commits to be
+tested if `bisect_rev` turns out to be good to `bisect_good`,
+the expected number of commits to be tested if `bisect_rev`
+turns out to be bad to `bisect_bad`, and the number of commits
+we are bisecting right now to `bisect_all`.
+
 --
 
 Commit Ordering
diff --git a/Makefile b/Makefile
index dcdaa02..ba21458 100644
--- a/Makefile
+++ b/Makefile
@@ -110,6 +110,14 @@
 # Define NO_PERL_MAKEMAKER if you cannot use Makefiles generated by perl's
 # MakeMaker (e.g. using ActiveState under Cygwin).
 #
+# Define WITH_P4IMPORT to build and install Python git-p4import script.
+#
+# Define NO_TCLTK if you do not want Tcl/Tk GUI.
+#
+# The TCLTK_PATH variable governs the location of the Tck/Tk interpreter.
+# If not set it defaults to the bare 'wish'. If it is set to the empty
+# string then NO_TCLTK will be forced (this is used by configure script).
+#
 
 GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
 	@$(SHELL_PATH) ./GIT-VERSION-GEN
@@ -159,6 +167,7 @@
 TAR = tar
 INSTALL = install
 RPMBUILD = rpmbuild
+TCLTK_PATH = wish
 
 # sparse is architecture-neutral, which means that we need to tell it
 # explicitly what architecture to check for. Fix this up for yours..
@@ -196,9 +205,20 @@
 	git-svnimport.perl git-cvsexportcommit.perl \
 	git-send-email.perl git-svn.perl
 
+SCRIPT_PYTHON = \
+	git-p4import.py
+
+ifdef WITH_P4IMPORT
+SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
+	  $(patsubst %.perl,%,$(SCRIPT_PERL)) \
+	  $(patsubst %.py,%,$(SCRIPT_PYTHON)) \
+	  git-status git-instaweb
+else
 SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
 	  $(patsubst %.perl,%,$(SCRIPT_PERL)) \
 	  git-status git-instaweb
+endif
+
 
 # ... and all the rest that could be moved out of bindir to gitexecdir
 PROGRAMS = \
@@ -231,6 +251,12 @@
 # what 'all' will build and 'install' will install, in gitexecdir
 ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
 
+# what 'all' will build but not install in gitexecdir
+OTHER_PROGRAMS = git$X gitweb/gitweb.cgi
+ifndef NO_TCLTK
+OTHER_PROGRAMS += gitk-wish
+endif
+
 # Backward compatibility -- to be removed after 1.0
 PROGRAMS += git-ssh-pull$X git-ssh-push$X
 
@@ -241,6 +267,9 @@
 ifndef PERL_PATH
 	PERL_PATH = /usr/bin/perl
 endif
+ifndef PYTHON_PATH
+	PYTHON_PATH = /usr/local/bin/python
+endif
 
 export PERL_PATH
 
@@ -609,6 +638,10 @@
 	export NO_PERL_MAKEMAKER
 endif
 
+ifeq ($(TCLTK_PATH),)
+NO_TCLTK=NoThanks
+endif
+
 QUIET_SUBDIR0  = $(MAKE) -C # space to separate -C and subdir
 QUIET_SUBDIR1  =
 
@@ -647,6 +680,8 @@
 
 SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
 PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
+PYTHON_PATH_SQ = $(subst ','\'',$(PYTHON_PATH))
+TCLTK_PATH_SQ = $(subst ','\'',$(TCLTK_PATH))
 
 LIBS = $(GITLIBS) $(EXTLIBS)
 
@@ -662,19 +697,27 @@
 
 ### Build rules
 
-all:: $(ALL_PROGRAMS) $(BUILT_INS) git$X gitk gitweb/gitweb.cgi
+all:: $(ALL_PROGRAMS) $(BUILT_INS) $(OTHER_PROGRAMS)
 ifneq (,$X)
 	$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), rm -f '$p';)
 endif
 
 all::
-	$(QUIET_SUBDIR0)git-gui $(QUIET_SUBDIR1) all
+ifndef NO_TCLTK
+	$(QUIET_SUBDIR0)git-gui $(QUIET_SUBDIR1) TCLTK_PATH='$(TCLTK_PATH_SQ)' all
+endif
 	$(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' all
 	$(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1)
 
 strip: $(PROGRAMS) git$X
 	$(STRIP) $(STRIP_OPTS) $(PROGRAMS) git$X
 
+gitk-wish: gitk GIT-GUI-VARS
+	$(QUIET_GEN)rm -f $@ $@+ && \
+	sed -e '1,3s|^exec .* "$$0"|exec $(subst |,'\|',$(TCLTK_PATH_SQ)) "$$0"|' <gitk >$@+ && \
+	chmod +x $@+ && \
+	mv -f $@+ $@
+
 git$X: git.c common-cmds.h $(BUILTIN_OBJS) $(GITLIBS) GIT-CFLAGS
 	$(QUIET_LINK)$(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \
 		$(ALL_CFLAGS) -o $@ $(filter %.c,$^) \
@@ -700,6 +743,15 @@
 
 $(patsubst %.perl,%,$(SCRIPT_PERL)): perl/perl.mak
 
+$(patsubst %.py,%,$(SCRIPT_PYTHON)) : % : %.py
+	rm -f $@ $@+
+	sed -e '1s|#!.*/python|#!$(PYTHON_PATH_SQ)|' \
+	    -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
+	    -e 's/@@NO_CURL@@/$(NO_CURL)/g' \
+	    $@.py >$@+
+	chmod +x $@+
+	mv $@+ $@
+
 perl/perl.mak: GIT-CFLAGS
 	$(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' $(@F)
 
@@ -853,6 +905,20 @@
 		echo "$$FLAGS" >GIT-CFLAGS; \
             fi
 
+### Detect Tck/Tk interpreter path changes
+ifndef NO_TCLTK
+TRACK_VARS = $(subst ','\'',-DTCLTK_PATH='$(TCLTK_PATH_SQ)')
+
+GIT-GUI-VARS: .FORCE-GIT-GUI-VARS
+	@VARS='$(TRACK_VARS)'; \
+	    if test x"$$VARS" != x"`cat $@ 2>/dev/null`" ; then \
+		echo 1>&2 "    * new Tcl/Tk interpreter location"; \
+		echo "$$VARS" >$@; \
+            fi
+
+.PHONY: .FORCE-GIT-GUI-VARS
+endif
+
 ### Testing rules
 
 # GNU make supports exporting all variables by "export" without parameters.
@@ -893,10 +959,13 @@
 	$(INSTALL) -d -m755 '$(DESTDIR_SQ)$(bindir_SQ)'
 	$(INSTALL) -d -m755 '$(DESTDIR_SQ)$(gitexecdir_SQ)'
 	$(INSTALL) $(ALL_PROGRAMS) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
-	$(INSTALL) git$X gitk '$(DESTDIR_SQ)$(bindir_SQ)'
+	$(INSTALL) git$X '$(DESTDIR_SQ)$(bindir_SQ)'
 	$(MAKE) -C templates DESTDIR='$(DESTDIR_SQ)' install
 	$(MAKE) -C perl prefix='$(prefix_SQ)' install
+ifndef NO_TCLTK
+	$(INSTALL) gitk-wish '$(DESTDIR_SQ)$(bindir_SQ)'/gitk
 	$(MAKE) -C git-gui install
+endif
 	if test 'z$(bindir_SQ)' != 'z$(gitexecdir_SQ)'; \
 	then \
 		ln -f '$(DESTDIR_SQ)$(bindir_SQ)/git$X' \
@@ -975,10 +1044,13 @@
 	rm -f gitweb/gitweb.cgi
 	$(MAKE) -C Documentation/ clean
 	$(MAKE) -C perl clean
-	$(MAKE) -C git-gui clean
 	$(MAKE) -C templates/ clean
 	$(MAKE) -C t/ clean
-	rm -f GIT-VERSION-FILE GIT-CFLAGS
+ifndef NO_TCLTK
+	rm -f gitk-wish
+	$(MAKE) -C git-gui clean
+endif
+	rm -f GIT-VERSION-FILE GIT-CFLAGS GIT-GUI-VARS
 
 .PHONY: all install clean strip
 .PHONY: .FORCE-GIT-VERSION-FILE TAGS tags .FORCE-GIT-CFLAGS
diff --git a/builtin-add.c b/builtin-add.c
index 9fcf514..7d1d5dc 100644
--- a/builtin-add.c
+++ b/builtin-add.c
@@ -87,7 +87,7 @@
 	}
 
 	/* Read the directory and prune it */
-	read_directory(dir, path, base, baselen);
+	read_directory(dir, path, base, baselen, pathspec);
 	if (pathspec)
 		prune_directory(dir, pathspec, baselen);
 }
@@ -205,7 +205,7 @@
 	}
 
 	for (i = 0; i < dir.nr; i++)
-		add_file_to_index(dir.entries[i]->name, verbose);
+		add_file_to_cache(dir.entries[i]->name, verbose);
 
 	if (active_cache_changed) {
 		if (write_cache(newfd, active_cache, active_nr) ||
diff --git a/builtin-apply.c b/builtin-apply.c
index a5d6126..4b8311b 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -30,7 +30,7 @@
 static int p_value = 1;
 static int p_value_known;
 static int check_index;
-static int write_index;
+static int update_index;
 static int cached;
 static int diffstat;
 static int numstat;
@@ -2308,7 +2308,7 @@
 
 static void remove_file(struct patch *patch, int rmdir_empty)
 {
-	if (write_index) {
+	if (update_index) {
 		if (remove_file_from_cache(patch->old_name) < 0)
 			die("unable to remove %s from index", patch->old_name);
 		cache_tree_invalidate_path(active_cache_tree, patch->old_name);
@@ -2335,7 +2335,7 @@
 	int namelen = strlen(path);
 	unsigned ce_size = cache_entry_size(namelen);
 
-	if (!write_index)
+	if (!update_index)
 		return;
 
 	ce = xcalloc(1, ce_size);
@@ -2662,8 +2662,8 @@
 	if (whitespace_error && (new_whitespace == error_on_whitespace))
 		apply = 0;
 
-	write_index = check_index && apply;
-	if (write_index && newfd < 0)
+	update_index = check_index && apply;
+	if (update_index && newfd < 0)
 		newfd = hold_lock_file_for_update(&lock_file,
 						  get_index_file(), 1);
 	if (check_index) {
@@ -2870,7 +2870,7 @@
 				whitespace_error == 1 ? "s" : "");
 	}
 
-	if (write_index) {
+	if (update_index) {
 		if (write_cache(newfd, active_cache, active_nr) ||
 		    close(newfd) || commit_lock_file(&lock_file))
 			die("Unable to write new index file");
diff --git a/builtin-fsck.c b/builtin-fsck.c
index 21f1f9e..4d8b66c 100644
--- a/builtin-fsck.c
+++ b/builtin-fsck.c
@@ -14,6 +14,7 @@
 static int show_root;
 static int show_tags;
 static int show_unreachable;
+static int include_reflogs = 1;
 static int check_full;
 static int check_strict;
 static int keep_cache_objects;
@@ -348,7 +349,7 @@
 	return 0;
 }
 
-static int fsck_sha1(unsigned char *sha1)
+static int fsck_sha1(const unsigned char *sha1)
 {
 	struct object *obj = parse_object(sha1);
 	if (!obj) {
@@ -517,7 +518,8 @@
 static void get_default_heads(void)
 {
 	for_each_ref(fsck_handle_ref, NULL);
-	for_each_reflog(fsck_handle_reflog, NULL);
+	if (include_reflogs)
+		for_each_reflog(fsck_handle_reflog, NULL);
 
 	/*
 	 * Not having any default heads isn't really fatal, but
@@ -616,6 +618,10 @@
 			keep_cache_objects = 1;
 			continue;
 		}
+		if (!strcmp(arg, "--no-reflogs")) {
+			include_reflogs = 0;
+			continue;
+		}
 		if (!strcmp(arg, "--full")) {
 			check_full = 1;
 			continue;
@@ -648,11 +654,8 @@
 
 		for (p = packed_git; p; p = p->next) {
 			uint32_t i, num = num_packed_objects(p);
-			for (i = 0; i < num; i++) {
-				unsigned char sha1[20];
-				nth_packed_object_sha1(p, i, sha1);
-				fsck_sha1(sha1);
-			}
+			for (i = 0; i < num; i++)
+				fsck_sha1(nth_packed_object_sha1(p, i));
 		}
 	}
 
diff --git a/builtin-ls-files.c b/builtin-ls-files.c
index 4e1d5af..74a6aca 100644
--- a/builtin-ls-files.c
+++ b/builtin-ls-files.c
@@ -216,7 +216,7 @@
 
 		if (baselen)
 			path = base = prefix;
-		read_directory(dir, path, base, baselen);
+		read_directory(dir, path, base, baselen, pathspec);
 		if (show_others)
 			show_other_files(dir);
 		if (show_killed)
diff --git a/builtin-mv.c b/builtin-mv.c
index 737af35..c4ab478 100644
--- a/builtin-mv.c
+++ b/builtin-mv.c
@@ -273,7 +273,7 @@
 
 		for (i = 0; i < added.nr; i++) {
 			const char *path = added.items[i].path;
-			add_file_to_index(path, verbose);
+			add_file_to_cache(path, verbose);
 		}
 
 		for (i = 0; i < deleted.nr; i++) {
diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
index b5f9648..45ac3e4 100644
--- a/builtin-pack-objects.c
+++ b/builtin-pack-objects.c
@@ -222,7 +222,7 @@
 						    off_t ofs)
 {
 	struct revindex_entry *entry = find_packed_object(p, ofs);
-	return ((unsigned char *)p->index_data) + 4 * 256 + 24 * entry->nr + 4;
+	return nth_packed_object_sha1(p, entry->nr);
 }
 
 static void *delta_against(void *buf, unsigned long size, struct object_entry *entry)
diff --git a/builtin-rev-list.c b/builtin-rev-list.c
index b86e7ca..09774f9 100644
--- a/builtin-rev-list.c
+++ b/builtin-rev-list.c
@@ -37,7 +37,8 @@
 "    --abbrev-commit\n"
 "    --left-right\n"
 "  special purpose:\n"
-"    --bisect"
+"    --bisect\n"
+"    --bisect-vars"
 ;
 
 static struct rev_info revs;
@@ -169,38 +170,273 @@
 	}
 }
 
-static struct commit_list *find_bisection(struct commit_list *list)
-{
-	int nr, closest;
-	struct commit_list *p, *best;
+#define DEBUG_BISECT 0
 
-	nr = 0;
-	p = list;
-	while (p) {
-		if (!revs.prune_fn || (p->item->object.flags & TREECHANGE))
-			nr++;
-		p = p->next;
+static inline int weight(struct commit_list *elem)
+{
+	return *((int*)(elem->item->util));
+}
+
+static inline void weight_set(struct commit_list *elem, int weight)
+{
+	*((int*)(elem->item->util)) = weight;
+}
+
+static int count_interesting_parents(struct commit *commit)
+{
+	struct commit_list *p;
+	int count;
+
+	for (count = 0, p = commit->parents; p; p = p->next) {
+		if (p->item->object.flags & UNINTERESTING)
+			continue;
+		count++;
 	}
-	closest = -1;
-	best = list;
+	return count;
+}
+
+static inline int halfway(struct commit_list *p, int distance, int nr)
+{
+	/*
+	 * Don't short-cut something we are not going to return!
+	 */
+	if (revs.prune_fn && !(p->item->object.flags & TREECHANGE))
+		return 0;
+	if (DEBUG_BISECT)
+		return 0;
+	/*
+	 * 2 and 3 are halfway of 5.
+	 * 3 is halfway of 6 but 2 and 4 are not.
+	 */
+	distance *= 2;
+	switch (distance - nr) {
+	case -1: case 0: case 1:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+#if !DEBUG_BISECT
+#define show_list(a,b,c,d) do { ; } while (0)
+#else
+static void show_list(const char *debug, int counted, int nr,
+		      struct commit_list *list)
+{
+	struct commit_list *p;
+
+	fprintf(stderr, "%s (%d/%d)\n", debug, counted, nr);
 
 	for (p = list; p; p = p->next) {
-		int distance;
+		struct commit_list *pp;
+		struct commit *commit = p->item;
+		unsigned flags = commit->object.flags;
+		enum object_type type;
+		unsigned long size;
+		char *buf = read_sha1_file(commit->object.sha1, &type, &size);
+		char *ep, *sp;
 
-		if (revs.prune_fn && !(p->item->object.flags & TREECHANGE))
+		fprintf(stderr, "%c%c%c ",
+			(flags & TREECHANGE) ? 'T' : ' ',
+			(flags & UNINTERESTING) ? 'U' : ' ',
+			(flags & COUNTED) ? 'C' : ' ');
+		if (commit->util)
+			fprintf(stderr, "%3d", weight(p));
+		else
+			fprintf(stderr, "---");
+		fprintf(stderr, " %.*s", 8, sha1_to_hex(commit->object.sha1));
+		for (pp = commit->parents; pp; pp = pp->next)
+			fprintf(stderr, " %.*s", 8,
+				sha1_to_hex(pp->item->object.sha1));
+
+		sp = strstr(buf, "\n\n");
+		if (sp) {
+			sp += 2;
+			for (ep = sp; *ep && *ep != '\n'; ep++)
+				;
+			fprintf(stderr, " %.*s", (int)(ep - sp), sp);
+		}
+		fprintf(stderr, "\n");
+	}
+}
+#endif /* DEBUG_BISECT */
+
+/*
+ * zero or positive weight is the number of interesting commits it can
+ * reach, including itself.  Especially, weight = 0 means it does not
+ * reach any tree-changing commits (e.g. just above uninteresting one
+ * but traversal is with pathspec).
+ *
+ * weight = -1 means it has one parent and its distance is yet to
+ * be computed.
+ *
+ * weight = -2 means it has more than one parent and its distance is
+ * unknown.  After running count_distance() first, they will get zero
+ * or positive distance.
+ */
+
+static struct commit_list *find_bisection(struct commit_list *list,
+					  int *reaches, int *all)
+{
+	int n, nr, on_list, counted, distance;
+	struct commit_list *p, *best, *next, *last;
+	int *weights;
+
+	show_list("bisection 2 entry", 0, 0, list);
+
+	/*
+	 * Count the number of total and tree-changing items on the
+	 * list, while reversing the list.
+	 */
+	for (nr = on_list = 0, last = NULL, p = list;
+	     p;
+	     p = next) {
+		unsigned flags = p->item->object.flags;
+
+		next = p->next;
+		if (flags & UNINTERESTING)
 			continue;
+		p->next = last;
+		last = p;
+		if (!revs.prune_fn || (flags & TREECHANGE))
+			nr++;
+		on_list++;
+	}
+	list = last;
+	show_list("bisection 2 sorted", 0, nr, list);
 
+	*all = nr;
+	weights = xcalloc(on_list, sizeof(int*));
+	counted = 0;
+
+	for (n = 0, p = list; p; p = p->next) {
+		struct commit *commit = p->item;
+		unsigned flags = commit->object.flags;
+
+		p->item->util = &weights[n++];
+		switch (count_interesting_parents(commit)) {
+		case 0:
+			if (!revs.prune_fn || (flags & TREECHANGE)) {
+				weight_set(p, 1);
+				counted++;
+				show_list("bisection 2 count one",
+					  counted, nr, list);
+			}
+			/*
+			 * otherwise, it is known not to reach any
+			 * tree-changing commit and gets weight 0.
+			 */
+			break;
+		case 1:
+			weight_set(p, -1);
+			break;
+		default:
+			weight_set(p, -2);
+			break;
+		}
+	}
+
+	show_list("bisection 2 initialize", counted, nr, list);
+
+	/*
+	 * If you have only one parent in the resulting set
+	 * then you can reach one commit more than that parent
+	 * can reach.  So we do not have to run the expensive
+	 * count_distance() for single strand of pearls.
+	 *
+	 * However, if you have more than one parents, you cannot
+	 * just add their distance and one for yourself, since
+	 * they usually reach the same ancestor and you would
+	 * end up counting them twice that way.
+	 *
+	 * So we will first count distance of merges the usual
+	 * way, and then fill the blanks using cheaper algorithm.
+	 */
+	for (p = list; p; p = p->next) {
+		if (p->item->object.flags & UNINTERESTING)
+			continue;
+		n = weight(p);
+		if (n != -2)
+			continue;
 		distance = count_distance(p);
 		clear_distance(list);
+		weight_set(p, distance);
+
+		/* Does it happen to be at exactly half-way? */
+		if (halfway(p, distance, nr)) {
+			p->next = NULL;
+			*reaches = distance;
+			free(weights);
+			return p;
+		}
+		counted++;
+	}
+
+	show_list("bisection 2 count_distance", counted, nr, list);
+
+	while (counted < nr) {
+		for (p = list; p; p = p->next) {
+			struct commit_list *q;
+			unsigned flags = p->item->object.flags;
+
+			if (0 <= weight(p))
+				continue;
+			for (q = p->item->parents; q; q = q->next) {
+				if (q->item->object.flags & UNINTERESTING)
+					continue;
+				if (0 <= weight(q))
+					break;
+			}
+			if (!q)
+				continue;
+
+			/*
+			 * weight for p is unknown but q is known.
+			 * add one for p itself if p is to be counted,
+			 * otherwise inherit it from q directly.
+			 */
+			if (!revs.prune_fn || (flags & TREECHANGE)) {
+				weight_set(p, weight(q)+1);
+				counted++;
+				show_list("bisection 2 count one",
+					  counted, nr, list);
+			}
+			else
+				weight_set(p, weight(q));
+
+			/* Does it happen to be at exactly half-way? */
+			distance = weight(p);
+			if (halfway(p, distance, nr)) {
+				p->next = NULL;
+				*reaches = distance;
+				free(weights);
+				return p;
+			}
+		}
+	}
+
+	show_list("bisection 2 counted all", counted, nr, list);
+
+	/* Then find the best one */
+	counted = -1;
+	best = list;
+	for (p = list; p; p = p->next) {
+		unsigned flags = p->item->object.flags;
+
+		if (revs.prune_fn && !(flags & TREECHANGE))
+			continue;
+		distance = weight(p);
 		if (nr - distance < distance)
 			distance = nr - distance;
-		if (distance > closest) {
+		if (distance > counted) {
 			best = p;
-			closest = distance;
+			counted = distance;
+			*reaches = weight(p);
 		}
 	}
 	if (best)
 		best->next = NULL;
+	free(weights);
 	return best;
 }
 
@@ -226,6 +462,7 @@
 	struct commit_list *list;
 	int i;
 	int read_from_stdin = 0;
+	int bisect_show_vars = 0;
 
 	git_config(git_default_config);
 	init_revisions(&revs, prefix);
@@ -248,6 +485,11 @@
 			bisect_list = 1;
 			continue;
 		}
+		if (!strcmp(arg, "--bisect-vars")) {
+			bisect_list = 1;
+			bisect_show_vars = 1;
+			continue;
+		}
 		if (!strcmp(arg, "--stdin")) {
 			if (read_from_stdin++)
 				die("--stdin given twice?");
@@ -286,8 +528,39 @@
 	if (revs.tree_objects)
 		mark_edges_uninteresting(revs.commits, &revs, show_edge);
 
-	if (bisect_list)
-		revs.commits = find_bisection(revs.commits);
+	if (bisect_list) {
+		int reaches = reaches, all = all;
+
+		revs.commits = find_bisection(revs.commits, &reaches, &all);
+		if (bisect_show_vars) {
+			int cnt;
+			if (!revs.commits)
+				return 1;
+			/*
+			 * revs.commits can reach "reaches" commits among
+			 * "all" commits.  If it is good, then there are
+			 * (all-reaches) commits left to be bisected.
+			 * On the other hand, if it is bad, then the set
+			 * to bisect is "reaches".
+			 * A bisect set of size N has (N-1) commits further
+			 * to test, as we already know one bad one.
+			 */
+			cnt = all-reaches;
+			if (cnt < reaches)
+				cnt = reaches;
+			printf("bisect_rev=%s\n"
+			       "bisect_nr=%d\n"
+			       "bisect_good=%d\n"
+			       "bisect_bad=%d\n"
+			       "bisect_all=%d\n",
+			       sha1_to_hex(revs.commits->item->object.sha1),
+			       cnt - 1,
+			       all - reaches - 1,
+			       reaches - 1,
+			       all);
+			return 0;
+		}
+	}
 
 	traverse_commit_list(&revs, show_commit, show_object);
 
diff --git a/builtin-update-index.c b/builtin-update-index.c
index 71cef63..d1e5cf7 100644
--- a/builtin-update-index.c
+++ b/builtin-update-index.c
@@ -60,7 +60,7 @@
 	return -1;
 }
 
-static int add_file_to_cache(const char *path)
+static int process_file(const char *path)
 {
 	int size, namelen, option, status;
 	struct cache_entry *ce;
@@ -210,7 +210,7 @@
 		report("remove '%s'", path);
 		goto free_return;
 	}
-	if (add_file_to_cache(p))
+	if (process_file(p))
 		die("Unable to process file %s", path);
 	report("add '%s'", path);
  free_return:
diff --git a/cache.h b/cache.h
index 384b260..ece0c04 100644
--- a/cache.h
+++ b/cache.h
@@ -128,7 +128,6 @@
 extern struct cache_entry **active_cache;
 extern unsigned int active_nr, active_alloc, active_cache_changed;
 extern struct cache_tree *active_cache_tree;
-extern int cache_errno;
 
 enum object_type {
 	OBJ_BAD = -1,
@@ -188,7 +187,7 @@
 extern struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really);
 extern int remove_cache_entry_at(int pos);
 extern int remove_file_from_cache(const char *path);
-extern int add_file_to_index(const char *path, int verbose);
+extern int add_file_to_cache(const char *path, int verbose);
 extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);
 extern int ce_match_stat(struct cache_entry *ce, struct stat *st, int);
 extern int ce_modified(struct cache_entry *ce, struct stat *st, int);
@@ -428,7 +427,7 @@
 extern void unuse_pack(struct pack_window **);
 extern struct packed_git *add_packed_git(const char *, int, int);
 extern uint32_t num_packed_objects(const struct packed_git *p);
-extern int nth_packed_object_sha1(const struct packed_git *, uint32_t, unsigned char*);
+extern const unsigned char *nth_packed_object_sha1(const struct packed_git *, uint32_t);
 extern off_t find_pack_entry_one(const unsigned char *, struct packed_git *);
 extern void *unpack_entry(struct packed_git *, off_t, enum object_type *, unsigned long *);
 extern unsigned long unpack_object_header_gently(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep);
diff --git a/config.mak.in b/config.mak.in
index 9a57840..eb9d7a5 100644
--- a/config.mak.in
+++ b/config.mak.in
@@ -6,6 +6,7 @@
 AR = @AR@
 TAR = @TAR@
 #INSTALL = @INSTALL@		# needs install-sh or install.sh in sources
+TCLTK_PATH = @TCLTK_PATH@
 
 prefix = @prefix@
 exec_prefix = @exec_prefix@
diff --git a/configure.ac b/configure.ac
index 3a8e778..50d2b85 100644
--- a/configure.ac
+++ b/configure.ac
@@ -75,6 +75,14 @@
 # Define PERL_PATH to provide path to Perl.
 GIT_ARG_SET_PATH(perl)
 #
+# Declare the with-tcltk/without-tcltk options.
+AC_ARG_WITH(tcltk,
+AS_HELP_STRING([--with-tcltk],[use Tcl/Tk GUI (default is YES)])
+AS_HELP_STRING([],[ARG is the full path to the Tcl/Tk interpreter.])
+AS_HELP_STRING([],[Bare --with-tcltk will make the GUI part only if])
+AS_HELP_STRING([],[Tcl/Tk interpreter will be found in a system.]),\
+GIT_PARSE_WITH(tcltk))
+#
 
 
 ## Checks for programs.
@@ -84,6 +92,22 @@
 #AC_PROG_INSTALL		# needs install-sh or install.sh in sources
 AC_CHECK_TOOL(AR, ar, :)
 AC_CHECK_PROGS(TAR, [gtar tar])
+# TCLTK_PATH will be set to some value if we want Tcl/Tk
+# or will be empty otherwise.
+if test -z "$NO_TCLTK"; then
+  if test "$with_tcltk" = ""; then
+  # No Tcl/Tk switches given. Do not check for Tcl/Tk, use bare 'wish'.
+    TCLTK_PATH=wish
+    AC_SUBST(TCLTK_PATH)
+  elif test "$with_tcltk" = "yes"; then
+  # Tcl/Tk check requested.
+    AC_CHECK_PROGS(TCLTK_PATH, [wish], )
+  else
+    AC_MSG_RESULT([Using Tcl/Tk interpreter $with_tcltk])
+    TCLTK_PATH="$with_tcltk"
+    AC_SUBST(TCLTK_PATH)
+  fi
+fi
 
 ## Checks for libraries.
 AC_MSG_NOTICE([CHECKS for libraries])
diff --git a/contrib/emacs/git-blame.el b/contrib/emacs/git-blame.el
index 64ad50b..bb671d5 100644
--- a/contrib/emacs/git-blame.el
+++ b/contrib/emacs/git-blame.el
@@ -8,8 +8,8 @@
 ;; License:    GPL
 ;; Keywords:   git, version control, release management
 ;;
-;; Compatibility: Emacs21
-
+;; Compatibility: Emacs21, Emacs22 and EmacsCVS
+;;                Git 1.5 and up
 
 ;; This file is *NOT* part of GNU Emacs.
 ;; This file is distributed under the same terms as GNU Emacs.
@@ -61,8 +61,9 @@
 
 ;;; Compatibility:
 ;;
-;; It requires GNU Emacs 21.  If you'are using Emacs 20, try
-;; changing this:
+;; It requires GNU Emacs 21 or later and Git 1.5.0 and up
+;;
+;; If you'are using Emacs 20, try changing this:
 ;;
 ;;            (overlay-put ovl 'face (list :background
 ;;                                         (cdr (assq 'color (cddddr info)))))
@@ -77,30 +78,51 @@
 ;;
 ;;; Code:
 
-(require 'cl)			      ; to use `push', `pop'
+(eval-when-compile (require 'cl))			      ; to use `push', `pop'
 
-(defun color-scale (l)
-  (let* ((colors ())
-         r g b)
-    (setq r l)
-    (while r
-      (setq g l)
-      (while g
-        (setq b l)
-        (while b
-          (push (concat "#" (car r) (car g) (car b)) colors)
-          (pop b))
-        (pop g))
-      (pop r))
-    colors))
+
+(defun git-blame-color-scale (&rest elements)
+  "Given a list, returns a list of triples formed with each
+elements of the list.
+
+a b => bbb bba bab baa abb aba aaa aab"
+  (let (result)
+    (dolist (a elements)
+      (dolist (b elements)
+        (dolist (c elements)
+          (setq result (cons (format "#%s%s%s" a b c) result)))))
+    result))
+
+;; (git-blame-color-scale "0c" "04" "24" "1c" "2c" "34" "14" "3c") =>
+;; ("#3c3c3c" "#3c3c14" "#3c3c34" "#3c3c2c" "#3c3c1c" "#3c3c24"
+;; "#3c3c04" "#3c3c0c" "#3c143c" "#3c1414" "#3c1434" "#3c142c" ...)
+
+(defmacro git-blame-random-pop (l)
+  "Select a random element from L and returns it. Also remove
+selected element from l."
+  ;; only works on lists with unique elements
+  `(let ((e (elt ,l (random (length ,l)))))
+     (setq ,l (remove e ,l))
+     e))
 
 (defvar git-blame-dark-colors
-  (color-scale '("0c" "04" "24" "1c" "2c" "34" "14" "3c")))
+  (git-blame-color-scale "0c" "04" "24" "1c" "2c" "34" "14" "3c")
+  "*List of colors (format #RGB) to use in a dark environment.
+
+To check out the list, evaluate (list-colors-display git-blame-dark-colors).")
 
 (defvar git-blame-light-colors
-  (color-scale '("c4" "d4" "cc" "dc" "f4" "e4" "fc" "ec")))
+  (git-blame-color-scale "c4" "d4" "cc" "dc" "f4" "e4" "fc" "ec")
+  "*List of colors (format #RGB) to use in a light environment.
 
-(defvar git-blame-ancient-color "dark green")
+To check out the list, evaluate (list-colors-display git-blame-light-colors).")
+
+(defvar git-blame-colors '()
+  "Colors used by git-blame. The list is built once when activating git-blame
+minor mode.")
+
+(defvar git-blame-ancient-color "dark green"
+  "*Color to be used for ancient commit.")
 
 (defvar git-blame-autoupdate t
   "*Automatically update the blame display while editing")
@@ -125,41 +147,64 @@
   "A queue of update requests")
 (make-variable-buffer-local 'git-blame-update-queue)
 
+;; FIXME: docstrings
+(defvar git-blame-file nil)
+(defvar git-blame-current nil)
+
 (defvar git-blame-mode nil)
 (make-variable-buffer-local 'git-blame-mode)
-(unless (assq 'git-blame-mode minor-mode-alist)
-  (setq minor-mode-alist
-	(cons (list 'git-blame-mode " blame")
-	      minor-mode-alist)))
+
+(defvar git-blame-mode-line-string " blame"
+  "String to display on the mode line when git-blame is active.")
+
+(or (assq 'git-blame-mode minor-mode-alist)
+    (setq minor-mode-alist
+	  (cons '(git-blame-mode git-blame-mode-line-string) minor-mode-alist)))
 
 ;;;###autoload
 (defun git-blame-mode (&optional arg)
-  "Minor mode for displaying Git blame"
+  "Toggle minor mode for displaying Git blame
+
+With prefix ARG, turn the mode on if ARG is positive."
   (interactive "P")
-  (if arg
-      (setq git-blame-mode (eq arg 1))
-    (setq git-blame-mode (not git-blame-mode)))
+  (cond
+   ((null arg)
+    (if git-blame-mode (git-blame-mode-off) (git-blame-mode-on)))
+   ((> (prefix-numeric-value arg) 0) (git-blame-mode-on))
+   (t (git-blame-mode-off))))
+
+(defun git-blame-mode-on ()
+  "Turn on git-blame mode.
+
+See also function `git-blame-mode'."
   (make-local-variable 'git-blame-colors)
   (if git-blame-autoupdate
       (add-hook 'after-change-functions 'git-blame-after-change nil t)
     (remove-hook 'after-change-functions 'git-blame-after-change t))
   (git-blame-cleanup)
-  (if git-blame-mode
-      (progn
-        (let ((bgmode (cdr (assoc 'background-mode (frame-parameters)))))
-          (if (eq bgmode 'dark)
-              (setq git-blame-colors git-blame-dark-colors)
-            (setq git-blame-colors git-blame-light-colors)))
-        (setq git-blame-cache (make-hash-table :test 'equal))
-        (git-blame-run))
-    (cancel-timer git-blame-idle-timer)))
+  (let ((bgmode (cdr (assoc 'background-mode (frame-parameters)))))
+    (if (eq bgmode 'dark)
+	(setq git-blame-colors git-blame-dark-colors)
+      (setq git-blame-colors git-blame-light-colors)))
+  (setq git-blame-cache (make-hash-table :test 'equal))
+  (setq git-blame-mode t)
+  (git-blame-run))
+
+(defun git-blame-mode-off ()
+  "Turn off git-blame mode.
+
+See also function `git-blame-mode'."
+  (git-blame-cleanup)
+  (if git-blame-idle-timer (cancel-timer git-blame-idle-timer))
+  (setq git-blame-mode nil))
 
 ;;;###autoload
 (defun git-reblame ()
   "Recalculate all blame information in the current buffer"
-  (unless git-blame-mode
-    (error "git-blame is not active"))
   (interactive)
+  (unless git-blame-mode
+    (error "Git-blame is not active"))
+
   (git-blame-cleanup)
   (git-blame-run))
 
@@ -275,7 +320,6 @@
         (t
          nil)))
 
-
 (defun git-blame-new-commit (hash src-line res-line num-lines)
   (save-excursion
     (set-buffer git-blame-file)
@@ -283,9 +327,11 @@
           (inhibit-point-motion-hooks t)
           (inhibit-modification-hooks t))
       (when (not info)
-        (let ((color (pop git-blame-colors)))
-          (unless color
-            (setq color git-blame-ancient-color))
+	;; Assign a random color to each new commit info
+	;; Take care not to select the same color multiple times
+	(let ((color (if git-blame-colors
+			 (git-blame-random-pop git-blame-colors)
+		       git-blame-ancient-color)))
           (setq info (list hash src-line res-line num-lines
                            (git-describe-commit hash)
                            (cons 'color color))))
diff --git a/diff.c b/diff.c
index d8f9242..fbb79d7 100644
--- a/diff.c
+++ b/diff.c
@@ -811,7 +811,12 @@
 
 		if (data->files[i]->is_binary) {
 			show_name(prefix, name, len, reset, set);
-			printf("  Bin\n");
+			printf("  Bin ");
+			printf("%s%d%s", del_c, deleted, reset);
+			printf(" -> ");
+			printf("%s%d%s", add_c, added, reset);
+			printf(" bytes");
+			printf("\n");
 			goto free_diffstat_file;
 		}
 		else if (data->files[i]->is_unmerged) {
@@ -1185,9 +1190,11 @@
 	if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
 		die("unable to read files to diff");
 
-	if (mmfile_is_binary(&mf1) || mmfile_is_binary(&mf2))
+	if (mmfile_is_binary(&mf1) || mmfile_is_binary(&mf2)) {
 		data->is_binary = 1;
-	else {
+		data->added = mf2.size;
+		data->deleted = mf1.size;
+	} else {
 		/* Crazy xdl interfaces.. */
 		xpparam_t xpp;
 		xdemitconf_t xecfg;
diff --git a/dir.c b/dir.c
index b48e19d..7426fde 100644
--- a/dir.c
+++ b/dir.c
@@ -8,6 +8,11 @@
 #include "cache.h"
 #include "dir.h"
 
+struct path_simplify {
+	int len;
+	const char *path;
+};
+
 int common_prefix(const char **pathspec)
 {
 	const char *path, *slash, *next;
@@ -293,6 +298,31 @@
 }
 
 /*
+ * This is an inexact early pruning of any recursive directory
+ * reading - if the path cannot possibly be in the pathspec,
+ * return true, and we'll skip it early.
+ */
+static int simplify_away(const char *path, int pathlen, const struct path_simplify *simplify)
+{
+	if (simplify) {
+		for (;;) {
+			const char *match = simplify->path;
+			int len = simplify->len;
+
+			if (!match)
+				break;
+			if (len > pathlen)
+				len = pathlen;
+			if (!memcmp(path, match, len))
+				return 0;
+			simplify++;
+		}
+		return 1;
+	}
+	return 0;
+}
+
+/*
  * Read a directory tree. We currently ignore anything but
  * directories, regular files and symlinks. That's because git
  * doesn't handle them at all yet. Maybe that will change some
@@ -301,7 +331,7 @@
  * Also, we ignore the name ".git" (even if it is not a directory).
  * That likely will not change.
  */
-static int read_directory_recursive(struct dir_struct *dir, const char *path, const char *base, int baselen, int check_only)
+static int read_directory_recursive(struct dir_struct *dir, const char *path, const char *base, int baselen, int check_only, const struct path_simplify *simplify)
 {
 	DIR *fdir = opendir(path);
 	int contents = 0;
@@ -324,6 +354,8 @@
 				continue;
 			len = strlen(de->d_name);
 			memcpy(fullname + baselen, de->d_name, len+1);
+			if (simplify_away(fullname, baselen + len, simplify))
+				continue;
 			if (excluded(dir, fullname) != dir->show_ignored) {
 				if (!dir->show_ignored || DTYPE(de) != DT_DIR) {
 					continue;
@@ -350,13 +382,13 @@
 					if (dir->hide_empty_directories &&
 					    !read_directory_recursive(dir,
 						    fullname, fullname,
-						    baselen + len, 1))
+						    baselen + len, 1, simplify))
 						continue;
 					break;
 				}
 
 				contents += read_directory_recursive(dir,
-					fullname, fullname, baselen + len, 0);
+					fullname, fullname, baselen + len, 0, simplify);
 				continue;
 			case DT_REG:
 			case DT_LNK:
@@ -386,8 +418,61 @@
 				  e2->name, e2->len);
 }
 
-int read_directory(struct dir_struct *dir, const char *path, const char *base, int baselen)
+/*
+ * Return the length of the "simple" part of a path match limiter.
+ */
+static int simple_length(const char *match)
 {
+	const char special[256] = {
+		[0] = 1, ['?'] = 1,
+		['\\'] = 1, ['*'] = 1,
+		['['] = 1
+	};
+	int len = -1;
+
+	for (;;) {
+		unsigned char c = *match++;
+		len++;
+		if (special[c])
+			return len;
+	}
+}
+
+static struct path_simplify *create_simplify(const char **pathspec)
+{
+	int nr, alloc = 0;
+	struct path_simplify *simplify = NULL;
+
+	if (!pathspec)
+		return NULL;
+
+	for (nr = 0 ; ; nr++) {
+		const char *match;
+		if (nr >= alloc) {
+			alloc = alloc_nr(alloc);
+			simplify = xrealloc(simplify, alloc * sizeof(*simplify));
+		}
+		match = *pathspec++;
+		if (!match)
+			break;
+		simplify[nr].path = match;
+		simplify[nr].len = simple_length(match);
+	}
+	simplify[nr].path = NULL;
+	simplify[nr].len = 0;
+	return simplify;
+}
+
+static void free_simplify(struct path_simplify *simplify)
+{
+	if (simplify)
+		free(simplify);
+}
+
+int read_directory(struct dir_struct *dir, const char *path, const char *base, int baselen, const char **pathspec)
+{
+	struct path_simplify *simplify = create_simplify(pathspec);
+
 	/*
 	 * Make sure to do the per-directory exclude for all the
 	 * directories leading up to our base.
@@ -414,7 +499,8 @@
 		}
 	}
 
-	read_directory_recursive(dir, path, base, baselen, 0);
+	read_directory_recursive(dir, path, base, baselen, 0, simplify);
+	free_simplify(simplify);
 	qsort(dir->entries, dir->nr, sizeof(struct dir_entry *), cmp_name);
 	return dir->nr;
 }
diff --git a/dir.h b/dir.h
index 7233d65..33c31f2 100644
--- a/dir.h
+++ b/dir.h
@@ -48,7 +48,7 @@
 #define MATCHED_EXACTLY 3
 extern int match_pathspec(const char **pathspec, const char *name, int namelen, int prefix, char *seen);
 
-extern int read_directory(struct dir_struct *, const char *path, const char *base, int baselen);
+extern int read_directory(struct dir_struct *, const char *path, const char *base, int baselen, const char **pathspec);
 extern int push_exclude_per_directory(struct dir_struct *, const char *, int);
 extern void pop_exclude_per_directory(struct dir_struct *, int);
 
diff --git a/git-lost-found.sh b/git-lost-found.sh
index 9360804..58570df 100755
--- a/git-lost-found.sh
+++ b/git-lost-found.sh
@@ -12,7 +12,7 @@
 laf="$GIT_DIR/lost-found"
 rm -fr "$laf" && mkdir -p "$laf/commit" "$laf/other" || exit
 
-git fsck --full |
+git fsck --full --no-reflogs |
 while read dangling type sha1
 do
 	case "$dangling" in
diff --git a/git-svn.perl b/git-svn.perl
index d307d43..6216cad 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -33,7 +33,7 @@
 use IO::File qw//;
 use File::Basename qw/dirname basename/;
 use File::Path qw/mkpath/;
-use Getopt::Long qw/:config gnu_getopt no_ignore_case auto_abbrev pass_through/;
+use Getopt::Long qw/:config gnu_getopt no_ignore_case auto_abbrev/;
 use IPC::Open3;
 use Git;
 
@@ -168,6 +168,7 @@
 my %opts = %{$cmd{$cmd}->[2]} if (defined $cmd);
 
 read_repo_config(\%opts);
+Getopt::Long::Configure('pass_through') if $cmd eq 'log';
 my $rv = GetOptions(%opts, 'help|H|h' => \$_help, 'version|V' => \$_version,
                     'minimize-connections' => \$Git::SVN::Migration::_minimize,
                     'id|i=s' => \$Git::SVN::default_ref_id,
@@ -229,6 +230,8 @@
 		next if /^multi-/; # don't show deprecated commands
 		print $fd '  ',pack('A17',$_),$cmd{$_}->[1],"\n";
 		foreach (keys %{$cmd{$_}->[2]}) {
+			# mixed-case options are for .git/config only
+			next if /[A-Z]/ && /^[a-z]+$/i;
 			# prints out arguments as they should be passed:
 			my $x = s#[:=]s$## ? '<arg>' : s#[:=]i$## ? '<num>' : '';
 			print $fd ' ' x 21, join(', ', map { length $_ > 1 ?
diff --git a/git.spec.in b/git.spec.in
index 46aee88..f0746ed 100644
--- a/git.spec.in
+++ b/git.spec.in
@@ -1,4 +1,7 @@
 # Pass --without docs to rpmbuild if you don't want the documentation
+
+%define python_path /usr/bin/python
+
 Name: 		git
 Version: 	@@VERSION@@
 Release: 	1%{?dist}
@@ -9,7 +12,7 @@
 Source: 	http://kernel.org/pub/software/scm/git/%{name}-%{version}.tar.gz
 BuildRequires:	zlib-devel >= 1.2, openssl-devel, curl-devel, expat-devel  %{!?_without_docs:, xmlto, asciidoc > 6.0.3}
 BuildRoot:	%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
-Requires:	git-core, git-svn, git-cvs, git-arch, git-email, gitk, git-gui, perl-Git
+Requires:	git-core, git-svn, git-cvs, git-arch, git-email, gitk, git-gui, git-p4, perl-Git
 
 %description
 Git is a fast, scalable, distributed revision control system with an
@@ -50,6 +53,13 @@
 %description arch
 Git tools for importing Arch repositories.
 
+%package p4
+Summary:        Git tools for importing Perforce repositories
+Group:          Development/Tools
+Requires:       git-core = %{version}-%{release}, python
+%description p4
+Git tools for importing Perforce repositories.
+
 %package email
 Summary:        Git tools for sending email
 Group:          Development/Tools
@@ -85,23 +95,23 @@
 %setup -q
 
 %build
-make %{_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" WITH_OWN_SUBPROCESS_PY=YesPlease \
-     prefix=%{_prefix} all %{!?_without_docs: doc}
+make %{_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" WITH_P4IMPORT=YesPlease \
+     prefix=%{_prefix} PYTHON_PATH=%{python_path} all %{!?_without_docs: doc}
 
 %install
 rm -rf $RPM_BUILD_ROOT
 make %{_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" DESTDIR=$RPM_BUILD_ROOT \
-     WITH_OWN_SUBPROCESS_PY=YesPlease \
-     prefix=%{_prefix} mandir=%{_mandir} INSTALLDIRS=vendor \
-     install %{!?_without_docs: install-doc}
+     WITH_P4IMPORT=YesPlease prefix=%{_prefix} mandir=%{_mandir} \
+     PYTHON_PATH=%{python_path} \
+     INSTALLDIRS=vendor install %{!?_without_docs: install-doc}
 find $RPM_BUILD_ROOT -type f -name .packlist -exec rm -f {} ';'
 find $RPM_BUILD_ROOT -type f -name '*.bs' -empty -exec rm -f {} ';'
 find $RPM_BUILD_ROOT -type f -name perllocal.pod -exec rm -f {} ';'
 
-(find $RPM_BUILD_ROOT%{_bindir} -type f | grep -vE "archimport|svn|cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@)               > bin-man-doc-files
+(find $RPM_BUILD_ROOT%{_bindir} -type f | grep -vE "p4import|archimport|svn|cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@)               > bin-man-doc-files
 (find $RPM_BUILD_ROOT%{perl_vendorlib} -type f | sed -e s@^$RPM_BUILD_ROOT@@) >> perl-files
 %if %{!?_without_docs:1}0
-(find $RPM_BUILD_ROOT%{_mandir} $RPM_BUILD_ROOT/Documentation -type f | grep -vE "archimport|svn|git-cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@ -e 's/$/*/' ) >> bin-man-doc-files
+(find $RPM_BUILD_ROOT%{_mandir} $RPM_BUILD_ROOT/Documentation -type f | grep -vE "p4import|archimport|svn|git-cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@ -e 's/$/*/' ) >> bin-man-doc-files
 %else
 rm -rf $RPM_BUILD_ROOT%{_mandir}
 %endif
@@ -133,6 +143,13 @@
 %{!?_without_docs: %{_mandir}/man1/git-archimport.1*}
 %{!?_without_docs: %doc Documentation/git-archimport.html }
 
+%files p4
+%defattr(-,root,root)
+%doc Documentation/git-p4import.txt
+%{_bindir}/git-p4import
+%{!?_without_docs: %{_mandir}/man1/git-p4import.1*}
+%{!?_without_docs: %doc Documentation/git-p4import.html }
+
 %files email
 %defattr(-,root,root)
 %doc Documentation/*email*.txt
@@ -167,6 +184,9 @@
 %{!?_without_docs: %doc Documentation/*.html }
 
 %changelog
+* Tue Mar 27 2007 Eygene Ryabinkin <rea-git@codelabs.ru>
+- Added the git-p4 package: Perforce import stuff.
+
 * Mon Feb 13 2007 Nicolas Pitre <nico@cam.org>
 - Update core package description (Git isn't as stupid as it used to be)
 
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 45ac9d7..e49eb91 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -19,7 +19,7 @@
 binmode STDOUT, ':utf8';
 
 BEGIN {
-	CGI->compile() if $ENV{MOD_PERL};
+	CGI->compile() if $ENV{'MOD_PERL'};
 }
 
 our $cgi = new CGI;
@@ -1800,7 +1800,7 @@
 		      $cgi->hidden(-name => "a") . "\n" .
 		      $cgi->hidden(-name => "h") . "\n" .
 		      $cgi->popup_menu(-name => 'st', -default => 'commit',
-				       -values => ['commit', 'author', 'committer', 'pickaxe']) .
+		                       -values => ['commit', 'author', 'committer', 'pickaxe']) .
 		      $cgi->sup($cgi->a({-href => href(action=>"search_help")}, "?")) .
 		      " search:\n",
 		      $cgi->textfield(-name => "s", -value => $searchtext) . "\n" .
@@ -1870,16 +1870,16 @@
 	my %arg = map { $_ => {action=>$_} } @navs;
 	if (defined $head) {
 		for (qw(commit commitdiff)) {
-			$arg{$_}{hash} = $head;
+			$arg{$_}{'hash'} = $head;
 		}
 		if ($current =~ m/^(tree | log | shortlog | commit | commitdiff | search)$/x) {
 			for (qw(shortlog log)) {
-				$arg{$_}{hash} = $head;
+				$arg{$_}{'hash'} = $head;
 			}
 		}
 	}
-	$arg{tree}{hash} = $treehead if defined $treehead;
-	$arg{tree}{hash_base} = $treebase if defined $treebase;
+	$arg{'tree'}{'hash'} = $treehead if defined $treehead;
+	$arg{'tree'}{'hash_base'} = $treebase if defined $treebase;
 
 	print "<div class=\"page_nav\">\n" .
 		(join " | ",
@@ -1927,9 +1927,9 @@
 	my ($action, $title, $hash, $hash_base) = @_;
 	my %args = ();
 
-	$args{action} = $action;
-	$args{hash} = $hash if $hash;
-	$args{hash_base} = $hash_base if $hash_base;
+	$args{'action'} = $action;
+	$args{'hash'} = $hash if $hash;
+	$args{'hash_base'} = $hash_base if $hash_base;
 
 	print "<div class=\"header\">\n" .
 	      $cgi->a({-href => href(%args), -class => "title"},
@@ -3095,7 +3095,7 @@
 		git_project_list_body(\@forklist, undef, 0, 15,
 		                      $#forklist <= 15 ? undef :
 		                      $cgi->a({-href => href(action=>"forks")}, "..."),
-				      'noheader');
+		                      'noheader');
 	}
 
 	git_footer_html();
@@ -3202,7 +3202,7 @@
 		my $rev = substr($full_rev, 0, 8);
 		my $author = $meta->{'author'};
 		my %date = parse_date($meta->{'author-time'},
-				      $meta->{'author-tz'});
+		                      $meta->{'author-tz'});
 		my $date = $date{'iso-tz'};
 		if ($group_size) {
 			$current_color = ++$current_color % $num_colors;
@@ -3214,9 +3214,9 @@
 			print " rowspan=\"$group_size\"" if ($group_size > 1);
 			print ">";
 			print $cgi->a({-href => href(action=>"commit",
-						     hash=>$full_rev,
-						     file_name=>$file_name)},
-				      esc_html($rev));
+			                             hash=>$full_rev,
+			                             file_name=>$file_name)},
+			              esc_html($rev));
 			print "</td>\n";
 		}
 		open (my $dd, "-|", git_cmd(), "rev-parse", "$full_rev^")
@@ -3225,13 +3225,13 @@
 		close $dd;
 		chomp($parent_commit);
 		my $blamed = href(action => 'blame',
-				  file_name => $meta->{'filename'},
-				  hash_base => $parent_commit);
+		                  file_name => $meta->{'filename'},
+		                  hash_base => $parent_commit);
 		print "<td class=\"linenr\">";
 		print $cgi->a({ -href => "$blamed#l$orig_lineno",
-				-id => "l$lineno",
-				-class => "linenr" },
-			      esc_html($lineno));
+		                -id => "l$lineno",
+		                -class => "linenr" },
+		              esc_html($lineno));
 		print "</td>";
 		print "<td class=\"pre\">" . esc_html($data) . "</td>\n";
 		print "</tr>\n";
@@ -3621,7 +3621,7 @@
 	my $name = $project;
 	$name =~ s/\047/\047\\\047\047/g;
 	open my $fd, "-|",
-	"$git archive --format=tar --prefix=\'$name\'/ $hash | $command"
+		"$git archive --format=tar --prefix=\'$name\'/ $hash | $command"
 		or die_error(undef, "Execute git-tar-tree failed");
 	binmode STDOUT, ':raw';
 	print <$fd>;
@@ -3734,7 +3734,7 @@
 		# difftree output is not printed for merges
 		open my $fd, "-|", git_cmd(), "diff-tree", '-r', "--no-commit-id",
 			@diff_opts, $parent, $hash, "--"
-				or die_error(undef, "Open git-diff-tree failed");
+			or die_error(undef, "Open git-diff-tree failed");
 		@difftree = map { chomp; $_ } <$fd>;
 		close $fd or die_error(undef, "Reading git-diff-tree failed");
 	}
@@ -4306,13 +4306,13 @@
 		if ($page > 0) {
 			$paging_nav .=
 				$cgi->a({-href => href(action=>"search", hash=>$hash,
-						       searchtext=>$searchtext, searchtype=>$searchtype)},
-					"first");
+				                       searchtext=>$searchtext, searchtype=>$searchtype)},
+				        "first");
 			$paging_nav .= " &sdot; " .
 				$cgi->a({-href => href(action=>"search", hash=>$hash,
-						       searchtext=>$searchtext, searchtype=>$searchtype,
-						       page=>$page-1),
-					 -accesskey => "p", -title => "Alt-p"}, "prev");
+				                       searchtext=>$searchtext, searchtype=>$searchtype,
+				                       page=>$page-1),
+				         -accesskey => "p", -title => "Alt-p"}, "prev");
 		} else {
 			$paging_nav .= "first";
 			$paging_nav .= " &sdot; prev";
@@ -4320,9 +4320,9 @@
 		if ($#commitlist >= 100) {
 			$paging_nav .= " &sdot; " .
 				$cgi->a({-href => href(action=>"search", hash=>$hash,
-						       searchtext=>$searchtext, searchtype=>$searchtype,
-						       page=>$page+1),
-					 -accesskey => "n", -title => "Alt-n"}, "next");
+				                       searchtext=>$searchtext, searchtype=>$searchtype,
+				                       page=>$page+1),
+				         -accesskey => "n", -title => "Alt-n"}, "next");
 		} else {
 			$paging_nav .= " &sdot; next";
 		}
@@ -4330,9 +4330,9 @@
 		if ($#commitlist >= 100) {
 			$next_link =
 				$cgi->a({-href => href(action=>"search", hash=>$hash,
-						       searchtext=>$searchtext, searchtype=>$searchtype,
-						       page=>$page+1),
-					 -accesskey => "n", -title => "Alt-n"}, "next");
+				                       searchtext=>$searchtext, searchtype=>$searchtype,
+				                       page=>$page+1),
+				         -accesskey => "n", -title => "Alt-n"}, "next");
 		}
 
 		git_print_page_nav('','', $hash,$co{'tree'},$hash, $paging_nav);
diff --git a/merge-recursive.c b/merge-recursive.c
index e1aebd7..3611a2b 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -221,7 +221,7 @@
 	struct cache_entry *ce;
 	ce = make_cache_entry(mode, sha1 ? sha1 : null_sha1, path, stage, refresh);
 	if (!ce)
-		return error("cache_addinfo failed: %s", strerror(cache_errno));
+		return error("addinfo_cache failed for path '%s'", path);
 	return add_cache_entry(ce, options);
 }
 
diff --git a/pack-check.c b/pack-check.c
index d988322..f58083d 100644
--- a/pack-check.c
+++ b/pack-check.c
@@ -42,13 +42,14 @@
 	 */
 	nr_objects = num_packed_objects(p);
 	for (i = 0, err = 0; i < nr_objects; i++) {
-		unsigned char sha1[20];
+		const unsigned char *sha1;
 		void *data;
 		enum object_type type;
 		unsigned long size;
 		off_t offset;
 
-		if (nth_packed_object_sha1(p, i, sha1))
+		sha1 = nth_packed_object_sha1(p, i);
+		if (!sha1)
 			die("internal error pack-check nth-packed-object");
 		offset = find_pack_entry_one(sha1, p);
 		if (!offset)
@@ -82,14 +83,16 @@
 	memset(chain_histogram, 0, sizeof(chain_histogram));
 
 	for (i = 0; i < nr_objects; i++) {
-		unsigned char sha1[20], base_sha1[20];
+		const unsigned char *sha1;
+		unsigned char base_sha1[20];
 		const char *type;
 		unsigned long size;
 		unsigned long store_size;
 		off_t offset;
 		unsigned int delta_chain_length;
 
-		if (nth_packed_object_sha1(p, i, sha1))
+		sha1 = nth_packed_object_sha1(p, i);
+		if (!sha1)
 			die("internal error pack-check nth-packed-object");
 		offset = find_pack_entry_one(sha1, p);
 		if (!offset)
diff --git a/read-cache.c b/read-cache.c
index 6339a27..a8f8a6b 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -24,8 +24,6 @@
 
 struct cache_tree *active_cache_tree;
 
-int cache_errno;
-
 static void *cache_mmap;
 static size_t cache_mmap_size;
 
@@ -327,7 +325,7 @@
 	return 0;
 }
 
-int add_file_to_index(const char *path, int verbose)
+int add_file_to_cache(const char *path, int verbose)
 {
 	int size, namelen;
 	struct stat st;
@@ -643,14 +641,15 @@
  * For example, you'd want to do this after doing a "git-read-tree",
  * to link up the stat cache details with the proper files.
  */
-struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really)
+static struct cache_entry *refresh_cache_ent(struct cache_entry *ce, int really, int *err)
 {
 	struct stat st;
 	struct cache_entry *updated;
 	int changed, size;
 
 	if (lstat(ce->name, &st) < 0) {
-		cache_errno = errno;
+		if (err)
+			*err = errno;
 		return NULL;
 	}
 
@@ -664,7 +663,8 @@
 	}
 
 	if (ce_modified(ce, &st, really)) {
-		cache_errno = EINVAL;
+		if (err)
+			*err = EINVAL;
 		return NULL;
 	}
 
@@ -696,6 +696,8 @@
 
 	for (i = 0; i < active_nr; i++) {
 		struct cache_entry *ce, *new;
+		int cache_errno = 0;
+
 		ce = active_cache[i];
 		if (ce_stage(ce)) {
 			while ((i < active_nr) &&
@@ -709,7 +711,7 @@
 			continue;
 		}
 
-		new = refresh_cache_entry(ce, really);
+		new = refresh_cache_ent(ce, really, &cache_errno);
 		if (new == ce)
 			continue;
 		if (!new) {
@@ -737,6 +739,11 @@
 	return has_errors;
 }
 
+struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really)
+{
+	return refresh_cache_ent(ce, really, NULL);
+}
+
 static int verify_hdr(struct cache_header *hdr, unsigned long size)
 {
 	SHA_CTX c;
diff --git a/sha1_file.c b/sha1_file.c
index 9c26038..4304fe9 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -1532,15 +1532,14 @@
 	return (uint32_t)((p->index_size - 20 - 20 - 4*256) / 24);
 }
 
-int nth_packed_object_sha1(const struct packed_git *p, uint32_t n,
-			   unsigned char* sha1)
+const unsigned char *nth_packed_object_sha1(const struct packed_git *p,
+					    uint32_t n)
 {
 	const unsigned char *index = p->index_data;
 	index += 4 * 256;
 	if (num_packed_objects(p) <= n)
-		return -1;
-	hashcpy(sha1, index + 24 * n + 4);
-	return 0;
+		return NULL;
+	return index + 24 * n + 4;
 }
 
 off_t find_pack_entry_one(const unsigned char *sha1,
diff --git a/sha1_name.c b/sha1_name.c
index bede0e5..267ea3f 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -71,7 +71,7 @@
 static int find_short_packed_object(int len, const unsigned char *match, unsigned char *sha1)
 {
 	struct packed_git *p;
-	unsigned char found_sha1[20];
+	const unsigned char *found_sha1 = NULL;
 	int found = 0;
 
 	prepare_packed_git();
@@ -80,10 +80,10 @@
 		uint32_t first = 0, last = num;
 		while (first < last) {
 			uint32_t mid = (first + last) / 2;
-			unsigned char now[20];
+			const unsigned char *now;
 			int cmp;
 
-			nth_packed_object_sha1(p, mid, now);
+			now = nth_packed_object_sha1(p, mid);
 			cmp = hashcmp(match, now);
 			if (!cmp) {
 				first = mid;
@@ -96,14 +96,14 @@
 			last = mid;
 		}
 		if (first < num) {
-			unsigned char now[20], next[20];
-			nth_packed_object_sha1(p, first, now);
+			const unsigned char *now, *next;
+		       now = nth_packed_object_sha1(p, first);
 			if (match_sha(len, match, now)) {
-				if (nth_packed_object_sha1(p, first+1, next) ||
-				    !match_sha(len, match, next)) {
+				next = nth_packed_object_sha1(p, first+1);
+			       if (!next|| !match_sha(len, match, next)) {
 					/* unique within this pack */
 					if (!found) {
-						hashcpy(found_sha1, now);
+						found_sha1 = now;
 						found++;
 					}
 					else if (hashcmp(found_sha1, now)) {
diff --git a/t/t6002-rev-list-bisect.sh b/t/t6002-rev-list-bisect.sh
index 7831e34..fcb3302 100755
--- a/t/t6002-rev-list-bisect.sh
+++ b/t/t6002-rev-list-bisect.sh
@@ -163,7 +163,7 @@
 # the bisection point is the head - this is the bad point.
 #
 
-test_output_expect_success "--bisect l5 ^root" 'git-rev-list $_bisect_option l5 ^root' <<EOF
+test_output_expect_success "$_bisect_option l5 ^root" 'git-rev-list $_bisect_option l5 ^root' <<EOF
 c3
 EOF
 
diff --git a/t/t6004-rev-list-path-optim.sh b/t/t6004-rev-list-path-optim.sh
index 5182dbb..761f09b 100755
--- a/t/t6004-rev-list-path-optim.sh
+++ b/t/t6004-rev-list-path-optim.sh
@@ -7,7 +7,8 @@
 test_expect_success setup '
 echo Hello > a &&
 git add a &&
-git commit -m "Initial commit" a
+git commit -m "Initial commit" a &&
+initial=$(git rev-parse --verify HEAD)
 '
 
 test_expect_success path-optimization '
@@ -16,4 +17,35 @@
     test $(git-rev-list $commit -- . | wc -l) = 1
 '
 
+test_expect_success 'further setup' '
+	git checkout -b side &&
+	echo Irrelevant >c &&
+	git add c &&
+	git commit -m "Side makes an irrelevant commit" &&
+	echo "More Irrelevancy" >c &&
+	git add c &&
+	git commit -m "Side makes another irrelevant commit" &&
+	echo Bye >a &&
+	git add a &&
+	git commit -m "Side touches a" &&
+	side=$(git rev-parse --verify HEAD) &&
+	echo "Yet more Irrelevancy" >c &&
+	git add c &&
+	git commit -m "Side makes yet another irrelevant commit" &&
+	git checkout master &&
+	echo Another >b &&
+	git add b &&
+	git commit -m "Master touches b" &&
+	git merge side &&
+	echo Touched >b &&
+	git add b &&
+	git commit -m "Master touches b again"
+'
+
+test_expect_success 'path optimization 2' '
+	( echo "$side"; echo "$initial" ) >expected &&
+	git rev-list HEAD -- a >actual &&
+	diff -u expected actual
+'
+
 test_done
diff --git a/wt-status.c b/wt-status.c
index a25632b..a055990 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -260,7 +260,7 @@
 	if (file_exists(x))
 		add_excludes_from_file(&dir, x);
 
-	read_directory(&dir, ".", "", 0);
+	read_directory(&dir, ".", "", 0, NULL);
 	for(i = 0; i < dir.nr; i++) {
 		/* check for matching entry, which is unmerged; lifted from
 		 * builtin-ls-files:show_other_files */