dirstate walking optimizations
The repo walking code introduces a number of calls to dirstate.map.copy(),
significantly slowing down the walk on large trees. When a list of
files is passed to the walking code, we should only look at map entries
relevant to the file list passed in.
dirstate.filterfiles() is added to return a subset of the dirstate map.
The subset includes in files passed in, and if one of the files requested
is actually a directory, it includes any files inside that directory tree.
This brings the time for hg diff Makefile down from 1.7s to .3s on
a linux kernel repo.
Also, the diff command was unconditionally calling makewalk, leading
to an extra pass through repo.changes. This patch avoids the call
to makewalk when commands.diff isn't given a list of patterns, cutting
the time for hg diff (with no args) in half.
Index: mine/mercurial/hg.py
===================================================================
+ hg init
+ hg add file1 file2
+ hg commit -m added file1 and file2 -d 0 0 -u user
+ hg commit -m changed file1 -d 0 0 -u user
+ hg -q log
1:3aa14bbc23d90e3f8b5b639b4a43d76509bae76c
0:8633637036c18f021d771208e16ae3508ab81d28
+ hg id
3aa14bbc23d9 tip
+ hg update -C 0
+ hg id
8633637036c1
+ hg id
8633637036c1+
+ hg revert
+ hg diff
+ hg status
+ hg id
8633637036c1
+ hg update
+ hg diff
+ hg status
+ hg id
3aa14bbc23d9 tip
+ hg update -C 0
+ hg update
merge: warning: conflicts during merge
merging file1
merging file1 failed!
+ hg diff
diff -r 3aa14bbc23d9 file1
--- a/file1
+++ b/file1
@@ -1,2 +1,6 @@
added file1
+<<<<<<<
+changed file1 different
+=======
changed file1
+>>>>>>>
+ hg status
M file1
+ hg id
3aa14bbc23d9+ tip
+ hg revert
+ hg diff
FIXME: This is a known bug:
+ hg status
+ hg id
3aa14bbc23d9 tip
+ hg revert -r tip
+ hg diff
+ hg status
+ hg id
3aa14bbc23d9 tip
+ hg update -C
+ hg diff
+ hg status
+ hg id
3aa14bbc23d9 tip