comparison onsub.py @ 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 34aa014b5989
children 5ea3f7533ec5
comparison
equal deleted inserted replaced
15:6ee895918df9 16:44feac64ecfe
47 47
48 ``HG_SUBSTATE``: 48 ``HG_SUBSTATE``:
49 State of the current subrepository as specified in the 49 State of the current subrepository as specified in the
50 containing repository's ``.hgsubstate`` file. 50 containing repository's ``.hgsubstate`` file.
51 """ 51 """
52
53 # function level "constants" - these won't be modified by the nested functions
54 print0 = opts.get('print0')
55 if opts.get('ignore_errors'):
56 onerr = None
57 else:
58 onerr = util.Abort
59 maxdepth = opts.get('max_depth')
60 precmd = None
61 postcmd = None
62 includeroot = opts.get('root_repo')
63
64 def execCmd(sub, cmd):
65 """if sub == None, cmd is executed inside repo; else, inside sub.
66 If cmd == None, do nothing. If cmd == '', do only the print0 (if needed).
67 Else, do either print0 or the debugging message, then execute the command.
68 """
69 if sub == None:
70 envargdict = dict(HG_SUBPATH='.',
71 HG_SUBURL='.',
72 HG_SUBSTATE=repo['.'].hex(),
73 HG_REPO=repo.root)
74 relpath = '.'
75 cmdwd = repo.root
76 else:
77 # subrepo.relpath was renamed to subrepo.subrelpath in
78 # 18b5b6392fcf.
79 if hasattr(subrepo, 'relpath'):
80 relpath = subrepo.relpath(sub)
81 else:
82 relpath = subrepo.subrelpath(sub)
83 envargdict = dict(HG_SUBPATH=relpath,
84 HG_SUBURL=sub._path,
85 HG_SUBSTATE=sub._state[1],
86 HG_REPO=repo.root)
87 cmdwd = os.path.join(repo.root, relpath)
88 if cmd != None:
89 if print0:
90 ui.write(relpath, "\0")
91 if cmd != '':
92 if not print0: ui.note(_("executing '%s' in %s\n") % (cmd, relpath))
93 util.system(cmd, environ=envargdict, cwd=cmdwd, onerr=onerr,
94 errprefix=_('terminated onsub in %s') % relpath)
95
96 def bfs():
97 """execute precmd in repo.root and in each subrepository, breadth-first"""
98 if includeroot:
99 execCmd(None, precmd)
100 ctx = repo['.']
101 work = [(1, ctx.sub(subpath)) for subpath in sorted(ctx.substate)]
102 while work:
103 (depth, sub) = work.pop(0)
104 if depth > maxdepth >= 0:
105 continue
106 execCmd(sub, precmd)
107 if isinstance(sub, subrepo.hgsubrepo):
108 rev = sub._state[1]
109 ctx = sub._repo[rev]
110 w = [(depth + 1, ctx.sub(subpath))
111 for subpath in sorted(ctx.substate)]
112 work.extend(w)
113
114 def dfs():
115 """execute pre-/postcmd in repo.root and in each subrepository, depth-first"""
116
117 def dfs_rek(depth, sub):
118 if depth > maxdepth >= 0:
119 return
120 execCmd(sub, precmd)
121 if isinstance(sub, subrepo.hgsubrepo):
122 rev = sub._state[1]
123 ctx = sub._repo[rev]
124 for subpath in sorted(ctx.substate):
125 dfs_rek(depth+1, ctx.sub(subpath))
126 execCmd(sub, postcmd)
127
128 ctx = repo['.']
129 work = [ctx.sub(subpath) for subpath in sorted(ctx.substate)]
130 if includeroot:
131 execCmd(None, precmd)
132 for sub in work:
133 dfs_rek(1, sub)
134 if includeroot:
135 execCmd(None, postcmd)
136
137 ### start of main function part ###
52 if len(args) == 2: 138 if len(args) == 2:
53 precmd = args[0] 139 precmd = args[0]
54 postcmd = args[1] 140 postcmd = args[1]
55 if opts.get('breadth_first') or opts.get('post_order'): 141 if opts.get('breadth_first') or opts.get('post_order'):
56 raise util.Abort(_("onsub: '-b' and '-p' imply the use of only one command")) 142 raise util.Abort(_("onsub: '-b' and '-p' imply the use of only one command"))
71 postcmd = None 157 postcmd = None
72 else: 158 else:
73 raise util.Abort(_("onsub: at most 2 command arguments required")) 159 raise util.Abort(_("onsub: at most 2 command arguments required"))
74 if opts.get('post_order') and opts.get('breadth_first'): 160 if opts.get('post_order') and opts.get('breadth_first'):
75 raise util.Abort(_("onsub: '-b' and '-p' are mutually exclusive")) 161 raise util.Abort(_("onsub: '-b' and '-p' are mutually exclusive"))
76 foreach(ui, repo, precmd, postcmd,
77 not opts.get('breadth_first'),
78 opts.get('max_depth'),
79 opts.get('print0'),
80 opts.get('ignore_errors'),
81 opts.get('root_repo'))
82 162
83 def execCmd(ui, rootrepo, sub, doaction, print0, cmd, inroot, ignoreerrors): 163 if opts.get('breadth_first'):
84 """ if doaction, execute cmd; else, do nothing. if inroot, 164 bfs()
85 then command is executed inside rootrepo; else, inside sub
86
87 If cmd == None, do nothing. If cmd == '', do only the print0 (if needed).
88 Else, do either print0 or the debugging message, then execute the command.
89 """
90 if not doaction:
91 return
92 if inroot:
93 envargdict = dict(HG_SUBPATH='.',
94 HG_SUBURL='.',
95 HG_SUBSTATE=rootrepo['.'].hex(),
96 HG_REPO=rootrepo.root)
97 relpath = '.'
98 cmdwd = rootrepo.root
99 else: 165 else:
100 # subrepo.relpath was renamed to subrepo.subrelpath in 166 dfs()
101 # 18b5b6392fcf. 167
102 if hasattr(subrepo, 'relpath'):
103 relpath = subrepo.relpath(sub)
104 else:
105 relpath = subrepo.subrelpath(sub)
106 envargdict = dict(HG_SUBPATH=relpath,
107 HG_SUBURL=sub._path,
108 HG_SUBSTATE=sub._state[1],
109 HG_REPO=rootrepo.root)
110 cmdwd = os.path.join(rootrepo.root, relpath)
111 if ignoreerrors:
112 onerr = None
113 else:
114 onerr = util.Abort
115 if cmd != None:
116 if print0:
117 ui.write(relpath, "\0")
118 if cmd != '':
119 if not print0: ui.note(_("executing '%s' in %s\n") % (cmd, relpath))
120 util.system(cmd, environ=envargdict, cwd=cmdwd, onerr=onerr,
121 errprefix=_('terminated onsub in %s') % relpath)
122
123
124
125 def foreach(ui, repo, precmd, postcmd, depthfirst, maxdepth, print0, ignoreerrors, includeroot):
126 """execute (pre/post)cmd in repo.root and in each subrepository"""
127 seen = set()
128 execCmd(ui=ui, rootrepo=repo, sub=None, doaction=includeroot,
129 print0=print0, cmd=precmd, inroot=True, ignoreerrors=ignoreerrors)
130 ctx = repo['.']
131 work = [(1, ctx.sub(subpath)) for subpath in sorted(ctx.substate)]
132 if depthfirst:
133 work.reverse()
134 while work:
135 if depthfirst:
136 (depth, sub) = work[-1]
137 if sub in seen:
138 dopreaction = False
139 dopostaction = True
140 doaddchildren = False
141 work.pop()
142 else:
143 dopreaction = True
144 dopostaction = False
145 doaddchildren = True
146 seen.add(sub)
147 else:
148 (depth, sub) = work.pop(0)
149 dopreaction = True
150 dopostaction = False
151 doaddchildren = True
152 if depth > maxdepth >= 0:
153 continue
154 execCmd(ui=ui, rootrepo=repo, sub=sub, doaction=dopreaction,
155 print0=print0, cmd=precmd, inroot=False, ignoreerrors=ignoreerrors)
156 if doaddchildren:
157 if isinstance(sub, subrepo.hgsubrepo):
158 rev = sub._state[1]
159 ctx = sub._repo[rev]
160 w = [(depth + 1, ctx.sub(subpath))
161 for subpath in sorted(ctx.substate)]
162 if depthfirst:
163 w.reverse()
164 work.extend(w)
165 execCmd(ui=ui, rootrepo=repo, sub=sub, doaction=dopostaction,
166 print0=print0, cmd=postcmd, inroot=False, ignoreerrors=ignoreerrors)
167 execCmd(ui=ui, rootrepo=repo, sub=None, doaction=includeroot,
168 print0=print0, cmd=postcmd, inroot=True, ignoreerrors=ignoreerrors)
169
170 cmdtable = { 168 cmdtable = {
171 "onsub": 169 "onsub":
172 (onsub, 170 (onsub,
173 [('b', 'breadth-first', None, 171 [('b', 'breadth-first', None,
174 _('use breadth-first traversal')), 172 _('use breadth-first traversal')),