Commits

Anonymous committed b668dae Merge

merge

Comments (0)

Files changed (1)

tortoise/iconoverlay.py

 # Copyright (C) 2007 Henry Ludemann <misc@hl.id.au>
 # Copyright (C) 2007 TK Soh <teekaysoh@gmail.com>
 
-import os.path
+import os
 import win32api
 import win32con
 from win32com.shell import shell, shellcon
 import _winreg
-from mercurial import hg, repo, ui, cmdutil, util
+from mercurial import hg, repo, ui, cmdutil, util
 import thgutil
 
 UNCHANGED = "unchanged"
 NOT_IN_TREE = "not in tree"
 CONTROL_FILE = "control file"
 
-CACHE_TIMEOUT = 1000
+CACHE_TIMEOUT = 3000
+CACHE_SIZE = 400
+overlay_cache = {}
+
+def get_cache_list(path, size):
+    """"
+    get a sorted list (of size 'size') of file/folders which reside in  
+    the same directory as 'path' and windowed around 'path' on the list. 
+    The .hg directory will be ignore. Other directories will also be 
+    ignored unless path is a directory itself.
+    """
+    pathdir = os.path.dirname(path)
+    dlist = [x for x in os.listdir(pathdir) if x <> ".hg"]
+    if not os.path.isdir(path):
+        dlist = [x for x in dlist if not os.path.isdir(x)]
+    dlist.sort()
+    idx = dlist.index(os.path.basename(path))
+    begin = max(0, idx - size/2)
+    end = idx + size/2
+    cache_list = dlist[begin : end]
+    cache_list = [os.path.join(pathdir, x) for x in cache_list]
+    return cache_list
 
 class IconOverlayExtension(object):
     """
         ]
 
     def GetOverlayInfo(self):
-        import win32api
+        import win32api
 
         # only support Overlays In Explorer
-        print "GetOverlayInfo: checking if in explorer"
+        print "GetOverlayInfo: checking if in explorer"
         modname = win32api.GetModuleFileName(win32api.GetModuleHandle(None))
         print "modname = %s" % modname
         if not modname.lower().endswith("\\explorer.exe"):
 
     def _get_installed_overlays():
         key = win32api.RegOpenKeyEx(win32con.HKEY_LOCAL_MACHINE,
-                                    "Software\\Microsoft\\Windows\\" +
-                                        "CurrentVersion\\Explorer\\" +
+                                    "Software\\Microsoft\\Windows\\" +
+                                        "CurrentVersion\\Explorer\\" +
                                         "ShellIconOverlayIdentifiers",
                                     0,
                                     win32con.KEY_READ)
-        keys = win32api.RegEnumKeyEx(key)
+        keys = win32api.RegEnumKeyEx(key)
         handlercount = len(keys)
-        print "number of overlay handlers installed = %d" % handlercount
-        for i, k in enumerate(keys):
+        print "number of overlay handlers installed = %d" % handlercount
+        for i, k in enumerate(keys):
             print i, k
-        win32api.RegCloseKey(key)
+        win32api.RegCloseKey(key)
         return handlercount
         
     def _get_state(self, path):
         """
         Get the state of a given path in source control.
         """
-        
+        global overlay_cache
         print "called: _get_state(%s)" % path
         
         # debugging
 
         # check if path is cached
         tc = win32api.GetTickCount()
-        elapsed = tc - IconOverlayExtension.last_tick
-        if IconOverlayExtension.last_path == path and elapsed < CACHE_TIMEOUT:
-            return IconOverlayExtension.last_status
+        if overlay_cache.has_key(path):
+            if tc - overlay_cache[path]['ticks'] < CACHE_TIMEOUT:
+                print "%s: %s (cached)" % (path, overlay_cache[path]['status'])
+                return overlay_cache[path]['status']
 
         # open repo
         root = thgutil.find_root(path)
         print "_get_state: root = ", root
         if root is None:
             print "_get_state: not in repo"
-            # cached path and status
-            IconOverlayExtension.last_status = NOT_IN_TREE
-            IconOverlayExtension.last_path = path
-            IconOverlayExtension.last_tick = tc
             return NOT_IN_TREE
 
         # skip root direcory to improve speed
         if root == path:
             print "_get_state: skip repo root"
-            IconOverlayExtension.last_status = NOT_IN_TREE
-            IconOverlayExtension.last_path = path
-            IconOverlayExtension.last_tick = tc
             return NOT_IN_TREE
-            
-        print "_get_state: cwd (before) = ", os.getcwd()
-        #os.chdir(dir)
-        #print "_get_state: cwd (after) = ", os.getcwd()
 
         u = ui.ui()
-        try:
+        try:
             repo = hg.repository(u, path=root)
         except repo.RepoError:
             # We aren't in a working tree
             print "%s: not in repo" % dir
-            # cached path and status
-            IconOverlayExtension.last_status = NOT_IN_TREE
-            IconOverlayExtension.last_path = path
-            IconOverlayExtension.last_tick = tc
             return NOT_IN_TREE
 
         # get file status
-        try:
-            files, matchfn, anypats = cmdutil.matchpats(repo, [path])
+        tc1 = win32api.GetTickCount()
+        cache_list = get_cache_list(path, CACHE_SIZE)
+        #print "cache_list: ", "\n".join(cache_list)
+        try:
+            files, matchfn, anypats = cmdutil.matchpats(repo, cache_list)
             modified, added, removed, deleted, unknown, ignored, clean = [
                     n for n in repo.status(files=files, list_clean=True)]
         except util.Abort, inst:
             print "abort: %s" % inst
             print "treat as unknown : %s" % path
             return UNKNOWN
+        print "status() took %d ticks" % (win32api.GetTickCount() - tc1)
+        
+        # add directory status to list
+        clean.extend(set([os.path.dirname(x) for x in clean]))
+        modified.extend(set([os.path.dirname(x) for x in modified]))
+        added.extend(set([os.path.dirname(x) for x in added]))
+        removed.extend(set([os.path.dirname(x) for x in removed]))
+        deleted.extend(set([os.path.dirname(x) for x in deleted]))
 
-        if added:
-            status = ADDED
-        elif modified:
-            status = MODIFIED
-        elif clean:
-            status = UNCHANGED
+        # cached file info
+        tc = win32api.GetTickCount()
+        overlay_cache = {}
+        for f in files:
+            if f in added:
+                status = ADDED
+            elif f in modified:
+                status = MODIFIED
+            elif f in clean:
+                status = UNCHANGED
+            else:
+                status = UNKNOWN
+            fpath = os.path.join(repo.root, os.path.normpath(f))
+            overlay_cache[fpath] = {'ticks': tc, 'status': status}
+        #print "overlay cache:", "\n".join(overlay_cache)
+
+        if overlay_cache.has_key(path):
+            status = overlay_cache[path]['status']
         else:
             status = UNKNOWN
-
-        # cached file info
-        IconOverlayExtension.last_status = status
-        IconOverlayExtension.last_path = path
-        IconOverlayExtension.last_tick = tc
-
         print "%s: %s" % (path, status)
         return status