Mercurial > hg-onsub
changeset 12:90b54c4fe4fe
onsub extension: pre and post order
author | jakob krainz <jakob@hawo-net.de> |
---|---|
date | Tue, 06 Mar 2012 12:55:40 +0100 |
parents | 4cb3f28590fd |
children | b10dd4461b52 |
files | onsub.py test-onsub.t |
diffstat | 2 files changed, 170 insertions(+), 47 deletions(-) [+] |
line wrap: on
line diff
--- a/onsub.py Tue Mar 06 12:22:06 2012 +0100 +++ b/onsub.py Tue Mar 06 12:55:40 2012 +0100 @@ -42,65 +42,133 @@ State of the current subrepository as specified in the containing repository's ``.hgsubstate`` file. """ - cmd = ' '.join(args) - foreach(ui, repo, cmd, + if len(args) == 2: + precmd = args[0] + postcmd = args[1] + if opts.get('breadth_first') or opts.get('post_order'): + raise util.Abort(_("onsub: '-b' and '-p' imply the use of only one command")) + elif len(args) == 1: + if opts.get('post_order'): + precmd = None + postcmd = args[0] + else: + precmd = args[0] + postcmd = None + elif len(args) == 0: + # cmd == '' means only do print0 + if opts.get('post_order'): + precmd = None + postcmd = '' + else: + precmd = '' + postcmd = None + else: + 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')) - -def foreach(ui, repo, cmd, depthfirst, maxdepth, print0, ignoreerrors): - """execute cmd in repo.root and in each subrepository""" - ctx = repo['.'] - work = [(1, ctx.sub(subpath)) for subpath in sorted(ctx.substate)] - if depthfirst: - work.reverse() + opts.get('ignore_errors'), + opts.get('root_repo')) - while work: - if depthfirst: - (depth, sub) = work.pop() - else: - (depth, sub) = work.pop(0) - if depth > maxdepth >= 0: - continue - +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 + else: + onerr = util.Abort + if cmd != None: if print0: ui.write(relpath, "\0") - else: - ui.note(_("executing '%s' in %s\n") % (cmd, relpath)) - if ignoreerrors: - onerr = None + 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: - onerr = util.Abort - util.system(cmd, environ=dict(HG_SUBPATH=relpath, - HG_SUBURL=sub._path, - HG_SUBSTATE=sub._state[1], - HG_REPO=repo.root), - cwd=os.path.join(repo.root, relpath), - onerr=onerr, - errprefix=_('terminated onsub in %s') % relpath) - - 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) - + (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) + cmdtable = { "onsub": (onsub, [('b', 'breadth-first', None, _('use breadth-first traversal')), + ('p', 'post-order', None, + _('use post-order depth-first traversal')), + ('', 'root-repo', None, + _('include root repository in traversal')), ('', 'max-depth', -1, _('limit recursion to N levels (negative for no limit)'), 'N'), ('', 'ignore-errors', None,
--- a/test-onsub.t Tue Mar 06 12:22:06 2012 +0100 +++ b/test-onsub.t Tue Mar 06 12:55:40 2012 +0100 @@ -39,11 +39,13 @@ options: - -b --breadth-first use breadth-first traversal - --max-depth N limit recursion to N levels (negative for no limit) - (default: -1) - --ignore-errors continue execution despite errors - -0 --print0 end subrepository names with NUL, for use with xargs + -b --breadth-first use breadth-first traversal + -p --post-order use post-order depth-first traversal + --root-repo include root repository in traversal + --max-depth N limit recursion to N levels (negative for no limit) + (default: -1) + --ignore-errors continue execution despite errors + -0 --print0 end subrepository names with NUL, for use with xargs use "hg -v help onsub" to show global options @@ -81,7 +83,7 @@ committing subrepository b/u committing subrepository b/v -The default depth-first traversal: +The default depth-first pre-order traversal: $ hg onsub 'echo $HG_SUBPATH' a @@ -94,6 +96,55 @@ b/u b/v +Traversal including the root repository: + + $ hg onsub 'echo $HG_SUBPATH' --root-repo + . + a + a/x + a/y + a/y/r + a/y/s + a/y/t + b + b/u + b/v + +Depth-first post-order traversal: + + $ hg onsub 'echo $HG_SUBPATH' --post-order + a/x + a/y/r + a/y/s + a/y/t + a/y + a + b/u + b/v + b + +Depth-first pre- and post-order traversal: + + $ hg onsub 'echo pre $HG_SUBPATH' 'echo post $HG_SUBPATH' + pre a + pre a/x + post a/x + pre a/y + pre a/y/r + post a/y/r + pre a/y/s + post a/y/s + pre a/y/t + post a/y/t + post a/y + post a + pre b + pre b/u + post b/u + pre b/v + post b/v + post b + Breadth-first traversal: $ hg onsub 'echo $HG_SUBPATH' --breadth-first @@ -125,6 +176,10 @@ a/y b/u b/v + $ hg onsub --max-depth 1 -b --root-repo 'echo $HG_SUBPATH' + . + a + b Test aborting: