##// END OF EJS Templates
dirstate: don't write repo.currenttransaction to repo.dirstate if repo...
Sietse Brouwer -
r27228:10695f8f stable
parent child Browse files
Show More
@@ -1,235 +1,236
1 # hook.py - hook support for mercurial
1 # hook.py - hook support for mercurial
2 #
2 #
3 # Copyright 2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import os
10 import os
11 import sys
11 import sys
12 import time
12 import time
13
13
14 from .i18n import _
14 from .i18n import _
15 from . import (
15 from . import (
16 demandimport,
16 demandimport,
17 error,
17 error,
18 extensions,
18 extensions,
19 util,
19 util,
20 )
20 )
21
21
22 def _pythonhook(ui, repo, name, hname, funcname, args, throw):
22 def _pythonhook(ui, repo, name, hname, funcname, args, throw):
23 '''call python hook. hook is callable object, looked up as
23 '''call python hook. hook is callable object, looked up as
24 name in python module. if callable returns "true", hook
24 name in python module. if callable returns "true", hook
25 fails, else passes. if hook raises exception, treated as
25 fails, else passes. if hook raises exception, treated as
26 hook failure. exception propagates if throw is "true".
26 hook failure. exception propagates if throw is "true".
27
27
28 reason for "true" meaning "hook failed" is so that
28 reason for "true" meaning "hook failed" is so that
29 unmodified commands (e.g. mercurial.commands.update) can
29 unmodified commands (e.g. mercurial.commands.update) can
30 be run as hooks without wrappers to convert return values.'''
30 be run as hooks without wrappers to convert return values.'''
31
31
32 if callable(funcname):
32 if callable(funcname):
33 obj = funcname
33 obj = funcname
34 funcname = obj.__module__ + "." + obj.__name__
34 funcname = obj.__module__ + "." + obj.__name__
35 else:
35 else:
36 d = funcname.rfind('.')
36 d = funcname.rfind('.')
37 if d == -1:
37 if d == -1:
38 raise error.HookLoadError(
38 raise error.HookLoadError(
39 _('%s hook is invalid ("%s" not in a module)')
39 _('%s hook is invalid ("%s" not in a module)')
40 % (hname, funcname))
40 % (hname, funcname))
41 modname = funcname[:d]
41 modname = funcname[:d]
42 oldpaths = sys.path
42 oldpaths = sys.path
43 if util.mainfrozen():
43 if util.mainfrozen():
44 # binary installs require sys.path manipulation
44 # binary installs require sys.path manipulation
45 modpath, modfile = os.path.split(modname)
45 modpath, modfile = os.path.split(modname)
46 if modpath and modfile:
46 if modpath and modfile:
47 sys.path = sys.path[:] + [modpath]
47 sys.path = sys.path[:] + [modpath]
48 modname = modfile
48 modname = modfile
49 with demandimport.deactivated():
49 with demandimport.deactivated():
50 try:
50 try:
51 obj = __import__(modname)
51 obj = __import__(modname)
52 except ImportError:
52 except ImportError:
53 e1 = sys.exc_type, sys.exc_value, sys.exc_traceback
53 e1 = sys.exc_type, sys.exc_value, sys.exc_traceback
54 try:
54 try:
55 # extensions are loaded with hgext_ prefix
55 # extensions are loaded with hgext_ prefix
56 obj = __import__("hgext_%s" % modname)
56 obj = __import__("hgext_%s" % modname)
57 except ImportError:
57 except ImportError:
58 e2 = sys.exc_type, sys.exc_value, sys.exc_traceback
58 e2 = sys.exc_type, sys.exc_value, sys.exc_traceback
59 if ui.tracebackflag:
59 if ui.tracebackflag:
60 ui.warn(_('exception from first failed import '
60 ui.warn(_('exception from first failed import '
61 'attempt:\n'))
61 'attempt:\n'))
62 ui.traceback(e1)
62 ui.traceback(e1)
63 if ui.tracebackflag:
63 if ui.tracebackflag:
64 ui.warn(_('exception from second failed import '
64 ui.warn(_('exception from second failed import '
65 'attempt:\n'))
65 'attempt:\n'))
66 ui.traceback(e2)
66 ui.traceback(e2)
67 raise error.HookLoadError(
67 raise error.HookLoadError(
68 _('%s hook is invalid (import of "%s" failed)') %
68 _('%s hook is invalid (import of "%s" failed)') %
69 (hname, modname))
69 (hname, modname))
70 sys.path = oldpaths
70 sys.path = oldpaths
71 try:
71 try:
72 for p in funcname.split('.')[1:]:
72 for p in funcname.split('.')[1:]:
73 obj = getattr(obj, p)
73 obj = getattr(obj, p)
74 except AttributeError:
74 except AttributeError:
75 raise error.HookLoadError(
75 raise error.HookLoadError(
76 _('%s hook is invalid ("%s" is not defined)')
76 _('%s hook is invalid ("%s" is not defined)')
77 % (hname, funcname))
77 % (hname, funcname))
78 if not callable(obj):
78 if not callable(obj):
79 raise error.HookLoadError(
79 raise error.HookLoadError(
80 _('%s hook is invalid ("%s" is not callable)')
80 _('%s hook is invalid ("%s" is not callable)')
81 % (hname, funcname))
81 % (hname, funcname))
82
82
83 ui.note(_("calling hook %s: %s\n") % (hname, funcname))
83 ui.note(_("calling hook %s: %s\n") % (hname, funcname))
84 starttime = time.time()
84 starttime = time.time()
85
85
86 try:
86 try:
87 # redirect IO descriptors to the ui descriptors so hooks
87 # redirect IO descriptors to the ui descriptors so hooks
88 # that write directly to these don't mess up the command
88 # that write directly to these don't mess up the command
89 # protocol when running through the command server
89 # protocol when running through the command server
90 old = sys.stdout, sys.stderr, sys.stdin
90 old = sys.stdout, sys.stderr, sys.stdin
91 sys.stdout, sys.stderr, sys.stdin = ui.fout, ui.ferr, ui.fin
91 sys.stdout, sys.stderr, sys.stdin = ui.fout, ui.ferr, ui.fin
92
92
93 r = obj(ui=ui, repo=repo, hooktype=name, **args)
93 r = obj(ui=ui, repo=repo, hooktype=name, **args)
94 except Exception as exc:
94 except Exception as exc:
95 if isinstance(exc, error.Abort):
95 if isinstance(exc, error.Abort):
96 ui.warn(_('error: %s hook failed: %s\n') %
96 ui.warn(_('error: %s hook failed: %s\n') %
97 (hname, exc.args[0]))
97 (hname, exc.args[0]))
98 else:
98 else:
99 ui.warn(_('error: %s hook raised an exception: '
99 ui.warn(_('error: %s hook raised an exception: '
100 '%s\n') % (hname, exc))
100 '%s\n') % (hname, exc))
101 if throw:
101 if throw:
102 raise
102 raise
103 ui.traceback()
103 ui.traceback()
104 return True, True
104 return True, True
105 finally:
105 finally:
106 sys.stdout, sys.stderr, sys.stdin = old
106 sys.stdout, sys.stderr, sys.stdin = old
107 duration = time.time() - starttime
107 duration = time.time() - starttime
108 ui.log('pythonhook', 'pythonhook-%s: %s finished in %0.2f seconds\n',
108 ui.log('pythonhook', 'pythonhook-%s: %s finished in %0.2f seconds\n',
109 name, funcname, duration)
109 name, funcname, duration)
110 if r:
110 if r:
111 if throw:
111 if throw:
112 raise error.HookAbort(_('%s hook failed') % hname)
112 raise error.HookAbort(_('%s hook failed') % hname)
113 ui.warn(_('warning: %s hook failed\n') % hname)
113 ui.warn(_('warning: %s hook failed\n') % hname)
114 return r, False
114 return r, False
115
115
116 def _exthook(ui, repo, name, cmd, args, throw):
116 def _exthook(ui, repo, name, cmd, args, throw):
117 ui.note(_("running hook %s: %s\n") % (name, cmd))
117 ui.note(_("running hook %s: %s\n") % (name, cmd))
118
118
119 starttime = time.time()
119 starttime = time.time()
120 env = {}
120 env = {}
121
121
122 # make in-memory changes visible to external process
122 # make in-memory changes visible to external process
123 tr = repo.currenttransaction()
123 if repo is not None:
124 repo.dirstate.write(tr)
124 tr = repo.currenttransaction()
125 if tr and tr.writepending():
125 repo.dirstate.write(tr)
126 env['HG_PENDING'] = repo.root
126 if tr and tr.writepending():
127 env['HG_PENDING'] = repo.root
127
128
128 for k, v in args.iteritems():
129 for k, v in args.iteritems():
129 if callable(v):
130 if callable(v):
130 v = v()
131 v = v()
131 if isinstance(v, dict):
132 if isinstance(v, dict):
132 # make the dictionary element order stable across Python
133 # make the dictionary element order stable across Python
133 # implementations
134 # implementations
134 v = ('{' +
135 v = ('{' +
135 ', '.join('%r: %r' % i for i in sorted(v.iteritems())) +
136 ', '.join('%r: %r' % i for i in sorted(v.iteritems())) +
136 '}')
137 '}')
137 env['HG_' + k.upper()] = v
138 env['HG_' + k.upper()] = v
138
139
139 if repo:
140 if repo:
140 cwd = repo.root
141 cwd = repo.root
141 else:
142 else:
142 cwd = os.getcwd()
143 cwd = os.getcwd()
143 r = ui.system(cmd, environ=env, cwd=cwd)
144 r = ui.system(cmd, environ=env, cwd=cwd)
144
145
145 duration = time.time() - starttime
146 duration = time.time() - starttime
146 ui.log('exthook', 'exthook-%s: %s finished in %0.2f seconds\n',
147 ui.log('exthook', 'exthook-%s: %s finished in %0.2f seconds\n',
147 name, cmd, duration)
148 name, cmd, duration)
148 if r:
149 if r:
149 desc, r = util.explainexit(r)
150 desc, r = util.explainexit(r)
150 if throw:
151 if throw:
151 raise error.HookAbort(_('%s hook %s') % (name, desc))
152 raise error.HookAbort(_('%s hook %s') % (name, desc))
152 ui.warn(_('warning: %s hook %s\n') % (name, desc))
153 ui.warn(_('warning: %s hook %s\n') % (name, desc))
153 return r
154 return r
154
155
155 def _allhooks(ui):
156 def _allhooks(ui):
156 hooks = []
157 hooks = []
157 for name, cmd in ui.configitems('hooks'):
158 for name, cmd in ui.configitems('hooks'):
158 if not name.startswith('priority'):
159 if not name.startswith('priority'):
159 priority = ui.configint('hooks', 'priority.%s' % name, 0)
160 priority = ui.configint('hooks', 'priority.%s' % name, 0)
160 hooks.append((-priority, len(hooks), name, cmd))
161 hooks.append((-priority, len(hooks), name, cmd))
161 return [(k, v) for p, o, k, v in sorted(hooks)]
162 return [(k, v) for p, o, k, v in sorted(hooks)]
162
163
163 _redirect = False
164 _redirect = False
164 def redirect(state):
165 def redirect(state):
165 global _redirect
166 global _redirect
166 _redirect = state
167 _redirect = state
167
168
168 def hook(ui, repo, name, throw=False, **args):
169 def hook(ui, repo, name, throw=False, **args):
169 if not ui.callhooks:
170 if not ui.callhooks:
170 return False
171 return False
171
172
172 hooks = []
173 hooks = []
173 for hname, cmd in _allhooks(ui):
174 for hname, cmd in _allhooks(ui):
174 if hname.split('.')[0] == name and cmd:
175 if hname.split('.')[0] == name and cmd:
175 hooks.append((hname, cmd))
176 hooks.append((hname, cmd))
176
177
177 res = runhooks(ui, repo, name, hooks, throw=throw, **args)
178 res = runhooks(ui, repo, name, hooks, throw=throw, **args)
178 r = False
179 r = False
179 for hname, cmd in hooks:
180 for hname, cmd in hooks:
180 r = res[hname][0] or r
181 r = res[hname][0] or r
181 return r
182 return r
182
183
183 def runhooks(ui, repo, name, hooks, throw=False, **args):
184 def runhooks(ui, repo, name, hooks, throw=False, **args):
184 res = {}
185 res = {}
185 oldstdout = -1
186 oldstdout = -1
186
187
187 try:
188 try:
188 for hname, cmd in hooks:
189 for hname, cmd in hooks:
189 if oldstdout == -1 and _redirect:
190 if oldstdout == -1 and _redirect:
190 try:
191 try:
191 stdoutno = sys.__stdout__.fileno()
192 stdoutno = sys.__stdout__.fileno()
192 stderrno = sys.__stderr__.fileno()
193 stderrno = sys.__stderr__.fileno()
193 # temporarily redirect stdout to stderr, if possible
194 # temporarily redirect stdout to stderr, if possible
194 if stdoutno >= 0 and stderrno >= 0:
195 if stdoutno >= 0 and stderrno >= 0:
195 sys.__stdout__.flush()
196 sys.__stdout__.flush()
196 oldstdout = os.dup(stdoutno)
197 oldstdout = os.dup(stdoutno)
197 os.dup2(stderrno, stdoutno)
198 os.dup2(stderrno, stdoutno)
198 except (OSError, AttributeError):
199 except (OSError, AttributeError):
199 # files seem to be bogus, give up on redirecting (WSGI, etc)
200 # files seem to be bogus, give up on redirecting (WSGI, etc)
200 pass
201 pass
201
202
202 if callable(cmd):
203 if callable(cmd):
203 r, raised = _pythonhook(ui, repo, name, hname, cmd, args, throw)
204 r, raised = _pythonhook(ui, repo, name, hname, cmd, args, throw)
204 elif cmd.startswith('python:'):
205 elif cmd.startswith('python:'):
205 if cmd.count(':') >= 2:
206 if cmd.count(':') >= 2:
206 path, cmd = cmd[7:].rsplit(':', 1)
207 path, cmd = cmd[7:].rsplit(':', 1)
207 path = util.expandpath(path)
208 path = util.expandpath(path)
208 if repo:
209 if repo:
209 path = os.path.join(repo.root, path)
210 path = os.path.join(repo.root, path)
210 try:
211 try:
211 mod = extensions.loadpath(path, 'hghook.%s' % hname)
212 mod = extensions.loadpath(path, 'hghook.%s' % hname)
212 except Exception:
213 except Exception:
213 ui.write(_("loading %s hook failed:\n") % hname)
214 ui.write(_("loading %s hook failed:\n") % hname)
214 raise
215 raise
215 hookfn = getattr(mod, cmd)
216 hookfn = getattr(mod, cmd)
216 else:
217 else:
217 hookfn = cmd[7:].strip()
218 hookfn = cmd[7:].strip()
218 r, raised = _pythonhook(ui, repo, name, hname, hookfn, args,
219 r, raised = _pythonhook(ui, repo, name, hname, hookfn, args,
219 throw)
220 throw)
220 else:
221 else:
221 r = _exthook(ui, repo, hname, cmd, args, throw)
222 r = _exthook(ui, repo, hname, cmd, args, throw)
222 raised = False
223 raised = False
223
224
224 res[hname] = r, raised
225 res[hname] = r, raised
225
226
226 # The stderr is fully buffered on Windows when connected to a pipe.
227 # The stderr is fully buffered on Windows when connected to a pipe.
227 # A forcible flush is required to make small stderr data in the
228 # A forcible flush is required to make small stderr data in the
228 # remote side available to the client immediately.
229 # remote side available to the client immediately.
229 sys.stderr.flush()
230 sys.stderr.flush()
230 finally:
231 finally:
231 if _redirect and oldstdout >= 0:
232 if _redirect and oldstdout >= 0:
232 os.dup2(oldstdout, stdoutno)
233 os.dup2(oldstdout, stdoutno)
233 os.close(oldstdout)
234 os.close(oldstdout)
234
235
235 return res
236 return res
@@ -1,717 +1,726
1 commit hooks can see env vars
1 commit hooks can see env vars
2 (and post-transaction one are run unlocked)
2 (and post-transaction one are run unlocked)
3
3
4 $ cat << EOF >> $HGRCPATH
4 $ cat << EOF >> $HGRCPATH
5 > [experimental]
5 > [experimental]
6 > # drop me once bundle2 is the default,
6 > # drop me once bundle2 is the default,
7 > # added to get test change early.
7 > # added to get test change early.
8 > bundle2-exp = True
8 > bundle2-exp = True
9 > EOF
9 > EOF
10
10
11 $ cat > $TESTTMP/txnabort.checkargs.py <<EOF
11 $ cat > $TESTTMP/txnabort.checkargs.py <<EOF
12 > def showargs(ui, repo, hooktype, **kwargs):
12 > def showargs(ui, repo, hooktype, **kwargs):
13 > ui.write('%s python hook: %s\n' % (hooktype, ','.join(sorted(kwargs))))
13 > ui.write('%s python hook: %s\n' % (hooktype, ','.join(sorted(kwargs))))
14 > EOF
14 > EOF
15
15
16 $ hg init a
16 $ hg init a
17 $ cd a
17 $ cd a
18 $ cat > .hg/hgrc <<EOF
18 $ cat > .hg/hgrc <<EOF
19 > [hooks]
19 > [hooks]
20 > commit = sh -c "HG_LOCAL= HG_TAG= printenv.py commit"
20 > commit = sh -c "HG_LOCAL= HG_TAG= printenv.py commit"
21 > commit.b = sh -c "HG_LOCAL= HG_TAG= printenv.py commit.b"
21 > commit.b = sh -c "HG_LOCAL= HG_TAG= printenv.py commit.b"
22 > precommit = sh -c "HG_LOCAL= HG_NODE= HG_TAG= printenv.py precommit"
22 > precommit = sh -c "HG_LOCAL= HG_NODE= HG_TAG= printenv.py precommit"
23 > pretxncommit = sh -c "HG_LOCAL= HG_TAG= printenv.py pretxncommit"
23 > pretxncommit = sh -c "HG_LOCAL= HG_TAG= printenv.py pretxncommit"
24 > pretxncommit.tip = hg -q tip
24 > pretxncommit.tip = hg -q tip
25 > pre-identify = printenv.py pre-identify 1
25 > pre-identify = printenv.py pre-identify 1
26 > pre-cat = printenv.py pre-cat
26 > pre-cat = printenv.py pre-cat
27 > post-cat = printenv.py post-cat
27 > post-cat = printenv.py post-cat
28 > pretxnopen = sh -c "HG_LOCAL= HG_TAG= printenv.py pretxnopen"
28 > pretxnopen = sh -c "HG_LOCAL= HG_TAG= printenv.py pretxnopen"
29 > pretxnclose = sh -c "HG_LOCAL= HG_TAG= printenv.py pretxnclose"
29 > pretxnclose = sh -c "HG_LOCAL= HG_TAG= printenv.py pretxnclose"
30 > txnclose = sh -c "HG_LOCAL= HG_TAG= printenv.py txnclose"
30 > txnclose = sh -c "HG_LOCAL= HG_TAG= printenv.py txnclose"
31 > txnabort.0 = python:$TESTTMP/txnabort.checkargs.py:showargs
31 > txnabort.0 = python:$TESTTMP/txnabort.checkargs.py:showargs
32 > txnabort.1 = sh -c "HG_LOCAL= HG_TAG= printenv.py txnabort"
32 > txnabort.1 = sh -c "HG_LOCAL= HG_TAG= printenv.py txnabort"
33 > txnclose.checklock = sh -c "hg debuglock > /dev/null"
33 > txnclose.checklock = sh -c "hg debuglock > /dev/null"
34 > EOF
34 > EOF
35 $ echo a > a
35 $ echo a > a
36 $ hg add a
36 $ hg add a
37 $ hg commit -m a
37 $ hg commit -m a
38 precommit hook: HG_PARENT1=0000000000000000000000000000000000000000
38 precommit hook: HG_PARENT1=0000000000000000000000000000000000000000
39 pretxnopen hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
39 pretxnopen hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
40 pretxncommit hook: HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PARENT1=0000000000000000000000000000000000000000 HG_PENDING=$TESTTMP/a
40 pretxncommit hook: HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PARENT1=0000000000000000000000000000000000000000 HG_PENDING=$TESTTMP/a
41 0:cb9a9f314b8b
41 0:cb9a9f314b8b
42 pretxnclose hook: HG_PENDING=$TESTTMP/a HG_PHASES_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
42 pretxnclose hook: HG_PENDING=$TESTTMP/a HG_PHASES_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
43 txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
43 txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
44 commit hook: HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PARENT1=0000000000000000000000000000000000000000
44 commit hook: HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PARENT1=0000000000000000000000000000000000000000
45 commit.b hook: HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PARENT1=0000000000000000000000000000000000000000
45 commit.b hook: HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PARENT1=0000000000000000000000000000000000000000
46
46
47 $ hg clone . ../b
47 $ hg clone . ../b
48 updating to branch default
48 updating to branch default
49 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
49 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
50 $ cd ../b
50 $ cd ../b
51
51
52 changegroup hooks can see env vars
52 changegroup hooks can see env vars
53
53
54 $ cat > .hg/hgrc <<EOF
54 $ cat > .hg/hgrc <<EOF
55 > [hooks]
55 > [hooks]
56 > prechangegroup = printenv.py prechangegroup
56 > prechangegroup = printenv.py prechangegroup
57 > changegroup = printenv.py changegroup
57 > changegroup = printenv.py changegroup
58 > incoming = printenv.py incoming
58 > incoming = printenv.py incoming
59 > EOF
59 > EOF
60
60
61 pretxncommit and commit hooks can see both parents of merge
61 pretxncommit and commit hooks can see both parents of merge
62
62
63 $ cd ../a
63 $ cd ../a
64 $ echo b >> a
64 $ echo b >> a
65 $ hg commit -m a1 -d "1 0"
65 $ hg commit -m a1 -d "1 0"
66 precommit hook: HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
66 precommit hook: HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
67 pretxnopen hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
67 pretxnopen hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
68 pretxncommit hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PENDING=$TESTTMP/a
68 pretxncommit hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PENDING=$TESTTMP/a
69 1:ab228980c14d
69 1:ab228980c14d
70 pretxnclose hook: HG_PENDING=$TESTTMP/a HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
70 pretxnclose hook: HG_PENDING=$TESTTMP/a HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
71 txnclose hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
71 txnclose hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
72 commit hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
72 commit hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
73 commit.b hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
73 commit.b hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
74 $ hg update -C 0
74 $ hg update -C 0
75 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
75 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
76 $ echo b > b
76 $ echo b > b
77 $ hg add b
77 $ hg add b
78 $ hg commit -m b -d '1 0'
78 $ hg commit -m b -d '1 0'
79 precommit hook: HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
79 precommit hook: HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
80 pretxnopen hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
80 pretxnopen hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
81 pretxncommit hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PENDING=$TESTTMP/a
81 pretxncommit hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PENDING=$TESTTMP/a
82 2:ee9deb46ab31
82 2:ee9deb46ab31
83 pretxnclose hook: HG_PENDING=$TESTTMP/a HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
83 pretxnclose hook: HG_PENDING=$TESTTMP/a HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
84 txnclose hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
84 txnclose hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
85 commit hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
85 commit hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
86 commit.b hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
86 commit.b hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
87 created new head
87 created new head
88 $ hg merge 1
88 $ hg merge 1
89 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
89 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
90 (branch merge, don't forget to commit)
90 (branch merge, don't forget to commit)
91 $ hg commit -m merge -d '2 0'
91 $ hg commit -m merge -d '2 0'
92 precommit hook: HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd
92 precommit hook: HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd
93 pretxnopen hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
93 pretxnopen hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
94 pretxncommit hook: HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd HG_PENDING=$TESTTMP/a
94 pretxncommit hook: HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd HG_PENDING=$TESTTMP/a
95 3:07f3376c1e65
95 3:07f3376c1e65
96 pretxnclose hook: HG_PENDING=$TESTTMP/a HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
96 pretxnclose hook: HG_PENDING=$TESTTMP/a HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
97 txnclose hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
97 txnclose hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
98 commit hook: HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd
98 commit hook: HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd
99 commit.b hook: HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd
99 commit.b hook: HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd
100
100
101 test generic hooks
101 test generic hooks
102
102
103 $ hg id
103 $ hg id
104 pre-identify hook: HG_ARGS=id HG_OPTS={'bookmarks': None, 'branch': None, 'id': None, 'insecure': None, 'num': None, 'remotecmd': '', 'rev': '', 'ssh': '', 'tags': None} HG_PATS=[]
104 pre-identify hook: HG_ARGS=id HG_OPTS={'bookmarks': None, 'branch': None, 'id': None, 'insecure': None, 'num': None, 'remotecmd': '', 'rev': '', 'ssh': '', 'tags': None} HG_PATS=[]
105 abort: pre-identify hook exited with status 1
105 abort: pre-identify hook exited with status 1
106 [255]
106 [255]
107 $ hg cat b
107 $ hg cat b
108 pre-cat hook: HG_ARGS=cat b HG_OPTS={'decode': None, 'exclude': [], 'include': [], 'output': '', 'rev': ''} HG_PATS=['b']
108 pre-cat hook: HG_ARGS=cat b HG_OPTS={'decode': None, 'exclude': [], 'include': [], 'output': '', 'rev': ''} HG_PATS=['b']
109 b
109 b
110 post-cat hook: HG_ARGS=cat b HG_OPTS={'decode': None, 'exclude': [], 'include': [], 'output': '', 'rev': ''} HG_PATS=['b'] HG_RESULT=0
110 post-cat hook: HG_ARGS=cat b HG_OPTS={'decode': None, 'exclude': [], 'include': [], 'output': '', 'rev': ''} HG_PATS=['b'] HG_RESULT=0
111
111
112 $ cd ../b
112 $ cd ../b
113 $ hg pull ../a
113 $ hg pull ../a
114 pulling from ../a
114 pulling from ../a
115 searching for changes
115 searching for changes
116 prechangegroup hook: HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=file:$TESTTMP/a (glob)
116 prechangegroup hook: HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=file:$TESTTMP/a (glob)
117 adding changesets
117 adding changesets
118 adding manifests
118 adding manifests
119 adding file changes
119 adding file changes
120 added 3 changesets with 2 changes to 2 files
120 added 3 changesets with 2 changes to 2 files
121 changegroup hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=file:$TESTTMP/a (glob)
121 changegroup hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=file:$TESTTMP/a (glob)
122 incoming hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=file:$TESTTMP/a (glob)
122 incoming hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=file:$TESTTMP/a (glob)
123 incoming hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=file:$TESTTMP/a (glob)
123 incoming hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=file:$TESTTMP/a (glob)
124 incoming hook: HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=file:$TESTTMP/a (glob)
124 incoming hook: HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=file:$TESTTMP/a (glob)
125 (run 'hg update' to get a working copy)
125 (run 'hg update' to get a working copy)
126
126
127 tag hooks can see env vars
127 tag hooks can see env vars
128
128
129 $ cd ../a
129 $ cd ../a
130 $ cat >> .hg/hgrc <<EOF
130 $ cat >> .hg/hgrc <<EOF
131 > pretag = printenv.py pretag
131 > pretag = printenv.py pretag
132 > tag = sh -c "HG_PARENT1= HG_PARENT2= printenv.py tag"
132 > tag = sh -c "HG_PARENT1= HG_PARENT2= printenv.py tag"
133 > EOF
133 > EOF
134 $ hg tag -d '3 0' a
134 $ hg tag -d '3 0' a
135 pretag hook: HG_LOCAL=0 HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_TAG=a
135 pretag hook: HG_LOCAL=0 HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_TAG=a
136 precommit hook: HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2
136 precommit hook: HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2
137 pretxnopen hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
137 pretxnopen hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
138 pretxncommit hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PENDING=$TESTTMP/a
138 pretxncommit hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PENDING=$TESTTMP/a
139 4:539e4b31b6dc
139 4:539e4b31b6dc
140 pretxnclose hook: HG_PENDING=$TESTTMP/a HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
140 pretxnclose hook: HG_PENDING=$TESTTMP/a HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
141 tag hook: HG_LOCAL=0 HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_TAG=a
141 tag hook: HG_LOCAL=0 HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_TAG=a
142 txnclose hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
142 txnclose hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
143 commit hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2
143 commit hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2
144 commit.b hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2
144 commit.b hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2
145 $ hg tag -l la
145 $ hg tag -l la
146 pretag hook: HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=la
146 pretag hook: HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=la
147 tag hook: HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=la
147 tag hook: HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=la
148
148
149 pretag hook can forbid tagging
149 pretag hook can forbid tagging
150
150
151 $ echo "pretag.forbid = printenv.py pretag.forbid 1" >> .hg/hgrc
151 $ echo "pretag.forbid = printenv.py pretag.forbid 1" >> .hg/hgrc
152 $ hg tag -d '4 0' fa
152 $ hg tag -d '4 0' fa
153 pretag hook: HG_LOCAL=0 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fa
153 pretag hook: HG_LOCAL=0 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fa
154 pretag.forbid hook: HG_LOCAL=0 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fa
154 pretag.forbid hook: HG_LOCAL=0 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fa
155 abort: pretag.forbid hook exited with status 1
155 abort: pretag.forbid hook exited with status 1
156 [255]
156 [255]
157 $ hg tag -l fla
157 $ hg tag -l fla
158 pretag hook: HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fla
158 pretag hook: HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fla
159 pretag.forbid hook: HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fla
159 pretag.forbid hook: HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fla
160 abort: pretag.forbid hook exited with status 1
160 abort: pretag.forbid hook exited with status 1
161 [255]
161 [255]
162
162
163 pretxncommit hook can see changeset, can roll back txn, changeset no
163 pretxncommit hook can see changeset, can roll back txn, changeset no
164 more there after
164 more there after
165
165
166 $ echo "pretxncommit.forbid0 = hg tip -q" >> .hg/hgrc
166 $ echo "pretxncommit.forbid0 = hg tip -q" >> .hg/hgrc
167 $ echo "pretxncommit.forbid1 = printenv.py pretxncommit.forbid 1" >> .hg/hgrc
167 $ echo "pretxncommit.forbid1 = printenv.py pretxncommit.forbid 1" >> .hg/hgrc
168 $ echo z > z
168 $ echo z > z
169 $ hg add z
169 $ hg add z
170 $ hg -q tip
170 $ hg -q tip
171 4:539e4b31b6dc
171 4:539e4b31b6dc
172 $ hg commit -m 'fail' -d '4 0'
172 $ hg commit -m 'fail' -d '4 0'
173 precommit hook: HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10
173 precommit hook: HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10
174 pretxnopen hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
174 pretxnopen hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
175 pretxncommit hook: HG_NODE=6f611f8018c10e827fee6bd2bc807f937e761567 HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PENDING=$TESTTMP/a
175 pretxncommit hook: HG_NODE=6f611f8018c10e827fee6bd2bc807f937e761567 HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PENDING=$TESTTMP/a
176 5:6f611f8018c1
176 5:6f611f8018c1
177 5:6f611f8018c1
177 5:6f611f8018c1
178 pretxncommit.forbid hook: HG_NODE=6f611f8018c10e827fee6bd2bc807f937e761567 HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PENDING=$TESTTMP/a
178 pretxncommit.forbid hook: HG_NODE=6f611f8018c10e827fee6bd2bc807f937e761567 HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PENDING=$TESTTMP/a
179 transaction abort!
179 transaction abort!
180 txnabort python hook: txnid,txnname
180 txnabort python hook: txnid,txnname
181 txnabort hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
181 txnabort hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
182 rollback completed
182 rollback completed
183 abort: pretxncommit.forbid1 hook exited with status 1
183 abort: pretxncommit.forbid1 hook exited with status 1
184 [255]
184 [255]
185 $ hg -q tip
185 $ hg -q tip
186 4:539e4b31b6dc
186 4:539e4b31b6dc
187
187
188 (Check that no 'changelog.i.a' file were left behind)
188 (Check that no 'changelog.i.a' file were left behind)
189
189
190 $ ls -1 .hg/store/
190 $ ls -1 .hg/store/
191 00changelog.i
191 00changelog.i
192 00manifest.i
192 00manifest.i
193 data
193 data
194 fncache
194 fncache
195 journal.phaseroots
195 journal.phaseroots
196 phaseroots
196 phaseroots
197 undo
197 undo
198 undo.backup.fncache
198 undo.backup.fncache
199 undo.backupfiles
199 undo.backupfiles
200 undo.phaseroots
200 undo.phaseroots
201
201
202
202
203 precommit hook can prevent commit
203 precommit hook can prevent commit
204
204
205 $ echo "precommit.forbid = printenv.py precommit.forbid 1" >> .hg/hgrc
205 $ echo "precommit.forbid = printenv.py precommit.forbid 1" >> .hg/hgrc
206 $ hg commit -m 'fail' -d '4 0'
206 $ hg commit -m 'fail' -d '4 0'
207 precommit hook: HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10
207 precommit hook: HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10
208 precommit.forbid hook: HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10
208 precommit.forbid hook: HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10
209 abort: precommit.forbid hook exited with status 1
209 abort: precommit.forbid hook exited with status 1
210 [255]
210 [255]
211 $ hg -q tip
211 $ hg -q tip
212 4:539e4b31b6dc
212 4:539e4b31b6dc
213
213
214 preupdate hook can prevent update
214 preupdate hook can prevent update
215
215
216 $ echo "preupdate = printenv.py preupdate" >> .hg/hgrc
216 $ echo "preupdate = printenv.py preupdate" >> .hg/hgrc
217 $ hg update 1
217 $ hg update 1
218 preupdate hook: HG_PARENT1=ab228980c14d
218 preupdate hook: HG_PARENT1=ab228980c14d
219 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
219 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
220
220
221 update hook
221 update hook
222
222
223 $ echo "update = printenv.py update" >> .hg/hgrc
223 $ echo "update = printenv.py update" >> .hg/hgrc
224 $ hg update
224 $ hg update
225 preupdate hook: HG_PARENT1=539e4b31b6dc
225 preupdate hook: HG_PARENT1=539e4b31b6dc
226 update hook: HG_ERROR=0 HG_PARENT1=539e4b31b6dc
226 update hook: HG_ERROR=0 HG_PARENT1=539e4b31b6dc
227 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
227 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
228
228
229 pushkey hook
229 pushkey hook
230
230
231 $ echo "pushkey = printenv.py pushkey" >> .hg/hgrc
231 $ echo "pushkey = printenv.py pushkey" >> .hg/hgrc
232 $ cd ../b
232 $ cd ../b
233 $ hg bookmark -r null foo
233 $ hg bookmark -r null foo
234 $ hg push -B foo ../a
234 $ hg push -B foo ../a
235 pushing to ../a
235 pushing to ../a
236 searching for changes
236 searching for changes
237 no changes found
237 no changes found
238 pretxnopen hook: HG_TXNID=TXN:* HG_TXNNAME=push (glob)
238 pretxnopen hook: HG_TXNID=TXN:* HG_TXNNAME=push (glob)
239 pretxnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_PENDING=$TESTTMP/a HG_SOURCE=push HG_TXNID=TXN:* HG_TXNNAME=push HG_URL=push (glob)
239 pretxnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_PENDING=$TESTTMP/a HG_SOURCE=push HG_TXNID=TXN:* HG_TXNNAME=push HG_URL=push (glob)
240 pushkey hook: HG_KEY=foo HG_NAMESPACE=bookmarks HG_NEW=0000000000000000000000000000000000000000 HG_RET=1
240 pushkey hook: HG_KEY=foo HG_NAMESPACE=bookmarks HG_NEW=0000000000000000000000000000000000000000 HG_RET=1
241 txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_SOURCE=push HG_TXNID=TXN:* HG_TXNNAME=push HG_URL=push (glob)
241 txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_SOURCE=push HG_TXNID=TXN:* HG_TXNNAME=push HG_URL=push (glob)
242 exporting bookmark foo
242 exporting bookmark foo
243 [1]
243 [1]
244 $ cd ../a
244 $ cd ../a
245
245
246 listkeys hook
246 listkeys hook
247
247
248 $ echo "listkeys = printenv.py listkeys" >> .hg/hgrc
248 $ echo "listkeys = printenv.py listkeys" >> .hg/hgrc
249 $ hg bookmark -r null bar
249 $ hg bookmark -r null bar
250 pretxnopen hook: HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
250 pretxnopen hook: HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
251 pretxnclose hook: HG_BOOKMARK_MOVED=1 HG_PENDING=$TESTTMP/a HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
251 pretxnclose hook: HG_BOOKMARK_MOVED=1 HG_PENDING=$TESTTMP/a HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
252 txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
252 txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
253 $ cd ../b
253 $ cd ../b
254 $ hg pull -B bar ../a
254 $ hg pull -B bar ../a
255 pulling from ../a
255 pulling from ../a
256 listkeys hook: HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'}
256 listkeys hook: HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'}
257 no changes found
257 no changes found
258 listkeys hook: HG_NAMESPACE=phase HG_VALUES={}
258 listkeys hook: HG_NAMESPACE=phase HG_VALUES={}
259 adding remote bookmark bar
259 adding remote bookmark bar
260 listkeys hook: HG_NAMESPACE=phases HG_VALUES={'cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b': '1', 'publishing': 'True'}
260 listkeys hook: HG_NAMESPACE=phases HG_VALUES={'cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b': '1', 'publishing': 'True'}
261 $ cd ../a
261 $ cd ../a
262
262
263 test that prepushkey can prevent incoming keys
263 test that prepushkey can prevent incoming keys
264
264
265 $ echo "prepushkey = printenv.py prepushkey.forbid 1" >> .hg/hgrc
265 $ echo "prepushkey = printenv.py prepushkey.forbid 1" >> .hg/hgrc
266 $ cd ../b
266 $ cd ../b
267 $ hg bookmark -r null baz
267 $ hg bookmark -r null baz
268 $ hg push -B baz ../a
268 $ hg push -B baz ../a
269 pushing to ../a
269 pushing to ../a
270 searching for changes
270 searching for changes
271 listkeys hook: HG_NAMESPACE=phases HG_VALUES={'cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b': '1', 'publishing': 'True'}
271 listkeys hook: HG_NAMESPACE=phases HG_VALUES={'cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b': '1', 'publishing': 'True'}
272 listkeys hook: HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'}
272 listkeys hook: HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'}
273 no changes found
273 no changes found
274 pretxnopen hook: HG_TXNID=TXN:* HG_TXNNAME=push (glob)
274 pretxnopen hook: HG_TXNID=TXN:* HG_TXNNAME=push (glob)
275 prepushkey.forbid hook: HG_BUNDLE2=1 HG_KEY=baz HG_NAMESPACE=bookmarks HG_NEW=0000000000000000000000000000000000000000 HG_SOURCE=push HG_TXNID=TXN:* HG_URL=push (glob)
275 prepushkey.forbid hook: HG_BUNDLE2=1 HG_KEY=baz HG_NAMESPACE=bookmarks HG_NEW=0000000000000000000000000000000000000000 HG_SOURCE=push HG_TXNID=TXN:* HG_URL=push (glob)
276 pushkey-abort: prepushkey hook exited with status 1
276 pushkey-abort: prepushkey hook exited with status 1
277 abort: exporting bookmark baz failed!
277 abort: exporting bookmark baz failed!
278 [255]
278 [255]
279 $ cd ../a
279 $ cd ../a
280
280
281 test that prelistkeys can prevent listing keys
281 test that prelistkeys can prevent listing keys
282
282
283 $ echo "prelistkeys = printenv.py prelistkeys.forbid 1" >> .hg/hgrc
283 $ echo "prelistkeys = printenv.py prelistkeys.forbid 1" >> .hg/hgrc
284 $ hg bookmark -r null quux
284 $ hg bookmark -r null quux
285 pretxnopen hook: HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
285 pretxnopen hook: HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
286 pretxnclose hook: HG_BOOKMARK_MOVED=1 HG_PENDING=$TESTTMP/a HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
286 pretxnclose hook: HG_BOOKMARK_MOVED=1 HG_PENDING=$TESTTMP/a HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
287 txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
287 txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
288 $ cd ../b
288 $ cd ../b
289 $ hg pull -B quux ../a
289 $ hg pull -B quux ../a
290 pulling from ../a
290 pulling from ../a
291 prelistkeys.forbid hook: HG_NAMESPACE=bookmarks
291 prelistkeys.forbid hook: HG_NAMESPACE=bookmarks
292 abort: prelistkeys hook exited with status 1
292 abort: prelistkeys hook exited with status 1
293 [255]
293 [255]
294 $ cd ../a
294 $ cd ../a
295 $ rm .hg/hgrc
295 $ rm .hg/hgrc
296
296
297 prechangegroup hook can prevent incoming changes
297 prechangegroup hook can prevent incoming changes
298
298
299 $ cd ../b
299 $ cd ../b
300 $ hg -q tip
300 $ hg -q tip
301 3:07f3376c1e65
301 3:07f3376c1e65
302 $ cat > .hg/hgrc <<EOF
302 $ cat > .hg/hgrc <<EOF
303 > [hooks]
303 > [hooks]
304 > prechangegroup.forbid = printenv.py prechangegroup.forbid 1
304 > prechangegroup.forbid = printenv.py prechangegroup.forbid 1
305 > EOF
305 > EOF
306 $ hg pull ../a
306 $ hg pull ../a
307 pulling from ../a
307 pulling from ../a
308 searching for changes
308 searching for changes
309 prechangegroup.forbid hook: HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=file:$TESTTMP/a (glob)
309 prechangegroup.forbid hook: HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=file:$TESTTMP/a (glob)
310 abort: prechangegroup.forbid hook exited with status 1
310 abort: prechangegroup.forbid hook exited with status 1
311 [255]
311 [255]
312
312
313 pretxnchangegroup hook can see incoming changes, can roll back txn,
313 pretxnchangegroup hook can see incoming changes, can roll back txn,
314 incoming changes no longer there after
314 incoming changes no longer there after
315
315
316 $ cat > .hg/hgrc <<EOF
316 $ cat > .hg/hgrc <<EOF
317 > [hooks]
317 > [hooks]
318 > pretxnchangegroup.forbid0 = hg tip -q
318 > pretxnchangegroup.forbid0 = hg tip -q
319 > pretxnchangegroup.forbid1 = printenv.py pretxnchangegroup.forbid 1
319 > pretxnchangegroup.forbid1 = printenv.py pretxnchangegroup.forbid 1
320 > EOF
320 > EOF
321 $ hg pull ../a
321 $ hg pull ../a
322 pulling from ../a
322 pulling from ../a
323 searching for changes
323 searching for changes
324 adding changesets
324 adding changesets
325 adding manifests
325 adding manifests
326 adding file changes
326 adding file changes
327 added 1 changesets with 1 changes to 1 files
327 added 1 changesets with 1 changes to 1 files
328 4:539e4b31b6dc
328 4:539e4b31b6dc
329 pretxnchangegroup.forbid hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PENDING=$TESTTMP/b HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=file:$TESTTMP/a (glob)
329 pretxnchangegroup.forbid hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PENDING=$TESTTMP/b HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=file:$TESTTMP/a (glob)
330 transaction abort!
330 transaction abort!
331 rollback completed
331 rollback completed
332 abort: pretxnchangegroup.forbid1 hook exited with status 1
332 abort: pretxnchangegroup.forbid1 hook exited with status 1
333 [255]
333 [255]
334 $ hg -q tip
334 $ hg -q tip
335 3:07f3376c1e65
335 3:07f3376c1e65
336
336
337 outgoing hooks can see env vars
337 outgoing hooks can see env vars
338
338
339 $ rm .hg/hgrc
339 $ rm .hg/hgrc
340 $ cat > ../a/.hg/hgrc <<EOF
340 $ cat > ../a/.hg/hgrc <<EOF
341 > [hooks]
341 > [hooks]
342 > preoutgoing = printenv.py preoutgoing
342 > preoutgoing = printenv.py preoutgoing
343 > outgoing = printenv.py outgoing
343 > outgoing = printenv.py outgoing
344 > EOF
344 > EOF
345 $ hg pull ../a
345 $ hg pull ../a
346 pulling from ../a
346 pulling from ../a
347 searching for changes
347 searching for changes
348 preoutgoing hook: HG_SOURCE=pull
348 preoutgoing hook: HG_SOURCE=pull
349 outgoing hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_SOURCE=pull
349 outgoing hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_SOURCE=pull
350 adding changesets
350 adding changesets
351 adding manifests
351 adding manifests
352 adding file changes
352 adding file changes
353 added 1 changesets with 1 changes to 1 files
353 added 1 changesets with 1 changes to 1 files
354 adding remote bookmark quux
354 adding remote bookmark quux
355 (run 'hg update' to get a working copy)
355 (run 'hg update' to get a working copy)
356 $ hg rollback
356 $ hg rollback
357 repository tip rolled back to revision 3 (undo pull)
357 repository tip rolled back to revision 3 (undo pull)
358
358
359 preoutgoing hook can prevent outgoing changes
359 preoutgoing hook can prevent outgoing changes
360
360
361 $ echo "preoutgoing.forbid = printenv.py preoutgoing.forbid 1" >> ../a/.hg/hgrc
361 $ echo "preoutgoing.forbid = printenv.py preoutgoing.forbid 1" >> ../a/.hg/hgrc
362 $ hg pull ../a
362 $ hg pull ../a
363 pulling from ../a
363 pulling from ../a
364 searching for changes
364 searching for changes
365 preoutgoing hook: HG_SOURCE=pull
365 preoutgoing hook: HG_SOURCE=pull
366 preoutgoing.forbid hook: HG_SOURCE=pull
366 preoutgoing.forbid hook: HG_SOURCE=pull
367 abort: preoutgoing.forbid hook exited with status 1
367 abort: preoutgoing.forbid hook exited with status 1
368 [255]
368 [255]
369
369
370 outgoing hooks work for local clones
370 outgoing hooks work for local clones
371
371
372 $ cd ..
372 $ cd ..
373 $ cat > a/.hg/hgrc <<EOF
373 $ cat > a/.hg/hgrc <<EOF
374 > [hooks]
374 > [hooks]
375 > preoutgoing = printenv.py preoutgoing
375 > preoutgoing = printenv.py preoutgoing
376 > outgoing = printenv.py outgoing
376 > outgoing = printenv.py outgoing
377 > EOF
377 > EOF
378 $ hg clone a c
378 $ hg clone a c
379 preoutgoing hook: HG_SOURCE=clone
379 preoutgoing hook: HG_SOURCE=clone
380 outgoing hook: HG_NODE=0000000000000000000000000000000000000000 HG_SOURCE=clone
380 outgoing hook: HG_NODE=0000000000000000000000000000000000000000 HG_SOURCE=clone
381 updating to branch default
381 updating to branch default
382 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
382 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
383 $ rm -rf c
383 $ rm -rf c
384
384
385 preoutgoing hook can prevent outgoing changes for local clones
385 preoutgoing hook can prevent outgoing changes for local clones
386
386
387 $ echo "preoutgoing.forbid = printenv.py preoutgoing.forbid 1" >> a/.hg/hgrc
387 $ echo "preoutgoing.forbid = printenv.py preoutgoing.forbid 1" >> a/.hg/hgrc
388 $ hg clone a zzz
388 $ hg clone a zzz
389 preoutgoing hook: HG_SOURCE=clone
389 preoutgoing hook: HG_SOURCE=clone
390 preoutgoing.forbid hook: HG_SOURCE=clone
390 preoutgoing.forbid hook: HG_SOURCE=clone
391 abort: preoutgoing.forbid hook exited with status 1
391 abort: preoutgoing.forbid hook exited with status 1
392 [255]
392 [255]
393
393
394 $ cd "$TESTTMP/b"
394 $ cd "$TESTTMP/b"
395
395
396 $ cat > hooktests.py <<EOF
396 $ cat > hooktests.py <<EOF
397 > from mercurial import error
397 > from mercurial import error
398 >
398 >
399 > uncallable = 0
399 > uncallable = 0
400 >
400 >
401 > def printargs(args):
401 > def printargs(args):
402 > args.pop('ui', None)
402 > args.pop('ui', None)
403 > args.pop('repo', None)
403 > args.pop('repo', None)
404 > a = list(args.items())
404 > a = list(args.items())
405 > a.sort()
405 > a.sort()
406 > print 'hook args:'
406 > print 'hook args:'
407 > for k, v in a:
407 > for k, v in a:
408 > print ' ', k, v
408 > print ' ', k, v
409 >
409 >
410 > def passhook(**args):
410 > def passhook(**args):
411 > printargs(args)
411 > printargs(args)
412 >
412 >
413 > def failhook(**args):
413 > def failhook(**args):
414 > printargs(args)
414 > printargs(args)
415 > return True
415 > return True
416 >
416 >
417 > class LocalException(Exception):
417 > class LocalException(Exception):
418 > pass
418 > pass
419 >
419 >
420 > def raisehook(**args):
420 > def raisehook(**args):
421 > raise LocalException('exception from hook')
421 > raise LocalException('exception from hook')
422 >
422 >
423 > def aborthook(**args):
423 > def aborthook(**args):
424 > raise error.Abort('raise abort from hook')
424 > raise error.Abort('raise abort from hook')
425 >
425 >
426 > def brokenhook(**args):
426 > def brokenhook(**args):
427 > return 1 + {}
427 > return 1 + {}
428 >
428 >
429 > def verbosehook(ui, **args):
429 > def verbosehook(ui, **args):
430 > ui.note('verbose output from hook\n')
430 > ui.note('verbose output from hook\n')
431 >
431 >
432 > def printtags(ui, repo, **args):
432 > def printtags(ui, repo, **args):
433 > print sorted(repo.tags())
433 > print sorted(repo.tags())
434 >
434 >
435 > class container:
435 > class container:
436 > unreachable = 1
436 > unreachable = 1
437 > EOF
437 > EOF
438
438
439 test python hooks
439 test python hooks
440
440
441 #if windows
441 #if windows
442 $ PYTHONPATH="$TESTTMP/b;$PYTHONPATH"
442 $ PYTHONPATH="$TESTTMP/b;$PYTHONPATH"
443 #else
443 #else
444 $ PYTHONPATH="$TESTTMP/b:$PYTHONPATH"
444 $ PYTHONPATH="$TESTTMP/b:$PYTHONPATH"
445 #endif
445 #endif
446 $ export PYTHONPATH
446 $ export PYTHONPATH
447
447
448 $ echo '[hooks]' > ../a/.hg/hgrc
448 $ echo '[hooks]' > ../a/.hg/hgrc
449 $ echo 'preoutgoing.broken = python:hooktests.brokenhook' >> ../a/.hg/hgrc
449 $ echo 'preoutgoing.broken = python:hooktests.brokenhook' >> ../a/.hg/hgrc
450 $ hg pull ../a 2>&1 | grep 'raised an exception'
450 $ hg pull ../a 2>&1 | grep 'raised an exception'
451 error: preoutgoing.broken hook raised an exception: unsupported operand type(s) for +: 'int' and 'dict'
451 error: preoutgoing.broken hook raised an exception: unsupported operand type(s) for +: 'int' and 'dict'
452
452
453 $ echo '[hooks]' > ../a/.hg/hgrc
453 $ echo '[hooks]' > ../a/.hg/hgrc
454 $ echo 'preoutgoing.raise = python:hooktests.raisehook' >> ../a/.hg/hgrc
454 $ echo 'preoutgoing.raise = python:hooktests.raisehook' >> ../a/.hg/hgrc
455 $ hg pull ../a 2>&1 | grep 'raised an exception'
455 $ hg pull ../a 2>&1 | grep 'raised an exception'
456 error: preoutgoing.raise hook raised an exception: exception from hook
456 error: preoutgoing.raise hook raised an exception: exception from hook
457
457
458 $ echo '[hooks]' > ../a/.hg/hgrc
458 $ echo '[hooks]' > ../a/.hg/hgrc
459 $ echo 'preoutgoing.abort = python:hooktests.aborthook' >> ../a/.hg/hgrc
459 $ echo 'preoutgoing.abort = python:hooktests.aborthook' >> ../a/.hg/hgrc
460 $ hg pull ../a
460 $ hg pull ../a
461 pulling from ../a
461 pulling from ../a
462 searching for changes
462 searching for changes
463 error: preoutgoing.abort hook failed: raise abort from hook
463 error: preoutgoing.abort hook failed: raise abort from hook
464 abort: raise abort from hook
464 abort: raise abort from hook
465 [255]
465 [255]
466
466
467 $ echo '[hooks]' > ../a/.hg/hgrc
467 $ echo '[hooks]' > ../a/.hg/hgrc
468 $ echo 'preoutgoing.fail = python:hooktests.failhook' >> ../a/.hg/hgrc
468 $ echo 'preoutgoing.fail = python:hooktests.failhook' >> ../a/.hg/hgrc
469 $ hg pull ../a
469 $ hg pull ../a
470 pulling from ../a
470 pulling from ../a
471 searching for changes
471 searching for changes
472 hook args:
472 hook args:
473 hooktype preoutgoing
473 hooktype preoutgoing
474 source pull
474 source pull
475 abort: preoutgoing.fail hook failed
475 abort: preoutgoing.fail hook failed
476 [255]
476 [255]
477
477
478 $ echo '[hooks]' > ../a/.hg/hgrc
478 $ echo '[hooks]' > ../a/.hg/hgrc
479 $ echo 'preoutgoing.uncallable = python:hooktests.uncallable' >> ../a/.hg/hgrc
479 $ echo 'preoutgoing.uncallable = python:hooktests.uncallable' >> ../a/.hg/hgrc
480 $ hg pull ../a
480 $ hg pull ../a
481 pulling from ../a
481 pulling from ../a
482 searching for changes
482 searching for changes
483 abort: preoutgoing.uncallable hook is invalid ("hooktests.uncallable" is not callable)
483 abort: preoutgoing.uncallable hook is invalid ("hooktests.uncallable" is not callable)
484 [255]
484 [255]
485
485
486 $ echo '[hooks]' > ../a/.hg/hgrc
486 $ echo '[hooks]' > ../a/.hg/hgrc
487 $ echo 'preoutgoing.nohook = python:hooktests.nohook' >> ../a/.hg/hgrc
487 $ echo 'preoutgoing.nohook = python:hooktests.nohook' >> ../a/.hg/hgrc
488 $ hg pull ../a
488 $ hg pull ../a
489 pulling from ../a
489 pulling from ../a
490 searching for changes
490 searching for changes
491 abort: preoutgoing.nohook hook is invalid ("hooktests.nohook" is not defined)
491 abort: preoutgoing.nohook hook is invalid ("hooktests.nohook" is not defined)
492 [255]
492 [255]
493
493
494 $ echo '[hooks]' > ../a/.hg/hgrc
494 $ echo '[hooks]' > ../a/.hg/hgrc
495 $ echo 'preoutgoing.nomodule = python:nomodule' >> ../a/.hg/hgrc
495 $ echo 'preoutgoing.nomodule = python:nomodule' >> ../a/.hg/hgrc
496 $ hg pull ../a
496 $ hg pull ../a
497 pulling from ../a
497 pulling from ../a
498 searching for changes
498 searching for changes
499 abort: preoutgoing.nomodule hook is invalid ("nomodule" not in a module)
499 abort: preoutgoing.nomodule hook is invalid ("nomodule" not in a module)
500 [255]
500 [255]
501
501
502 $ echo '[hooks]' > ../a/.hg/hgrc
502 $ echo '[hooks]' > ../a/.hg/hgrc
503 $ echo 'preoutgoing.badmodule = python:nomodule.nowhere' >> ../a/.hg/hgrc
503 $ echo 'preoutgoing.badmodule = python:nomodule.nowhere' >> ../a/.hg/hgrc
504 $ hg pull ../a
504 $ hg pull ../a
505 pulling from ../a
505 pulling from ../a
506 searching for changes
506 searching for changes
507 abort: preoutgoing.badmodule hook is invalid (import of "nomodule" failed)
507 abort: preoutgoing.badmodule hook is invalid (import of "nomodule" failed)
508 [255]
508 [255]
509
509
510 $ echo '[hooks]' > ../a/.hg/hgrc
510 $ echo '[hooks]' > ../a/.hg/hgrc
511 $ echo 'preoutgoing.unreachable = python:hooktests.container.unreachable' >> ../a/.hg/hgrc
511 $ echo 'preoutgoing.unreachable = python:hooktests.container.unreachable' >> ../a/.hg/hgrc
512 $ hg pull ../a
512 $ hg pull ../a
513 pulling from ../a
513 pulling from ../a
514 searching for changes
514 searching for changes
515 abort: preoutgoing.unreachable hook is invalid (import of "hooktests.container" failed)
515 abort: preoutgoing.unreachable hook is invalid (import of "hooktests.container" failed)
516 [255]
516 [255]
517
517
518 $ echo '[hooks]' > ../a/.hg/hgrc
518 $ echo '[hooks]' > ../a/.hg/hgrc
519 $ echo 'preoutgoing.pass = python:hooktests.passhook' >> ../a/.hg/hgrc
519 $ echo 'preoutgoing.pass = python:hooktests.passhook' >> ../a/.hg/hgrc
520 $ hg pull ../a
520 $ hg pull ../a
521 pulling from ../a
521 pulling from ../a
522 searching for changes
522 searching for changes
523 hook args:
523 hook args:
524 hooktype preoutgoing
524 hooktype preoutgoing
525 source pull
525 source pull
526 adding changesets
526 adding changesets
527 adding manifests
527 adding manifests
528 adding file changes
528 adding file changes
529 added 1 changesets with 1 changes to 1 files
529 added 1 changesets with 1 changes to 1 files
530 adding remote bookmark quux
530 adding remote bookmark quux
531 (run 'hg update' to get a working copy)
531 (run 'hg update' to get a working copy)
532
532
533 make sure --traceback works
533 make sure --traceback works
534
534
535 $ echo '[hooks]' > .hg/hgrc
535 $ echo '[hooks]' > .hg/hgrc
536 $ echo 'commit.abort = python:hooktests.aborthook' >> .hg/hgrc
536 $ echo 'commit.abort = python:hooktests.aborthook' >> .hg/hgrc
537
537
538 $ echo aa > a
538 $ echo aa > a
539 $ hg --traceback commit -d '0 0' -ma 2>&1 | grep '^Traceback'
539 $ hg --traceback commit -d '0 0' -ma 2>&1 | grep '^Traceback'
540 Traceback (most recent call last):
540 Traceback (most recent call last):
541
541
542 $ cd ..
542 $ cd ..
543 $ hg init c
543 $ hg init c
544 $ cd c
544 $ cd c
545
545
546 $ cat > hookext.py <<EOF
546 $ cat > hookext.py <<EOF
547 > def autohook(**args):
547 > def autohook(**args):
548 > print "Automatically installed hook"
548 > print "Automatically installed hook"
549 >
549 >
550 > def reposetup(ui, repo):
550 > def reposetup(ui, repo):
551 > repo.ui.setconfig("hooks", "commit.auto", autohook)
551 > repo.ui.setconfig("hooks", "commit.auto", autohook)
552 > EOF
552 > EOF
553 $ echo '[extensions]' >> .hg/hgrc
553 $ echo '[extensions]' >> .hg/hgrc
554 $ echo 'hookext = hookext.py' >> .hg/hgrc
554 $ echo 'hookext = hookext.py' >> .hg/hgrc
555
555
556 $ touch foo
556 $ touch foo
557 $ hg add foo
557 $ hg add foo
558 $ hg ci -d '0 0' -m 'add foo'
558 $ hg ci -d '0 0' -m 'add foo'
559 Automatically installed hook
559 Automatically installed hook
560 $ echo >> foo
560 $ echo >> foo
561 $ hg ci --debug -d '0 0' -m 'change foo'
561 $ hg ci --debug -d '0 0' -m 'change foo'
562 committing files:
562 committing files:
563 foo
563 foo
564 committing manifest
564 committing manifest
565 committing changelog
565 committing changelog
566 calling hook commit.auto: hgext_hookext.autohook
566 calling hook commit.auto: hgext_hookext.autohook
567 Automatically installed hook
567 Automatically installed hook
568 committed changeset 1:52998019f6252a2b893452765fcb0a47351a5708
568 committed changeset 1:52998019f6252a2b893452765fcb0a47351a5708
569
569
570 $ hg showconfig hooks
570 $ hg showconfig hooks
571 hooks.commit.auto=<function autohook at *> (glob)
571 hooks.commit.auto=<function autohook at *> (glob)
572
572
573 test python hook configured with python:[file]:[hook] syntax
573 test python hook configured with python:[file]:[hook] syntax
574
574
575 $ cd ..
575 $ cd ..
576 $ mkdir d
576 $ mkdir d
577 $ cd d
577 $ cd d
578 $ hg init repo
578 $ hg init repo
579 $ mkdir hooks
579 $ mkdir hooks
580
580
581 $ cd hooks
581 $ cd hooks
582 $ cat > testhooks.py <<EOF
582 $ cat > testhooks.py <<EOF
583 > def testhook(**args):
583 > def testhook(**args):
584 > print 'hook works'
584 > print 'hook works'
585 > EOF
585 > EOF
586 $ echo '[hooks]' > ../repo/.hg/hgrc
586 $ echo '[hooks]' > ../repo/.hg/hgrc
587 $ echo "pre-commit.test = python:`pwd`/testhooks.py:testhook" >> ../repo/.hg/hgrc
587 $ echo "pre-commit.test = python:`pwd`/testhooks.py:testhook" >> ../repo/.hg/hgrc
588
588
589 $ cd ../repo
589 $ cd ../repo
590 $ hg commit -d '0 0'
590 $ hg commit -d '0 0'
591 hook works
591 hook works
592 nothing changed
592 nothing changed
593 [1]
593 [1]
594
594
595 $ echo '[hooks]' > .hg/hgrc
595 $ echo '[hooks]' > .hg/hgrc
596 $ echo "update.ne = python:`pwd`/nonexistent.py:testhook" >> .hg/hgrc
596 $ echo "update.ne = python:`pwd`/nonexistent.py:testhook" >> .hg/hgrc
597 $ echo "pre-identify.npmd = python:`pwd`/:no_python_module_dir" >> .hg/hgrc
597 $ echo "pre-identify.npmd = python:`pwd`/:no_python_module_dir" >> .hg/hgrc
598
598
599 $ hg up null
599 $ hg up null
600 loading update.ne hook failed:
600 loading update.ne hook failed:
601 abort: No such file or directory: $TESTTMP/d/repo/nonexistent.py
601 abort: No such file or directory: $TESTTMP/d/repo/nonexistent.py
602 [255]
602 [255]
603
603
604 $ hg id
604 $ hg id
605 loading pre-identify.npmd hook failed:
605 loading pre-identify.npmd hook failed:
606 abort: No module named repo!
606 abort: No module named repo!
607 [255]
607 [255]
608
608
609 $ cd ../../b
609 $ cd ../../b
610
610
611 make sure --traceback works on hook import failure
611 make sure --traceback works on hook import failure
612
612
613 $ cat > importfail.py <<EOF
613 $ cat > importfail.py <<EOF
614 > import somebogusmodule
614 > import somebogusmodule
615 > # dereference something in the module to force demandimport to load it
615 > # dereference something in the module to force demandimport to load it
616 > somebogusmodule.whatever
616 > somebogusmodule.whatever
617 > EOF
617 > EOF
618
618
619 $ echo '[hooks]' > .hg/hgrc
619 $ echo '[hooks]' > .hg/hgrc
620 $ echo 'precommit.importfail = python:importfail.whatever' >> .hg/hgrc
620 $ echo 'precommit.importfail = python:importfail.whatever' >> .hg/hgrc
621
621
622 $ echo a >> a
622 $ echo a >> a
623 $ hg --traceback commit -ma 2>&1 | egrep -v '^( +File| [a-zA-Z(])'
623 $ hg --traceback commit -ma 2>&1 | egrep -v '^( +File| [a-zA-Z(])'
624 exception from first failed import attempt:
624 exception from first failed import attempt:
625 Traceback (most recent call last):
625 Traceback (most recent call last):
626 ImportError: No module named somebogusmodule
626 ImportError: No module named somebogusmodule
627 exception from second failed import attempt:
627 exception from second failed import attempt:
628 Traceback (most recent call last):
628 Traceback (most recent call last):
629 ImportError: No module named hgext_importfail
629 ImportError: No module named hgext_importfail
630 Traceback (most recent call last):
630 Traceback (most recent call last):
631 HookLoadError: precommit.importfail hook is invalid (import of "importfail" failed)
631 HookLoadError: precommit.importfail hook is invalid (import of "importfail" failed)
632 abort: precommit.importfail hook is invalid (import of "importfail" failed)
632 abort: precommit.importfail hook is invalid (import of "importfail" failed)
633
633
634 Issue1827: Hooks Update & Commit not completely post operation
634 Issue1827: Hooks Update & Commit not completely post operation
635
635
636 commit and update hooks should run after command completion. The largefiles
636 commit and update hooks should run after command completion. The largefiles
637 use demonstrates a recursive wlock, showing the hook doesn't run until the
637 use demonstrates a recursive wlock, showing the hook doesn't run until the
638 final release (and dirstate flush).
638 final release (and dirstate flush).
639
639
640 $ echo '[hooks]' > .hg/hgrc
640 $ echo '[hooks]' > .hg/hgrc
641 $ echo 'commit = hg id' >> .hg/hgrc
641 $ echo 'commit = hg id' >> .hg/hgrc
642 $ echo 'update = hg id' >> .hg/hgrc
642 $ echo 'update = hg id' >> .hg/hgrc
643 $ echo bb > a
643 $ echo bb > a
644 $ hg ci -ma
644 $ hg ci -ma
645 223eafe2750c tip
645 223eafe2750c tip
646 $ hg up 0 --config extensions.largefiles=
646 $ hg up 0 --config extensions.largefiles=
647 cb9a9f314b8b
647 cb9a9f314b8b
648 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
648 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
649
649
650 make sure --verbose (and --quiet/--debug etc.) are propagated to the local ui
650 make sure --verbose (and --quiet/--debug etc.) are propagated to the local ui
651 that is passed to pre/post hooks
651 that is passed to pre/post hooks
652
652
653 $ echo '[hooks]' > .hg/hgrc
653 $ echo '[hooks]' > .hg/hgrc
654 $ echo 'pre-identify = python:hooktests.verbosehook' >> .hg/hgrc
654 $ echo 'pre-identify = python:hooktests.verbosehook' >> .hg/hgrc
655 $ hg id
655 $ hg id
656 cb9a9f314b8b
656 cb9a9f314b8b
657 $ hg id --verbose
657 $ hg id --verbose
658 calling hook pre-identify: hooktests.verbosehook
658 calling hook pre-identify: hooktests.verbosehook
659 verbose output from hook
659 verbose output from hook
660 cb9a9f314b8b
660 cb9a9f314b8b
661
661
662 Ensure hooks can be prioritized
662 Ensure hooks can be prioritized
663
663
664 $ echo '[hooks]' > .hg/hgrc
664 $ echo '[hooks]' > .hg/hgrc
665 $ echo 'pre-identify.a = python:hooktests.verbosehook' >> .hg/hgrc
665 $ echo 'pre-identify.a = python:hooktests.verbosehook' >> .hg/hgrc
666 $ echo 'pre-identify.b = python:hooktests.verbosehook' >> .hg/hgrc
666 $ echo 'pre-identify.b = python:hooktests.verbosehook' >> .hg/hgrc
667 $ echo 'priority.pre-identify.b = 1' >> .hg/hgrc
667 $ echo 'priority.pre-identify.b = 1' >> .hg/hgrc
668 $ echo 'pre-identify.c = python:hooktests.verbosehook' >> .hg/hgrc
668 $ echo 'pre-identify.c = python:hooktests.verbosehook' >> .hg/hgrc
669 $ hg id --verbose
669 $ hg id --verbose
670 calling hook pre-identify.b: hooktests.verbosehook
670 calling hook pre-identify.b: hooktests.verbosehook
671 verbose output from hook
671 verbose output from hook
672 calling hook pre-identify.a: hooktests.verbosehook
672 calling hook pre-identify.a: hooktests.verbosehook
673 verbose output from hook
673 verbose output from hook
674 calling hook pre-identify.c: hooktests.verbosehook
674 calling hook pre-identify.c: hooktests.verbosehook
675 verbose output from hook
675 verbose output from hook
676 cb9a9f314b8b
676 cb9a9f314b8b
677
677
678 new tags must be visible in pretxncommit (issue3210)
678 new tags must be visible in pretxncommit (issue3210)
679
679
680 $ echo 'pretxncommit.printtags = python:hooktests.printtags' >> .hg/hgrc
680 $ echo 'pretxncommit.printtags = python:hooktests.printtags' >> .hg/hgrc
681 $ hg tag -f foo
681 $ hg tag -f foo
682 ['a', 'foo', 'tip']
682 ['a', 'foo', 'tip']
683
683
684 post-init hooks must not crash (issue4983)
685 This also creates the `to` repo for the next test block.
686
687 $ cd ..
688 $ cat << EOF >> hgrc-with-post-init-hook
689 > [hooks]
690 > post-init = printenv.py post-init
691 > EOF
692 $ HGRCPATH=hgrc-with-post-init-hook hg init to
693 post-init hook: HG_ARGS=init to HG_OPTS={'insecure': None, 'remotecmd': '', 'ssh': ''} HG_PATS=['to'] HG_RESULT=0
694
684 new commits must be visible in pretxnchangegroup (issue3428)
695 new commits must be visible in pretxnchangegroup (issue3428)
685
696
686 $ cd ..
687 $ hg init to
688 $ echo '[hooks]' >> to/.hg/hgrc
697 $ echo '[hooks]' >> to/.hg/hgrc
689 $ echo 'prechangegroup = hg --traceback tip' >> to/.hg/hgrc
698 $ echo 'prechangegroup = hg --traceback tip' >> to/.hg/hgrc
690 $ echo 'pretxnchangegroup = hg --traceback tip' >> to/.hg/hgrc
699 $ echo 'pretxnchangegroup = hg --traceback tip' >> to/.hg/hgrc
691 $ echo a >> to/a
700 $ echo a >> to/a
692 $ hg --cwd to ci -Ama
701 $ hg --cwd to ci -Ama
693 adding a
702 adding a
694 $ hg clone to from
703 $ hg clone to from
695 updating to branch default
704 updating to branch default
696 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
705 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
697 $ echo aa >> from/a
706 $ echo aa >> from/a
698 $ hg --cwd from ci -mb
707 $ hg --cwd from ci -mb
699 $ hg --cwd from push
708 $ hg --cwd from push
700 pushing to $TESTTMP/to (glob)
709 pushing to $TESTTMP/to (glob)
701 searching for changes
710 searching for changes
702 changeset: 0:cb9a9f314b8b
711 changeset: 0:cb9a9f314b8b
703 tag: tip
712 tag: tip
704 user: test
713 user: test
705 date: Thu Jan 01 00:00:00 1970 +0000
714 date: Thu Jan 01 00:00:00 1970 +0000
706 summary: a
715 summary: a
707
716
708 adding changesets
717 adding changesets
709 adding manifests
718 adding manifests
710 adding file changes
719 adding file changes
711 added 1 changesets with 1 changes to 1 files
720 added 1 changesets with 1 changes to 1 files
712 changeset: 1:9836a07b9b9d
721 changeset: 1:9836a07b9b9d
713 tag: tip
722 tag: tip
714 user: test
723 user: test
715 date: Thu Jan 01 00:00:00 1970 +0000
724 date: Thu Jan 01 00:00:00 1970 +0000
716 summary: b
725 summary: b
717
726
General Comments 0
You need to be logged in to leave comments. Login now