64 except (ImportError, SyntaxError): |
64 except (ImportError, SyntaxError): |
65 e2 = sys.exc_info() |
65 e2 = sys.exc_info() |
66 if ui.tracebackflag: |
66 if ui.tracebackflag: |
67 ui.warn( |
67 ui.warn( |
68 _( |
68 _( |
69 'exception from first failed import ' |
69 b'exception from first failed import ' |
70 'attempt:\n' |
70 b'attempt:\n' |
71 ) |
71 ) |
72 ) |
72 ) |
73 ui.traceback(e1) |
73 ui.traceback(e1) |
74 if ui.tracebackflag: |
74 if ui.tracebackflag: |
75 ui.warn( |
75 ui.warn( |
76 _( |
76 _( |
77 'exception from second failed import ' |
77 b'exception from second failed import ' |
78 'attempt:\n' |
78 b'attempt:\n' |
79 ) |
79 ) |
80 ) |
80 ) |
81 ui.traceback(e2) |
81 ui.traceback(e2) |
82 |
82 |
83 if not ui.tracebackflag: |
83 if not ui.tracebackflag: |
84 tracebackhint = _( |
84 tracebackhint = _( |
85 'run with --traceback for stack trace' |
85 b'run with --traceback for stack trace' |
86 ) |
86 ) |
87 else: |
87 else: |
88 tracebackhint = None |
88 tracebackhint = None |
89 raise error.HookLoadError( |
89 raise error.HookLoadError( |
90 _('%s hook is invalid: import of "%s" failed') |
90 _(b'%s hook is invalid: import of "%s" failed') |
91 % (hname, modname), |
91 % (hname, modname), |
92 hint=tracebackhint, |
92 hint=tracebackhint, |
93 ) |
93 ) |
94 sys.path = oldpaths |
94 sys.path = oldpaths |
95 try: |
95 try: |
96 for p in funcname.split('.')[1:]: |
96 for p in funcname.split(b'.')[1:]: |
97 obj = getattr(obj, p) |
97 obj = getattr(obj, p) |
98 except AttributeError: |
98 except AttributeError: |
99 raise error.HookLoadError( |
99 raise error.HookLoadError( |
100 _('%s hook is invalid: "%s" is not defined') % (hname, funcname) |
100 _(b'%s hook is invalid: "%s" is not defined') |
|
101 % (hname, funcname) |
101 ) |
102 ) |
102 if not callable(obj): |
103 if not callable(obj): |
103 raise error.HookLoadError( |
104 raise error.HookLoadError( |
104 _('%s hook is invalid: "%s" is not callable') |
105 _(b'%s hook is invalid: "%s" is not callable') |
105 % (hname, funcname) |
106 % (hname, funcname) |
106 ) |
107 ) |
107 |
108 |
108 ui.note(_("calling hook %s: %s\n") % (hname, funcname)) |
109 ui.note(_(b"calling hook %s: %s\n") % (hname, funcname)) |
109 starttime = util.timer() |
110 starttime = util.timer() |
110 |
111 |
111 try: |
112 try: |
112 r = obj(ui=ui, repo=repo, hooktype=htype, **pycompat.strkwargs(args)) |
113 r = obj(ui=ui, repo=repo, hooktype=htype, **pycompat.strkwargs(args)) |
113 except Exception as exc: |
114 except Exception as exc: |
114 if isinstance(exc, error.Abort): |
115 if isinstance(exc, error.Abort): |
115 ui.warn(_('error: %s hook failed: %s\n') % (hname, exc.args[0])) |
116 ui.warn(_(b'error: %s hook failed: %s\n') % (hname, exc.args[0])) |
116 else: |
117 else: |
117 ui.warn( |
118 ui.warn( |
118 _('error: %s hook raised an exception: ' '%s\n') |
119 _(b'error: %s hook raised an exception: ' b'%s\n') |
119 % (hname, stringutil.forcebytestr(exc)) |
120 % (hname, stringutil.forcebytestr(exc)) |
120 ) |
121 ) |
121 if throw: |
122 if throw: |
122 raise |
123 raise |
123 if not ui.tracebackflag: |
124 if not ui.tracebackflag: |
124 ui.warn(_('(run with --traceback for stack trace)\n')) |
125 ui.warn(_(b'(run with --traceback for stack trace)\n')) |
125 ui.traceback() |
126 ui.traceback() |
126 return True, True |
127 return True, True |
127 finally: |
128 finally: |
128 duration = util.timer() - starttime |
129 duration = util.timer() - starttime |
129 ui.log( |
130 ui.log( |
130 'pythonhook', |
131 b'pythonhook', |
131 'pythonhook-%s: %s finished in %0.2f seconds\n', |
132 b'pythonhook-%s: %s finished in %0.2f seconds\n', |
132 htype, |
133 htype, |
133 funcname, |
134 funcname, |
134 duration, |
135 duration, |
135 ) |
136 ) |
136 if r: |
137 if r: |
137 if throw: |
138 if throw: |
138 raise error.HookAbort(_('%s hook failed') % hname) |
139 raise error.HookAbort(_(b'%s hook failed') % hname) |
139 ui.warn(_('warning: %s hook failed\n') % hname) |
140 ui.warn(_(b'warning: %s hook failed\n') % hname) |
140 return r, False |
141 return r, False |
141 |
142 |
142 |
143 |
143 def _exthook(ui, repo, htype, name, cmd, args, throw): |
144 def _exthook(ui, repo, htype, name, cmd, args, throw): |
144 starttime = util.timer() |
145 starttime = util.timer() |
147 # make in-memory changes visible to external process |
148 # make in-memory changes visible to external process |
148 if repo is not None: |
149 if repo is not None: |
149 tr = repo.currenttransaction() |
150 tr = repo.currenttransaction() |
150 repo.dirstate.write(tr) |
151 repo.dirstate.write(tr) |
151 if tr and tr.writepending(): |
152 if tr and tr.writepending(): |
152 env['HG_PENDING'] = repo.root |
153 env[b'HG_PENDING'] = repo.root |
153 env['HG_HOOKTYPE'] = htype |
154 env[b'HG_HOOKTYPE'] = htype |
154 env['HG_HOOKNAME'] = name |
155 env[b'HG_HOOKNAME'] = name |
155 |
156 |
156 for k, v in args.iteritems(): |
157 for k, v in args.iteritems(): |
157 if callable(v): |
158 if callable(v): |
158 v = v() |
159 v = v() |
159 if isinstance(v, (dict, list)): |
160 if isinstance(v, (dict, list)): |
160 v = stringutil.pprint(v) |
161 v = stringutil.pprint(v) |
161 env['HG_' + k.upper()] = v |
162 env[b'HG_' + k.upper()] = v |
162 |
163 |
163 if ui.configbool('hooks', 'tonative.%s' % name, False): |
164 if ui.configbool(b'hooks', b'tonative.%s' % name, False): |
164 oldcmd = cmd |
165 oldcmd = cmd |
165 cmd = procutil.shelltonative(cmd, env) |
166 cmd = procutil.shelltonative(cmd, env) |
166 if cmd != oldcmd: |
167 if cmd != oldcmd: |
167 ui.note(_('converting hook "%s" to native\n') % name) |
168 ui.note(_(b'converting hook "%s" to native\n') % name) |
168 |
169 |
169 ui.note(_("running hook %s: %s\n") % (name, cmd)) |
170 ui.note(_(b"running hook %s: %s\n") % (name, cmd)) |
170 |
171 |
171 if repo: |
172 if repo: |
172 cwd = repo.root |
173 cwd = repo.root |
173 else: |
174 else: |
174 cwd = encoding.getcwd() |
175 cwd = encoding.getcwd() |
175 r = ui.system(cmd, environ=env, cwd=cwd, blockedtag='exthook-%s' % (name,)) |
176 r = ui.system(cmd, environ=env, cwd=cwd, blockedtag=b'exthook-%s' % (name,)) |
176 |
177 |
177 duration = util.timer() - starttime |
178 duration = util.timer() - starttime |
178 ui.log( |
179 ui.log( |
179 'exthook', |
180 b'exthook', |
180 'exthook-%s: %s finished in %0.2f seconds\n', |
181 b'exthook-%s: %s finished in %0.2f seconds\n', |
181 name, |
182 name, |
182 cmd, |
183 cmd, |
183 duration, |
184 duration, |
184 ) |
185 ) |
185 if r: |
186 if r: |
186 desc = procutil.explainexit(r) |
187 desc = procutil.explainexit(r) |
187 if throw: |
188 if throw: |
188 raise error.HookAbort(_('%s hook %s') % (name, desc)) |
189 raise error.HookAbort(_(b'%s hook %s') % (name, desc)) |
189 ui.warn(_('warning: %s hook %s\n') % (name, desc)) |
190 ui.warn(_(b'warning: %s hook %s\n') % (name, desc)) |
190 return r |
191 return r |
191 |
192 |
192 |
193 |
193 # represent an untrusted hook command |
194 # represent an untrusted hook command |
194 _fromuntrusted = object() |
195 _fromuntrusted = object() |
211 |
212 |
212 |
213 |
213 def _hookitems(ui, _untrusted=False): |
214 def _hookitems(ui, _untrusted=False): |
214 """return all hooks items ready to be sorted""" |
215 """return all hooks items ready to be sorted""" |
215 hooks = {} |
216 hooks = {} |
216 for name, cmd in ui.configitems('hooks', untrusted=_untrusted): |
217 for name, cmd in ui.configitems(b'hooks', untrusted=_untrusted): |
217 if name.startswith('priority.') or name.startswith('tonative.'): |
218 if name.startswith(b'priority.') or name.startswith(b'tonative.'): |
218 continue |
219 continue |
219 |
220 |
220 priority = ui.configint('hooks', 'priority.%s' % name, 0) |
221 priority = ui.configint(b'hooks', b'priority.%s' % name, 0) |
221 hooks[name] = (-priority, len(hooks), name, cmd) |
222 hooks[name] = (-priority, len(hooks), name, cmd) |
222 return hooks |
223 return hooks |
223 |
224 |
224 |
225 |
225 _redirect = False |
226 _redirect = False |
233 def hashook(ui, htype): |
234 def hashook(ui, htype): |
234 """return True if a hook is configured for 'htype'""" |
235 """return True if a hook is configured for 'htype'""" |
235 if not ui.callhooks: |
236 if not ui.callhooks: |
236 return False |
237 return False |
237 for hname, cmd in _allhooks(ui): |
238 for hname, cmd in _allhooks(ui): |
238 if hname.split('.')[0] == htype and cmd: |
239 if hname.split(b'.')[0] == htype and cmd: |
239 return True |
240 return True |
240 return False |
241 return False |
241 |
242 |
242 |
243 |
243 def hook(ui, repo, htype, throw=False, **args): |
244 def hook(ui, repo, htype, throw=False, **args): |
244 if not ui.callhooks: |
245 if not ui.callhooks: |
245 return False |
246 return False |
246 |
247 |
247 hooks = [] |
248 hooks = [] |
248 for hname, cmd in _allhooks(ui): |
249 for hname, cmd in _allhooks(ui): |
249 if hname.split('.')[0] == htype and cmd: |
250 if hname.split(b'.')[0] == htype and cmd: |
250 hooks.append((hname, cmd)) |
251 hooks.append((hname, cmd)) |
251 |
252 |
252 res = runhooks(ui, repo, htype, hooks, throw=throw, **args) |
253 res = runhooks(ui, repo, htype, hooks, throw=throw, **args) |
253 r = False |
254 r = False |
254 for hname, cmd in hooks: |
255 for hname, cmd in hooks: |
277 pass |
278 pass |
278 |
279 |
279 if cmd is _fromuntrusted: |
280 if cmd is _fromuntrusted: |
280 if throw: |
281 if throw: |
281 raise error.HookAbort( |
282 raise error.HookAbort( |
282 _('untrusted hook %s not executed') % hname, |
283 _(b'untrusted hook %s not executed') % hname, |
283 hint=_("see 'hg help config.trusted'"), |
284 hint=_(b"see 'hg help config.trusted'"), |
284 ) |
285 ) |
285 ui.warn(_('warning: untrusted hook %s not executed\n') % hname) |
286 ui.warn(_(b'warning: untrusted hook %s not executed\n') % hname) |
286 r = 1 |
287 r = 1 |
287 raised = False |
288 raised = False |
288 elif callable(cmd): |
289 elif callable(cmd): |
289 r, raised = pythonhook(ui, repo, htype, hname, cmd, args, throw) |
290 r, raised = pythonhook(ui, repo, htype, hname, cmd, args, throw) |
290 elif cmd.startswith('python:'): |
291 elif cmd.startswith(b'python:'): |
291 if cmd.count(':') >= 2: |
292 if cmd.count(b':') >= 2: |
292 path, cmd = cmd[7:].rsplit(':', 1) |
293 path, cmd = cmd[7:].rsplit(b':', 1) |
293 path = util.expandpath(path) |
294 path = util.expandpath(path) |
294 if repo: |
295 if repo: |
295 path = os.path.join(repo.root, path) |
296 path = os.path.join(repo.root, path) |
296 try: |
297 try: |
297 mod = extensions.loadpath(path, 'hghook.%s' % hname) |
298 mod = extensions.loadpath(path, b'hghook.%s' % hname) |
298 except Exception: |
299 except Exception: |
299 ui.write(_("loading %s hook failed:\n") % hname) |
300 ui.write(_(b"loading %s hook failed:\n") % hname) |
300 raise |
301 raise |
301 hookfn = getattr(mod, cmd) |
302 hookfn = getattr(mod, cmd) |
302 else: |
303 else: |
303 hookfn = cmd[7:].strip() |
304 hookfn = cmd[7:].strip() |
304 r, raised = pythonhook( |
305 r, raised = pythonhook( |