# HG changeset patch # User Chris # Date 1467413538 18000 # Node ID ed22ce1f3057800e517390656fa517b5e413f35a # Parent a410d2232772cf9f5bdb223739e9c2ec6a211543 o Daemonized the hg incoming/outgoing calls to increase responsiveness; o Added zero option to incoming and outgoing that will expand 0 counts. diff -r a410d2232772 -r ed22ce1f3057 .hgignore --- a/.hgignore Fri Jul 01 17:47:27 2016 -0500 +++ b/.hgignore Fri Jul 01 17:52:18 2016 -0500 @@ -2,5 +2,7 @@ .DS_Store *.pyc +.idea/ docs/.html docs/.tmp + diff -r a410d2232772 -r ed22ce1f3057 prompt.py --- a/prompt.py Fri Jul 01 17:47:27 2016 -0500 +++ b/prompt.py Fri Jul 01 17:52:18 2016 -0500 @@ -14,6 +14,7 @@ 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 @@ 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 @@ 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 @@ ')*': _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 @@ |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 @@ |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