eol: on update, only re-check files if filtering changed
authorMads Kiilerich <madski@unity3d.com>
Sun, 09 Oct 2016 15:54:49 +0200
changeset 30140 747e546c561f
parent 30139 27e00e6352ce
child 30141 c01acee367ec
eol: on update, only re-check files if filtering changed Before, update would mark all files as 'normallookup' in dirstate if .hgeol changed so all files would get the new filtering applied. That takes some time ... and is pointless if the filtering for that file didn't change. Instead, keep track of the old filtering and only check files where the filtering is changed. To keep the old filtering, change to write the applied .hgeol content to .hg/eol.cache instead of just touching it. That change is backwards/forwards compatible. In a real world test, this takes an update that is changing .hgeol and 30000 files from 12s to 4s - where the remaining eol overhead is 1-2s.
hgext/eol.py
--- a/hgext/eol.py	Thu Oct 13 10:59:29 2016 +0200
+++ b/hgext/eol.py	Sun Oct 09 15:54:49 2016 +0200
@@ -312,10 +312,15 @@
                 self._eolmatch = util.never
                 return
 
+            oldeol = None
             try:
                 cachemtime = os.path.getmtime(self.join("eol.cache"))
             except OSError:
                 cachemtime = 0
+            else:
+                olddata = self.vfs.read("eol.cache")
+                if olddata:
+                    oldeol = eolfile(self.ui, self.root, olddata)
 
             try:
                 eolmtime = os.path.getmtime(self.wjoin(".hgeol"))
@@ -324,17 +329,37 @@
 
             if eolmtime > cachemtime:
                 self.ui.debug("eol: detected change in .hgeol\n")
+
+                hgeoldata = self.wvfs.read('.hgeol')
+                neweol = eolfile(self.ui, self.root, hgeoldata)
+
                 wlock = None
                 try:
                     wlock = self.wlock()
                     for f in self.dirstate:
-                        if self.dirstate[f] == 'n':
-                            # all normal files need to be looked at
-                            # again since the new .hgeol file might no
-                            # longer match a file it matched before
-                            self.dirstate.normallookup(f)
-                    # Create or touch the cache to update mtime
-                    self.vfs("eol.cache", "w").close()
+                        if self.dirstate[f] != 'n':
+                            continue
+                        if oldeol is not None:
+                            if not oldeol.match(f) and not neweol.match(f):
+                                continue
+                            oldkey = None
+                            for pattern, key, m in oldeol.patterns:
+                                if m(f):
+                                    oldkey = key
+                                    break
+                            newkey = None
+                            for pattern, key, m in neweol.patterns:
+                                if m(f):
+                                    newkey = key
+                                    break
+                            if oldkey == newkey:
+                                continue
+                        # all normal files need to be looked at again since
+                        # the new .hgeol file specify a different filter
+                        self.dirstate.normallookup(f)
+                    # Write the cache to update mtime and cache .hgeol
+                    with self.vfs("eol.cache", "w") as f:
+                        f.write(hgeoldata)
                     wlock.release()
                 except error.LockUnavailable:
                     # If we cannot lock the repository and clear the