Commits

TK Soh  committed e7c0e22

overlay: improve Explorer's response using Mercurial dirstate

- skip repos without a valid dirstate file
- check status of files listed in dirstate only

  • Participants
  • Parent commits bde8494

Comments (0)

Files changed (1)

File tortoise/iconoverlay.py

 MODIFIED = "modified"
 UNKNOWN = "unknown"
 NOT_IN_TREE = "not in tree"
+NO_DIRSTATE = "dirstate not found"
 CONTROL_FILE = "control file"
 
 CACHE_TIMEOUT = 3000
 CACHE_SIZE = 400
 overlay_cache = {}
 
+def subdirs(p):
+    oldp = ""
+    if os.path.isdir(p):    
+        yield p
+    while 1:
+        oldp = p
+        p = os.path.dirname(p)
+        if p == oldp:
+            return
+        yield p
+
 def get_cache_list(path, size):
     """"
     get a sorted list (of size 'size') of file/folders which reside in  
             overlay_cache[path] = {'ticks': tc, 'status': UNKNOWN}
             return NOT_IN_TREE
 
+        # can't get correct status without dirstate
+        if not os.path.exists(os.path.join(root, ".hg", "dirstate")):
+            print "_get_state: dirstate not found"
+            return NO_DIRSTATE
+            
         # skip root direcory to improve speed
         if root == path:
             print "_get_state: skip repo root"
             overlay_cache[path] = {'ticks': tc, 'status': UNKNOWN}
             return NOT_IN_TREE
 
-        # get file status
-        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)
-        
+        def get_dirs(list):
+            return set([os.path.dirname(p) for p in list])
+            
         def add_dirs(list):
             dirs = set()
             for f in list:
                     dir = os.path.dirname(dir)
             list.extend(dirs)
 
-        # add directory status to list
-        add_dirs(clean)
-        add_dirs(modified)
-        add_dirs(added)
-        add_dirs(removed)
-        add_dirs(deleted)
+        # get file status
+        tc1 = win32api.GetTickCount()
+        cache_list = get_cache_list(path, CACHE_SIZE)
+        #print "cache_list: ", "\n".join(cache_list)
         
+        dirstate_list = [ os.path.normpath(os.path.join(root, x[0])) 
+                          for x in repo.dirstate._map.items() ]
+        ndirs = []
+        for d in get_dirs(dirstate_list):
+            ndirs.extend(subdirs(d))
+        dirstate_list.extend(set(ndirs))
+        #print "dirstate_list: ", "\n".join(dirstate_list)
+        
+        tracked_list = [ x for x in cache_list if x in dirstate_list ]
+        #print "tracked_list: ", "\n".join(tracked_list)
+
+        modified, added, removed, deleted = [], [], [], []
+        unknown, ignored, clean = [], [], []
+        files = []
+        if tracked_list:
+            try:
+                files, matchfn, anypats = cmdutil.matchpats(repo, tracked_list)
+                modified, added, removed, deleted, unknown, ignored, clean = [
+                        n for n in repo.status(files=files, list_clean=True)]
+
+                # add directory status to list
+                add_dirs(clean)
+                add_dirs(modified)
+                add_dirs(added)
+                add_dirs(removed)
+                add_dirs(deleted)
+            except util.Abort, inst:
+                print "abort: %s" % inst
+                print "treat as unknown : %s" % path
+                return UNKNOWN
+            
+            print "status() took %d ticks" % (win32api.GetTickCount() - tc1)
+                
         # cached file info
         tc = win32api.GetTickCount()
         overlay_cache = {}
             fpath = os.path.join(repo.root, os.path.normpath(f))
             overlay_cache[fpath] = {'ticks': tc, 'status': status}
             #print "cache:", fpath, status
+        
+        for f in cache_list:
+            if not f in overlay_cache:
+                overlay_cache[f] = {'ticks': tc, 'status': UNKNOWN}
 
         if overlay_cache.has_key(path):
             status = overlay_cache[path]['status']