Mercurial > hg-onsub
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')), |