##// END OF EJS Templates
hook.py: fix redirections introduced by 323b9c55b328...
Alexis S. L. Carvalho -
r6266:9f76df0e default
parent child Browse files
Show More
@@ -1,113 +1,115
1 1 # hook.py - hook support for mercurial
2 2 #
3 3 # Copyright 2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms
6 6 # of the GNU General Public License, incorporated herein by reference.
7 7
8 8 from i18n import _
9 9 import util, os, sys
10 10
11 11 def _pythonhook(ui, repo, name, hname, funcname, args, throw):
12 12 '''call python hook. hook is callable object, looked up as
13 13 name in python module. if callable returns "true", hook
14 14 fails, else passes. if hook raises exception, treated as
15 15 hook failure. exception propagates if throw is "true".
16 16
17 17 reason for "true" meaning "hook failed" is so that
18 18 unmodified commands (e.g. mercurial.commands.update) can
19 19 be run as hooks without wrappers to convert return values.'''
20 20
21 21 ui.note(_("calling hook %s: %s\n") % (hname, funcname))
22 22 obj = funcname
23 23 if not callable(obj):
24 24 d = funcname.rfind('.')
25 25 if d == -1:
26 26 raise util.Abort(_('%s hook is invalid ("%s" not in '
27 27 'a module)') % (hname, funcname))
28 28 modname = funcname[:d]
29 29 try:
30 30 obj = __import__(modname)
31 31 except ImportError:
32 32 try:
33 33 # extensions are loaded with hgext_ prefix
34 34 obj = __import__("hgext_%s" % modname)
35 35 except ImportError:
36 36 raise util.Abort(_('%s hook is invalid '
37 37 '(import of "%s" failed)') %
38 38 (hname, modname))
39 39 try:
40 40 for p in funcname.split('.')[1:]:
41 41 obj = getattr(obj, p)
42 42 except AttributeError, err:
43 43 raise util.Abort(_('%s hook is invalid '
44 44 '("%s" is not defined)') %
45 45 (hname, funcname))
46 46 if not callable(obj):
47 47 raise util.Abort(_('%s hook is invalid '
48 48 '("%s" is not callable)') %
49 49 (hname, funcname))
50 50 try:
51 51 r = obj(ui=ui, repo=repo, hooktype=name, **args)
52 52 except (KeyboardInterrupt, util.SignalInterrupt):
53 53 raise
54 54 except Exception, exc:
55 55 if isinstance(exc, util.Abort):
56 56 ui.warn(_('error: %s hook failed: %s\n') %
57 57 (hname, exc.args[0]))
58 58 else:
59 59 ui.warn(_('error: %s hook raised an exception: '
60 60 '%s\n') % (hname, exc))
61 61 if throw:
62 62 raise
63 63 ui.print_exc()
64 64 return True
65 65 if r:
66 66 if throw:
67 67 raise util.Abort(_('%s hook failed') % hname)
68 68 ui.warn(_('warning: %s hook failed\n') % hname)
69 69 return r
70 70
71 71 def _exthook(ui, repo, name, cmd, args, throw):
72 72 ui.note(_("running hook %s: %s\n") % (name, cmd))
73 73 env = dict([('HG_' + k.upper(), v) for k, v in args.iteritems()])
74 74 if repo:
75 75 cwd = repo.root
76 76 else:
77 77 cwd = os.getcwd()
78 78 r = util.system(cmd, environ=env, cwd=cwd)
79 79 if r:
80 80 desc, r = util.explain_exit(r)
81 81 if throw:
82 82 raise util.Abort(_('%s hook %s') % (name, desc))
83 83 ui.warn(_('warning: %s hook %s\n') % (name, desc))
84 84 return r
85 85
86 86 _redirect = False
87 87 def redirect(state):
88 global _redirect
88 89 _redirect = state
89 90
90 91 def hook(ui, repo, name, throw=False, **args):
91 92 r = False
92 93
93 94 if _redirect:
94 95 # temporarily redirect stdout to stderr
95 oldstdout = os.dup(sys.stdout.fileno())
96 os.dup2(sys.stderr.fileno(), sys.stdout.fileno())
96 oldstdout = os.dup(sys.__stdout__.fileno())
97 os.dup2(sys.__stderr__.fileno(), sys.__stdout__.fileno())
97 98
98 99 hooks = [(hname, cmd) for hname, cmd in ui.configitems("hooks")
99 100 if hname.split(".", 1)[0] == name and cmd]
100 101 hooks.sort()
101 102 for hname, cmd in hooks:
102 103 if callable(cmd):
103 104 r = _pythonhook(ui, repo, name, hname, cmd, args, throw) or r
104 105 elif cmd.startswith('python:'):
105 106 r = _pythonhook(ui, repo, name, hname, cmd[7:].strip(),
106 107 args, throw) or r
107 108 else:
108 109 r = _exthook(ui, repo, hname, cmd, args, throw) or r
109 return r
110 110
111 111 if _redirect:
112 os.dup2(oldstdout, sys.stdout.fileno())
112 os.dup2(oldstdout, sys.__stdout__.fileno())
113 113 os.close(oldstdout)
114
115 return r
@@ -1,111 +1,111
1 1 #!/bin/sh
2 2
3 3 cp "$TESTDIR"/printenv.py .
4 4
5 5 # This test tries to exercise the ssh functionality with a dummy script
6 6
7 7 cat <<EOF > dummyssh
8 8 import sys
9 9 import os
10 10
11 11 os.chdir(os.path.dirname(sys.argv[0]))
12 12 if sys.argv[1] != "user@dummy":
13 13 sys.exit(-1)
14 14
15 15 if not os.path.exists("dummyssh"):
16 16 sys.exit(-1)
17 17
18 18 os.environ["SSH_CLIENT"] = "127.0.0.1 1 2"
19 19
20 20 log = open("dummylog", "ab")
21 21 log.write("Got arguments")
22 22 for i, arg in enumerate(sys.argv[1:]):
23 23 log.write(" %d:%s" % (i+1, arg))
24 24 log.write("\n")
25 25 log.close()
26 26 r = os.system(sys.argv[2])
27 27 sys.exit(bool(r))
28 28 EOF
29 29
30 30 cat <<EOF > badhook
31 31 import sys
32 sys.stdout.write("KABOOM")
32 sys.stdout.write("KABOOM\n")
33 33 EOF
34 34
35 35 echo "# creating 'remote'"
36 36 hg init remote
37 37 cd remote
38 38 echo this > foo
39 39 echo this > fooO
40 40 hg ci -A -m "init" -d "1000000 0" foo fooO
41 41 echo '[server]' > .hg/hgrc
42 42 echo 'uncompressed = True' >> .hg/hgrc
43 43 echo '[hooks]' >> .hg/hgrc
44 44 echo 'changegroup = python ../printenv.py changegroup-in-remote 0 ../dummylog' >> .hg/hgrc
45 45
46 46 cd ..
47 47
48 48 echo "# repo not found error"
49 49 hg clone -e "python ./dummyssh" ssh://user@dummy/nonexistent local
50 50
51 51 echo "# clone remote via stream"
52 52 hg clone -e "python ./dummyssh" --uncompressed ssh://user@dummy/remote local-stream 2>&1 | \
53 53 sed -e 's/[0-9][0-9.]*/XXX/g' -e 's/[KM]\(B\/sec\)/X\1/'
54 54 cd local-stream
55 55 hg verify
56 56 cd ..
57 57
58 58 echo "# clone remote via pull"
59 59 hg clone -e "python ./dummyssh" ssh://user@dummy/remote local
60 60
61 61 echo "# verify"
62 62 cd local
63 63 hg verify
64 64
65 65 echo '[hooks]' >> .hg/hgrc
66 66 echo 'changegroup = python ../printenv.py changegroup-in-local 0 ../dummylog' >> .hg/hgrc
67 67
68 68 echo "# empty default pull"
69 69 hg paths
70 70 hg pull -e "python ../dummyssh"
71 71
72 72 echo "# local change"
73 73 echo bleah > foo
74 74 hg ci -m "add" -d "1000000 0"
75 75
76 76 echo "# updating rc"
77 77 echo "default-push = ssh://user@dummy/remote" >> .hg/hgrc
78 78 echo "[ui]" >> .hg/hgrc
79 79 echo "ssh = python ../dummyssh" >> .hg/hgrc
80 80
81 81 echo "# find outgoing"
82 82 hg out ssh://user@dummy/remote
83 83
84 84 echo "# find incoming on the remote side"
85 85 hg incoming -R ../remote -e "python ../dummyssh" ssh://user@dummy/local
86 86
87 87 echo "# push"
88 88 hg push
89 89
90 90 cd ../remote
91 91
92 92 echo "# check remote tip"
93 93 hg tip
94 94 hg verify
95 95 hg cat -r tip foo
96 96
97 97 echo z > z
98 98 hg ci -A -m z -d '1000001 0' z
99 99 # a bad, evil hook that prints to stdout
100 100 echo 'changegroup.stdout = python ../badhook' >> .hg/hgrc
101 101
102 102 cd ../local
103 103 echo r > r
104 104 hg ci -A -m z -d '1000002 0' r
105 105
106 106 echo "# push should succeed even though it has an unexpected response"
107 107 hg push
108 108 hg -R ../remote heads
109 109
110 110 cd ..
111 111 cat dummylog
@@ -1,105 +1,104
1 1 # creating 'remote'
2 2 # repo not found error
3 3 remote: abort: There is no Mercurial repository here (.hg not found)!
4 4 abort: no suitable response from remote hg!
5 5 # clone remote via stream
6 6 streaming all changes
7 7 XXX files to transfer, XXX bytes of data
8 8 transferred XXX bytes in XXX seconds (XXX XB/sec)
9 9 XXX files updated, XXX files merged, XXX files removed, XXX files unresolved
10 10 checking changesets
11 11 checking manifests
12 12 crosschecking files in changesets and manifests
13 13 checking files
14 14 2 files, 1 changesets, 2 total revisions
15 15 # clone remote via pull
16 16 requesting all changes
17 17 adding changesets
18 18 adding manifests
19 19 adding file changes
20 20 added 1 changesets with 2 changes to 2 files
21 21 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
22 22 # verify
23 23 checking changesets
24 24 checking manifests
25 25 crosschecking files in changesets and manifests
26 26 checking files
27 27 2 files, 1 changesets, 2 total revisions
28 28 # empty default pull
29 29 default = ssh://user@dummy/remote
30 30 pulling from ssh://user@dummy/remote
31 31 searching for changes
32 32 no changes found
33 33 # local change
34 34 # updating rc
35 35 # find outgoing
36 36 comparing with ssh://user@dummy/remote
37 37 searching for changes
38 38 changeset: 1:572896fe480d
39 39 tag: tip
40 40 user: test
41 41 date: Mon Jan 12 13:46:40 1970 +0000
42 42 summary: add
43 43
44 44 # find incoming on the remote side
45 45 comparing with ssh://user@dummy/local
46 46 searching for changes
47 47 changeset: 1:572896fe480d
48 48 tag: tip
49 49 user: test
50 50 date: Mon Jan 12 13:46:40 1970 +0000
51 51 summary: add
52 52
53 53 # push
54 54 pushing to ssh://user@dummy/remote
55 55 searching for changes
56 56 remote: adding changesets
57 57 remote: adding manifests
58 58 remote: adding file changes
59 59 remote: added 1 changesets with 1 changes to 1 files
60 60 # check remote tip
61 61 changeset: 1:572896fe480d
62 62 tag: tip
63 63 user: test
64 64 date: Mon Jan 12 13:46:40 1970 +0000
65 65 summary: add
66 66
67 67 checking changesets
68 68 checking manifests
69 69 crosschecking files in changesets and manifests
70 70 checking files
71 71 2 files, 2 changesets, 3 total revisions
72 72 bleah
73 73 # push should succeed even though it has an unexpected response
74 74 pushing to ssh://user@dummy/remote
75 75 searching for changes
76 76 note: unsynced remote changes!
77 77 remote: adding changesets
78 78 remote: adding manifests
79 79 remote: adding file changes
80 80 remote: added 1 changesets with 1 changes to 1 files
81 abort: unexpected response:
82 'KABOOM1\n'
81 remote: KABOOM
83 82 changeset: 3:ac7448082955
84 83 tag: tip
85 84 parent: 1:572896fe480d
86 85 user: test
87 86 date: Mon Jan 12 13:46:42 1970 +0000
88 87 summary: z
89 88
90 89 changeset: 2:187c6caa0d1e
91 90 parent: 0:e34318c26897
92 91 user: test
93 92 date: Mon Jan 12 13:46:41 1970 +0000
94 93 summary: z
95 94
96 95 Got arguments 1:user@dummy 2:hg -R nonexistent serve --stdio
97 96 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
98 97 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
99 98 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
100 99 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
101 100 Got arguments 1:user@dummy 2:hg -R local serve --stdio
102 101 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
103 102 changegroup-in-remote hook: HG_NODE=572896fe480d7581849806ee402175c49cb20037 HG_SOURCE=serve HG_URL=remote:ssh:127.0.0.1
104 103 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
105 104 changegroup-in-remote hook: HG_NODE=ac7448082955a0b2ff5cb4512c1e061c779bbc79 HG_SOURCE=serve HG_URL=remote:ssh:127.0.0.1
General Comments 0
You need to be logged in to leave comments. Login now