changeset 16:44feac64ecfe

refactoring: disentangled breadth-first and depth-first search; made functions nested
author jakob krainz <jakob@hawo-net.de>
date Tue, 06 Mar 2012 19:59:36 +0100
parents 6ee895918df9
children 5ea3f7533ec5
files onsub.py
diffstat 1 files changed, 90 insertions(+), 92 deletions(-) [+]
line wrap: on
line diff
--- a/onsub.py	Tue Mar 06 16:21:28 2012 +0100
+++ b/onsub.py	Tue Mar 06 19:59:36 2012 +0100
@@ -49,6 +49,92 @@
         State of the current subrepository as specified in the
         containing repository's ``.hgsubstate`` file.
     """
+
+    # function level "constants" - these won't be modified by the nested functions
+    print0 = opts.get('print0')
+    if opts.get('ignore_errors'):
+        onerr = None
+    else:
+        onerr = util.Abort
+    maxdepth = opts.get('max_depth')
+    precmd = None
+    postcmd = None
+    includeroot = opts.get('root_repo')
+
+    def execCmd(sub, cmd):
+        """if sub == None, cmd is executed inside repo; else, inside sub.
+        If cmd == None, do nothing. If cmd == '', do only the print0 (if needed). 
+        Else, do either print0 or the debugging message, then execute the command.
+        """
+        if sub == None:
+            envargdict = dict(HG_SUBPATH='.',
+                              HG_SUBURL='.',
+                              HG_SUBSTATE=repo['.'].hex(),
+                              HG_REPO=repo.root)
+            relpath = '.'
+            cmdwd = repo.root
+        else:
+            # subrepo.relpath was renamed to subrepo.subrelpath in
+            # 18b5b6392fcf.
+            if hasattr(subrepo, 'relpath'):
+                relpath = subrepo.relpath(sub)
+            else:
+                relpath = subrepo.subrelpath(sub)
+            envargdict = dict(HG_SUBPATH=relpath,
+                              HG_SUBURL=sub._path,
+                              HG_SUBSTATE=sub._state[1],
+                              HG_REPO=repo.root)
+            cmdwd = os.path.join(repo.root, relpath)
+        if cmd != None:
+            if print0:
+                ui.write(relpath, "\0")
+            if cmd != '':
+                if not print0: ui.note(_("executing '%s' in %s\n") % (cmd, relpath))
+                util.system(cmd, environ=envargdict, cwd=cmdwd, onerr=onerr,
+                            errprefix=_('terminated onsub in %s') % relpath)
+
+    def bfs():
+        """execute precmd in repo.root and in each subrepository, breadth-first"""
+        if includeroot:
+            execCmd(None, precmd) 
+        ctx = repo['.']
+        work = [(1, ctx.sub(subpath)) for subpath in sorted(ctx.substate)]
+        while work:
+            (depth, sub) = work.pop(0)
+            if depth > maxdepth >= 0:
+                continue
+            execCmd(sub, precmd) 
+            if isinstance(sub, subrepo.hgsubrepo):
+                rev = sub._state[1]
+                ctx = sub._repo[rev]
+                w = [(depth + 1, ctx.sub(subpath)) 
+                     for subpath in sorted(ctx.substate)]
+                work.extend(w)
+    
+    def dfs():
+        """execute pre-/postcmd in repo.root and in each subrepository, depth-first"""
+
+        def dfs_rek(depth, sub):
+            if depth > maxdepth >= 0:
+                return
+            execCmd(sub, precmd) 
+            if isinstance(sub, subrepo.hgsubrepo):
+                rev = sub._state[1]
+                ctx = sub._repo[rev]
+                for subpath in sorted(ctx.substate):
+                    dfs_rek(depth+1, ctx.sub(subpath))
+            execCmd(sub, postcmd)
+    
+        ctx = repo['.']
+        work = [ctx.sub(subpath) for subpath in sorted(ctx.substate)]
+        if includeroot:
+            execCmd(None, precmd) 
+        for sub in work:
+            dfs_rek(1, sub)
+        if includeroot:
+            execCmd(None, postcmd) 
+        
+    ### start of main function part ###
     if len(args) == 2:
         precmd = args[0]
         postcmd = args[1]
@@ -73,100 +159,12 @@
         raise util.Abort(_("onsub: at most 2 command arguments required"))
     if opts.get('post_order') and opts.get('breadth_first'):
         raise util.Abort(_("onsub: '-b' and '-p' are mutually exclusive"))
-    foreach(ui, repo, precmd, postcmd,
-            not opts.get('breadth_first'),
-            opts.get('max_depth'),
-            opts.get('print0'),
-            opts.get('ignore_errors'),
-            opts.get('root_repo'))
 
-def execCmd(ui, rootrepo, sub, doaction, print0, cmd, inroot, ignoreerrors):
-    """ if doaction, execute cmd; else, do nothing.  if inroot,
-    then command is executed inside rootrepo; else, inside sub
-    
-    If cmd == None, do nothing. If cmd == '', do only the print0 (if needed). 
-    Else, do either print0 or the debugging message, then execute the command.
-    """
-    if not doaction:
-        return
-    if inroot:
-        envargdict = dict(HG_SUBPATH='.',
-                          HG_SUBURL='.',
-                          HG_SUBSTATE=rootrepo['.'].hex(),
-                          HG_REPO=rootrepo.root)
-        relpath = '.'
-        cmdwd = rootrepo.root
-    else:
-        # subrepo.relpath was renamed to subrepo.subrelpath in
-        # 18b5b6392fcf.
-        if hasattr(subrepo, 'relpath'):
-            relpath = subrepo.relpath(sub)
-        else:
-            relpath = subrepo.subrelpath(sub)
-        envargdict = dict(HG_SUBPATH=relpath,
-                          HG_SUBURL=sub._path,
-                          HG_SUBSTATE=sub._state[1],
-                          HG_REPO=rootrepo.root)
-        cmdwd = os.path.join(rootrepo.root, relpath)
-    if ignoreerrors:
-        onerr = None
+    if opts.get('breadth_first'):
+        bfs()
     else:
-        onerr = util.Abort
-    if cmd != None:
-        if print0:
-            ui.write(relpath, "\0")
-        if cmd != '':
-            if not print0: ui.note(_("executing '%s' in %s\n") % (cmd, relpath))
-            util.system(cmd, environ=envargdict, cwd=cmdwd, onerr=onerr,
-                        errprefix=_('terminated onsub in %s') % relpath)
-    
-
-
-def foreach(ui, repo, precmd, postcmd, depthfirst, maxdepth, print0, ignoreerrors, includeroot):
-    """execute (pre/post)cmd in repo.root and in each subrepository"""
-    seen = set()
-    execCmd(ui=ui, rootrepo=repo, sub=None, doaction=includeroot, 
-            print0=print0, cmd=precmd, inroot=True, ignoreerrors=ignoreerrors) 
-    ctx = repo['.']
-    work = [(1, ctx.sub(subpath)) for subpath in sorted(ctx.substate)]
-    if depthfirst:
-        work.reverse()
-    while work:
-        if depthfirst:
-            (depth, sub) = work[-1]
-            if sub in seen:
-                dopreaction = False
-                dopostaction = True
-                doaddchildren = False
-                work.pop()
-            else:
-                dopreaction = True
-                dopostaction = False
-                doaddchildren = True
-                seen.add(sub)
-        else:
-            (depth, sub) = work.pop(0)
-            dopreaction = True
-            dopostaction = False
-            doaddchildren = True
-        if depth > maxdepth >= 0:
-            continue
-        execCmd(ui=ui, rootrepo=repo, sub=sub, doaction=dopreaction, 
-                print0=print0, cmd=precmd, inroot=False, ignoreerrors=ignoreerrors) 
-        if doaddchildren:
-            if isinstance(sub, subrepo.hgsubrepo):
-                rev = sub._state[1]
-                ctx = sub._repo[rev]
-                w = [(depth + 1, ctx.sub(subpath)) 
-                     for subpath in sorted(ctx.substate)]
-                if depthfirst:
-                    w.reverse()
-                work.extend(w)
-        execCmd(ui=ui, rootrepo=repo, sub=sub, doaction=dopostaction, 
-                print0=print0, cmd=postcmd, inroot=False, ignoreerrors=ignoreerrors) 
-    execCmd(ui=ui, rootrepo=repo, sub=None, doaction=includeroot, 
-            print0=print0, cmd=postcmd, inroot=True, ignoreerrors=ignoreerrors) 
-            
+        dfs()
+          
 cmdtable = {
     "onsub":
         (onsub,