o Daemonized the hg incoming/outgoing calls to increase responsiveness;
o Added zero option to incoming and outgoing that will expand 0 counts.
2 files changed, 63 insertions(+), 9 deletions(-)

M .hgignore
M prompt.py
M .hgignore +2 -0
@@ 2,5 2,7 @@ syntax: glob
 
 .DS_Store
 *.pyc
+.idea/
 docs/.html
 docs/.tmp
+

          
M prompt.py +61 -9
@@ 14,6 14,7 @@ import re
 import os
 import subprocess
 from datetime import datetime, timedelta
+from contextlib import closing
 from os import path
 from mercurial import extensions, commands, cmdutil, help
 from mercurial.i18n import _

          
@@ 34,15 35,54 @@ CACHE_TIMEOUT = timedelta(minutes=15)
 
 FILTER_ARG = re.compile(r'\|.+\((.*)\)')
 
+
+def _daemon_spawn (fn):
+    """
+    Daemonize the function `fn`. The calling process will not be
+    terminated; the daemon will terminate after `fn` completes.
+    """
+
+    pid = os.fork()
+    if pid == 0:
+        pid = os.fork()
+        if pid == 0:
+            for fd in range(0,subprocess.MAXFD):
+                try: os.close(fd)
+                except OSError: pass
+
+            os.open(os.devnull, os.O_RDWR)
+            os.dup2(0,1)
+            os.dup2(0,2)
+
+            try:
+                fn()
+            finally:
+                # We are done with this subprocess, so exit.
+                os._exit(0)
+        else:
+            # Close the parent (the first child) of the second child.
+            os._exit(0)
+
 def _cache_remote(repo, kind):
     cache = path.join(repo.root, CACHE_PATH, kind)
     c_tmp = cache + '.temp'
 
-    # This is kind of a hack and I feel a little bit dirty for doing it.
-    IGNORE = open('NUL:','w') if subprocess.mswindows else open('/dev/null','w')
+    devnull = 'NUL:' if subprocess.mswindows else os.devnull
+    spawn = lambda fn: fn() if subprocess.mswindows else _daemon_spawn
 
-    subprocess.call(['hg', kind, '--quiet'], stdout=file(c_tmp, 'w'), stderr=IGNORE)
-    os.rename(c_tmp, cache)
+    def _update_cache():
+        # This is kind of a hack and I feel a little bit dirty for doing it.
+        with closing(open(devnull, 'w')) as IGNORE:
+            subprocess.call(
+                ['hg', kind, '--quiet'],
+                stdout=file(c_tmp, 'w'),
+                stderr=IGNORE
+            )
+            os.rename(c_tmp, cache)
+
+    # Spawn the update in a daemon process so it doesn't slow
+    # down the prompt return.
+    spawn (_update_cache)
     return
 
 def _with_groups(groups, out):

          
@@ 285,10 325,12 @@ def prompt(ui, repo, fs='', **opts):
             if cache_exists:
                 with open(cache) as c:
                     count = len(c.readlines())
-                    if g[1]:
-                        return _with_groups(g, str(count)) if count else ''
+                    if g[1] and count > 0:
+                        return _with_groups(g, str(count))
+                    elif g[2]:
+                        return _with_groups(g, '0') if not count else ''
                     else:
-                        return _with_groups(g, '') if count else ''
+                        return _with_groups(g, '')
             else:
                 return ''
         return _r

          
@@ 428,8 470,14 @@ def prompt(ui, repo, fs='', **opts):
             ')*': _tip,
         'update': _update,
 
-        'incoming(\|count)?': _remote('incoming'),
-        'outgoing(\|count)?': _remote('outgoing'),
+        'incoming(?:'
+            '(\|count)'
+            '|(\|zero)'
+            ')*': _remote('incoming'),
+        'outgoing(?:'
+            '(\|count)'
+            '|(\|zero)'
+            ')*': _remote('outgoing')
     }
 
     if opts.get("cache_incoming"):

          
@@ 508,6 556,8 @@ incoming
 
      |count
          Display the number of incoming changesets (if greater than 0).
+     |zero
+         Display 0 if there are no incoming changesets.
 
 node
      Display the (full) changeset hash of the current parent.

          
@@ 531,6 581,8 @@ outgoing
 
      |count
          Display the number of outgoing changesets (if greater than 0).
+     |zero
+         Display 0 if there are no incoming changesets.
 
 patch
      Display the topmost currently-applied patch (requires the mq