##// END OF EJS Templates
Add (pre)outgoing hooks for local clones.
Fred Wulff -
r8907:e9ef409e default
parent child Browse files
Show More
@@ -1,362 +1,363
1 1 # hg.py - repository classes for mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
5 5 #
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2, incorporated herein by reference.
8 8
9 9 from i18n import _
10 10 from lock import release
11 11 import localrepo, bundlerepo, httprepo, sshrepo, statichttprepo
12 12 import lock, util, extensions, error
13 13 import merge as _merge
14 14 import verify as _verify
15 15 import errno, os, shutil
16 16
17 17 def _local(path):
18 18 return (os.path.isfile(util.drop_scheme('file', path)) and
19 19 bundlerepo or localrepo)
20 20
21 21 def parseurl(url, revs=[]):
22 22 '''parse url#branch, returning url, branch + revs'''
23 23
24 24 if '#' not in url:
25 25 return url, (revs or None), revs and revs[-1] or None
26 26
27 27 url, branch = url.split('#', 1)
28 28 checkout = revs and revs[-1] or branch
29 29 return url, (revs or []) + [branch], checkout
30 30
31 31 schemes = {
32 32 'bundle': bundlerepo,
33 33 'file': _local,
34 34 'http': httprepo,
35 35 'https': httprepo,
36 36 'ssh': sshrepo,
37 37 'static-http': statichttprepo,
38 38 }
39 39
40 40 def _lookup(path):
41 41 scheme = 'file'
42 42 if path:
43 43 c = path.find(':')
44 44 if c > 0:
45 45 scheme = path[:c]
46 46 thing = schemes.get(scheme) or schemes['file']
47 47 try:
48 48 return thing(path)
49 49 except TypeError:
50 50 return thing
51 51
52 52 def islocal(repo):
53 53 '''return true if repo or path is local'''
54 54 if isinstance(repo, str):
55 55 try:
56 56 return _lookup(repo).islocal(repo)
57 57 except AttributeError:
58 58 return False
59 59 return repo.local()
60 60
61 61 def repository(ui, path='', create=False):
62 62 """return a repository object for the specified path"""
63 63 repo = _lookup(path).instance(ui, path, create)
64 64 ui = getattr(repo, "ui", ui)
65 65 for name, module in extensions.extensions():
66 66 hook = getattr(module, 'reposetup', None)
67 67 if hook:
68 68 hook(ui, repo)
69 69 return repo
70 70
71 71 def defaultdest(source):
72 72 '''return default destination of clone if none is given'''
73 73 return os.path.basename(os.path.normpath(source))
74 74
75 75 def localpath(path):
76 76 if path.startswith('file://localhost/'):
77 77 return path[16:]
78 78 if path.startswith('file://'):
79 79 return path[7:]
80 80 if path.startswith('file:'):
81 81 return path[5:]
82 82 return path
83 83
84 84 def share(ui, source, dest=None, update=True):
85 85 '''create a shared repository'''
86 86
87 87 if not islocal(source):
88 88 raise util.Abort(_('can only share local repositories'))
89 89
90 90 if not dest:
91 91 dest = os.path.basename(source)
92 92
93 93 if isinstance(source, str):
94 94 origsource = ui.expandpath(source)
95 95 source, rev, checkout = parseurl(origsource, '')
96 96 srcrepo = repository(ui, source)
97 97 else:
98 98 srcrepo = source
99 99 origsource = source = srcrepo.url()
100 100 checkout = None
101 101
102 102 sharedpath = srcrepo.sharedpath # if our source is already sharing
103 103
104 104 root = os.path.realpath(dest)
105 105 roothg = os.path.join(root, '.hg')
106 106
107 107 if os.path.exists(roothg):
108 108 raise util.Abort(_('destination already exists'))
109 109
110 110 if not os.path.isdir(root):
111 111 os.mkdir(root)
112 112 os.mkdir(roothg)
113 113
114 114 requirements = ''
115 115 try:
116 116 requirements = srcrepo.opener('requires').read()
117 117 except IOError, inst:
118 118 if inst.errno != errno.ENOENT:
119 119 raise
120 120
121 121 requirements += 'shared\n'
122 122 file(os.path.join(roothg, 'requires'), 'w').write(requirements)
123 123 file(os.path.join(roothg, 'sharedpath'), 'w').write(sharedpath)
124 124
125 125 default = srcrepo.ui.config('paths', 'default')
126 126 if default:
127 127 f = file(os.path.join(roothg, 'hgrc'), 'w')
128 128 f.write('[paths]\ndefault = %s\n' % default)
129 129 f.close()
130 130
131 131 r = repository(ui, root)
132 132
133 133 if update:
134 134 r.ui.status(_("updating working directory\n"))
135 135 if update is not True:
136 136 checkout = update
137 137 for test in (checkout, 'default', 'tip'):
138 138 try:
139 139 uprev = r.lookup(test)
140 140 break
141 141 except:
142 142 continue
143 143 _update(r, uprev)
144 144
145 145 def clone(ui, source, dest=None, pull=False, rev=None, update=True,
146 146 stream=False):
147 147 """Make a copy of an existing repository.
148 148
149 149 Create a copy of an existing repository in a new directory. The
150 150 source and destination are URLs, as passed to the repository
151 151 function. Returns a pair of repository objects, the source and
152 152 newly created destination.
153 153
154 154 The location of the source is added to the new repository's
155 155 .hg/hgrc file, as the default to be used for future pulls and
156 156 pushes.
157 157
158 158 If an exception is raised, the partly cloned/updated destination
159 159 repository will be deleted.
160 160
161 161 Arguments:
162 162
163 163 source: repository object or URL
164 164
165 165 dest: URL of destination repository to create (defaults to base
166 166 name of source repository)
167 167
168 168 pull: always pull from source repository, even in local case
169 169
170 170 stream: stream raw data uncompressed from repository (fast over
171 171 LAN, slow over WAN)
172 172
173 173 rev: revision to clone up to (implies pull=True)
174 174
175 175 update: update working directory after clone completes, if
176 176 destination is local repository (True means update to default rev,
177 177 anything else is treated as a revision)
178 178 """
179 179
180 180 if isinstance(source, str):
181 181 origsource = ui.expandpath(source)
182 182 source, rev, checkout = parseurl(origsource, rev)
183 183 src_repo = repository(ui, source)
184 184 else:
185 185 src_repo = source
186 186 origsource = source = src_repo.url()
187 187 checkout = rev and rev[-1] or None
188 188
189 189 if dest is None:
190 190 dest = defaultdest(source)
191 191 ui.status(_("destination directory: %s\n") % dest)
192 192
193 193 dest = localpath(dest)
194 194 source = localpath(source)
195 195
196 196 if os.path.exists(dest):
197 197 if not os.path.isdir(dest):
198 198 raise util.Abort(_("destination '%s' already exists") % dest)
199 199 elif os.listdir(dest):
200 200 raise util.Abort(_("destination '%s' is not empty") % dest)
201 201
202 202 class DirCleanup(object):
203 203 def __init__(self, dir_):
204 204 self.rmtree = shutil.rmtree
205 205 self.dir_ = dir_
206 206 def close(self):
207 207 self.dir_ = None
208 208 def cleanup(self):
209 209 if self.dir_:
210 210 self.rmtree(self.dir_, True)
211 211
212 212 src_lock = dest_lock = dir_cleanup = None
213 213 try:
214 214 if islocal(dest):
215 215 dir_cleanup = DirCleanup(dest)
216 216
217 217 abspath = origsource
218 218 copy = False
219 219 if src_repo.cancopy() and islocal(dest):
220 220 abspath = os.path.abspath(util.drop_scheme('file', origsource))
221 221 copy = not pull and not rev
222 222
223 223 if copy:
224 224 try:
225 225 # we use a lock here because if we race with commit, we
226 226 # can end up with extra data in the cloned revlogs that's
227 227 # not pointed to by changesets, thus causing verify to
228 228 # fail
229 229 src_lock = src_repo.lock(wait=False)
230 230 except error.LockError:
231 231 copy = False
232 232
233 233 if copy:
234 src_repo.hook('preoutgoing', throw=True, source='clone')
234 235 hgdir = os.path.realpath(os.path.join(dest, ".hg"))
235 236 if not os.path.exists(dest):
236 237 os.mkdir(dest)
237 238 else:
238 239 # only clean up directories we create ourselves
239 240 dir_cleanup.dir_ = hgdir
240 241 try:
241 242 dest_path = hgdir
242 243 os.mkdir(dest_path)
243 244 except OSError, inst:
244 245 if inst.errno == errno.EEXIST:
245 246 dir_cleanup.close()
246 247 raise util.Abort(_("destination '%s' already exists")
247 248 % dest)
248 249 raise
249 250
250 251 for f in src_repo.store.copylist():
251 252 src = os.path.join(src_repo.path, f)
252 253 dst = os.path.join(dest_path, f)
253 254 dstbase = os.path.dirname(dst)
254 255 if dstbase and not os.path.exists(dstbase):
255 256 os.mkdir(dstbase)
256 257 if os.path.exists(src):
257 258 if dst.endswith('data'):
258 259 # lock to avoid premature writing to the target
259 260 dest_lock = lock.lock(os.path.join(dstbase, "lock"))
260 261 util.copyfiles(src, dst)
261 262
262 263 # we need to re-init the repo after manually copying the data
263 264 # into it
264 265 dest_repo = repository(ui, dest)
265
266 src_repo.hook('outgoing', source='clone', node='0'*40)
266 267 else:
267 268 try:
268 269 dest_repo = repository(ui, dest, create=True)
269 270 except OSError, inst:
270 271 if inst.errno == errno.EEXIST:
271 272 dir_cleanup.close()
272 273 raise util.Abort(_("destination '%s' already exists")
273 274 % dest)
274 275 raise
275 276
276 277 revs = None
277 278 if rev:
278 279 if 'lookup' not in src_repo.capabilities:
279 280 raise util.Abort(_("src repository does not support revision "
280 281 "lookup and so doesn't support clone by "
281 282 "revision"))
282 283 revs = [src_repo.lookup(r) for r in rev]
283 284 checkout = revs[0]
284 285 if dest_repo.local():
285 286 dest_repo.clone(src_repo, heads=revs, stream=stream)
286 287 elif src_repo.local():
287 288 src_repo.push(dest_repo, revs=revs)
288 289 else:
289 290 raise util.Abort(_("clone from remote to remote not supported"))
290 291
291 292 if dir_cleanup:
292 293 dir_cleanup.close()
293 294
294 295 if dest_repo.local():
295 296 fp = dest_repo.opener("hgrc", "w", text=True)
296 297 fp.write("[paths]\n")
297 298 fp.write("default = %s\n" % abspath)
298 299 fp.close()
299 300
300 301 dest_repo.ui.setconfig('paths', 'default', abspath)
301 302
302 303 if update:
303 304 dest_repo.ui.status(_("updating working directory\n"))
304 305 if update is not True:
305 306 checkout = update
306 307 for test in (checkout, 'default', 'tip'):
307 308 try:
308 309 uprev = dest_repo.lookup(test)
309 310 break
310 311 except:
311 312 continue
312 313 _update(dest_repo, uprev)
313 314
314 315 return src_repo, dest_repo
315 316 finally:
316 317 release(src_lock, dest_lock)
317 318 if dir_cleanup is not None:
318 319 dir_cleanup.cleanup()
319 320
320 321 def _showstats(repo, stats):
321 322 stats = ((stats[0], _("updated")),
322 323 (stats[1], _("merged")),
323 324 (stats[2], _("removed")),
324 325 (stats[3], _("unresolved")))
325 326 note = ", ".join([_("%d files %s") % s for s in stats])
326 327 repo.ui.status("%s\n" % note)
327 328
328 329 def update(repo, node):
329 330 """update the working directory to node, merging linear changes"""
330 331 stats = _merge.update(repo, node, False, False, None)
331 332 _showstats(repo, stats)
332 333 if stats[3]:
333 334 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
334 335 return stats[3] > 0
335 336
336 337 # naming conflict in clone()
337 338 _update = update
338 339
339 340 def clean(repo, node, show_stats=True):
340 341 """forcibly switch the working directory to node, clobbering changes"""
341 342 stats = _merge.update(repo, node, False, True, None)
342 343 if show_stats: _showstats(repo, stats)
343 344 return stats[3] > 0
344 345
345 346 def merge(repo, node, force=None, remind=True):
346 347 """branch merge with node, resolving changes"""
347 348 stats = _merge.update(repo, node, True, force, False)
348 349 _showstats(repo, stats)
349 350 if stats[3]:
350 351 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges "
351 352 "or 'hg up --clean' to abandon\n"))
352 353 elif remind:
353 354 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
354 355 return stats[3] > 0
355 356
356 357 def revert(repo, node, choose):
357 358 """revert changes to revision in node without updating dirstate"""
358 359 return _merge.update(repo, node, False, True, choose)[3] > 0
359 360
360 361 def verify(repo):
361 362 """verify the consistency of a repository"""
362 363 return _verify.verify(repo)
@@ -1,220 +1,233
1 1 #!/bin/sh
2 2
3 3 cp "$TESTDIR"/printenv.py .
4 4
5 5 # commit hooks can see env vars
6 6 hg init a
7 7 cd a
8 8 echo "[hooks]" > .hg/hgrc
9 9 echo 'commit = unset HG_LOCAL HG_TAG; python ../printenv.py commit' >> .hg/hgrc
10 10 echo 'commit.b = unset HG_LOCAL HG_TAG; python ../printenv.py commit.b' >> .hg/hgrc
11 11 echo 'precommit = unset HG_LOCAL HG_NODE HG_TAG; python ../printenv.py precommit' >> .hg/hgrc
12 12 echo 'pretxncommit = unset HG_LOCAL HG_TAG; python ../printenv.py pretxncommit' >> .hg/hgrc
13 13 echo 'pretxncommit.tip = hg -q tip' >> .hg/hgrc
14 14 echo 'pre-identify = python ../printenv.py pre-identify 1' >> .hg/hgrc
15 15 echo 'pre-cat = python ../printenv.py pre-cat' >> .hg/hgrc
16 16 echo 'post-cat = python ../printenv.py post-cat' >> .hg/hgrc
17 17 echo a > a
18 18 hg add a
19 19 hg commit -m a -d "1000000 0"
20 20
21 21 hg clone . ../b
22 22 cd ../b
23 23
24 24 # changegroup hooks can see env vars
25 25 echo '[hooks]' > .hg/hgrc
26 26 echo 'prechangegroup = python ../printenv.py prechangegroup' >> .hg/hgrc
27 27 echo 'changegroup = python ../printenv.py changegroup' >> .hg/hgrc
28 28 echo 'incoming = python ../printenv.py incoming' >> .hg/hgrc
29 29
30 30 # pretxncommit and commit hooks can see both parents of merge
31 31 cd ../a
32 32 echo b >> a
33 33 hg commit -m a1 -d "1 0"
34 34 hg update -C 0
35 35 echo b > b
36 36 hg add b
37 37 hg commit -m b -d '1 0'
38 38 hg merge 1
39 39 hg commit -m merge -d '2 0'
40 40
41 41 # test generic hooks
42 42 hg id
43 43 hg cat b
44 44
45 45 cd ../b
46 46 hg pull ../a
47 47
48 48 # tag hooks can see env vars
49 49 cd ../a
50 50 echo 'pretag = python ../printenv.py pretag' >> .hg/hgrc
51 51 echo 'tag = unset HG_PARENT1 HG_PARENT2; python ../printenv.py tag' >> .hg/hgrc
52 52 hg tag -d '3 0' a
53 53 hg tag -l la
54 54
55 55 # pretag hook can forbid tagging
56 56 echo 'pretag.forbid = python ../printenv.py pretag.forbid 1' >> .hg/hgrc
57 57 hg tag -d '4 0' fa
58 58 hg tag -l fla
59 59
60 60 # pretxncommit hook can see changeset, can roll back txn, changeset
61 61 # no more there after
62 62 echo 'pretxncommit.forbid0 = hg tip -q' >> .hg/hgrc
63 63 echo 'pretxncommit.forbid1 = python ../printenv.py pretxncommit.forbid 1' >> .hg/hgrc
64 64 echo z > z
65 65 hg add z
66 66 hg -q tip
67 67 hg commit -m 'fail' -d '4 0'
68 68 hg -q tip
69 69
70 70 # precommit hook can prevent commit
71 71 echo 'precommit.forbid = python ../printenv.py precommit.forbid 1' >> .hg/hgrc
72 72 hg commit -m 'fail' -d '4 0'
73 73 hg -q tip
74 74
75 75 # preupdate hook can prevent update
76 76 echo 'preupdate = python ../printenv.py preupdate' >> .hg/hgrc
77 77 hg update 1
78 78
79 79 # update hook
80 80 echo 'update = python ../printenv.py update' >> .hg/hgrc
81 81 hg update
82 82
83 83 # prechangegroup hook can prevent incoming changes
84 84 cd ../b
85 85 hg -q tip
86 86 echo '[hooks]' > .hg/hgrc
87 87 echo 'prechangegroup.forbid = python ../printenv.py prechangegroup.forbid 1' >> .hg/hgrc
88 88 hg pull ../a
89 89
90 90 # pretxnchangegroup hook can see incoming changes, can roll back txn,
91 91 # incoming changes no longer there after
92 92 echo '[hooks]' > .hg/hgrc
93 93 echo 'pretxnchangegroup.forbid0 = hg tip -q' >> .hg/hgrc
94 94 echo 'pretxnchangegroup.forbid1 = python ../printenv.py pretxnchangegroup.forbid 1' >> .hg/hgrc
95 95 hg pull ../a
96 96 hg -q tip
97 97
98 98 # outgoing hooks can see env vars
99 99 rm .hg/hgrc
100 100 echo '[hooks]' > ../a/.hg/hgrc
101 101 echo 'preoutgoing = python ../printenv.py preoutgoing' >> ../a/.hg/hgrc
102 102 echo 'outgoing = python ../printenv.py outgoing' >> ../a/.hg/hgrc
103 103 hg pull ../a
104 104 hg rollback
105 105
106 106 # preoutgoing hook can prevent outgoing changes
107 107 echo 'preoutgoing.forbid = python ../printenv.py preoutgoing.forbid 1' >> ../a/.hg/hgrc
108 108 hg pull ../a
109 109
110 # outgoing hooks work for local clones
111 cd ..
112 echo '[hooks]' > a/.hg/hgrc
113 echo 'preoutgoing = python ../printenv.py preoutgoing' >> a/.hg/hgrc
114 echo 'outgoing = python ../printenv.py outgoing' >> a/.hg/hgrc
115 hg clone a c
116 rm -rf c
117
118 # preoutgoing hook can prevent outgoing changes for local clones
119 echo 'preoutgoing.forbid = python ../printenv.py preoutgoing.forbid 1' >> a/.hg/hgrc
120 hg clone a zzz
121 cd b
122
110 123 cat > hooktests.py <<EOF
111 124 from mercurial import util
112 125
113 126 uncallable = 0
114 127
115 128 def printargs(args):
116 129 args.pop('ui', None)
117 130 args.pop('repo', None)
118 131 a = list(args.items())
119 132 a.sort()
120 133 print 'hook args:'
121 134 for k, v in a:
122 135 print ' ', k, v
123 136
124 137 def passhook(**args):
125 138 printargs(args)
126 139
127 140 def failhook(**args):
128 141 printargs(args)
129 142 return True
130 143
131 144 class LocalException(Exception):
132 145 pass
133 146
134 147 def raisehook(**args):
135 148 raise LocalException('exception from hook')
136 149
137 150 def aborthook(**args):
138 151 raise util.Abort('raise abort from hook')
139 152
140 153 def brokenhook(**args):
141 154 return 1 + {}
142 155
143 156 class container:
144 157 unreachable = 1
145 158 EOF
146 159
147 160 echo '# test python hooks'
148 161 PYTHONPATH="`pwd`:$PYTHONPATH"
149 162 export PYTHONPATH
150 163
151 164 echo '[hooks]' > ../a/.hg/hgrc
152 165 echo 'preoutgoing.broken = python:hooktests.brokenhook' >> ../a/.hg/hgrc
153 166 hg pull ../a 2>&1 | grep 'raised an exception'
154 167
155 168 echo '[hooks]' > ../a/.hg/hgrc
156 169 echo 'preoutgoing.raise = python:hooktests.raisehook' >> ../a/.hg/hgrc
157 170 hg pull ../a 2>&1 | grep 'raised an exception'
158 171
159 172 echo '[hooks]' > ../a/.hg/hgrc
160 173 echo 'preoutgoing.abort = python:hooktests.aborthook' >> ../a/.hg/hgrc
161 174 hg pull ../a
162 175
163 176 echo '[hooks]' > ../a/.hg/hgrc
164 177 echo 'preoutgoing.fail = python:hooktests.failhook' >> ../a/.hg/hgrc
165 178 hg pull ../a
166 179
167 180 echo '[hooks]' > ../a/.hg/hgrc
168 181 echo 'preoutgoing.uncallable = python:hooktests.uncallable' >> ../a/.hg/hgrc
169 182 hg pull ../a
170 183
171 184 echo '[hooks]' > ../a/.hg/hgrc
172 185 echo 'preoutgoing.nohook = python:hooktests.nohook' >> ../a/.hg/hgrc
173 186 hg pull ../a
174 187
175 188 echo '[hooks]' > ../a/.hg/hgrc
176 189 echo 'preoutgoing.nomodule = python:nomodule' >> ../a/.hg/hgrc
177 190 hg pull ../a
178 191
179 192 echo '[hooks]' > ../a/.hg/hgrc
180 193 echo 'preoutgoing.badmodule = python:nomodule.nowhere' >> ../a/.hg/hgrc
181 194 hg pull ../a
182 195
183 196 echo '[hooks]' > ../a/.hg/hgrc
184 197 echo 'preoutgoing.unreachable = python:hooktests.container.unreachable' >> ../a/.hg/hgrc
185 198 hg pull ../a
186 199
187 200 echo '[hooks]' > ../a/.hg/hgrc
188 201 echo 'preoutgoing.pass = python:hooktests.passhook' >> ../a/.hg/hgrc
189 202 hg pull ../a
190 203
191 204 echo '# make sure --traceback works'
192 205 echo '[hooks]' > .hg/hgrc
193 206 echo 'commit.abort = python:hooktests.aborthook' >> .hg/hgrc
194 207
195 208 echo a >> a
196 209 hg --traceback commit -A -m a 2>&1 | grep '^Traceback'
197 210
198 211 cd ..
199 212 hg init c
200 213 cd c
201 214
202 215 cat > hookext.py <<EOF
203 216 def autohook(**args):
204 217 print "Automatically installed hook"
205 218
206 219 def reposetup(ui, repo):
207 220 repo.ui.setconfig("hooks", "commit.auto", autohook)
208 221 EOF
209 222 echo '[extensions]' >> .hg/hgrc
210 223 echo 'hookext = hookext.py' >> .hg/hgrc
211 224
212 225 touch foo
213 226 hg add foo
214 227 hg ci -m 'add foo'
215 228 echo >> foo
216 229 hg ci --debug -m 'change foo' | sed -e 's/ at .*>/>/'
217 230
218 231 hg showconfig hooks | sed -e 's/ at .*>/>/'
219 232
220 233 exit 0
@@ -1,155 +1,162
1 1 precommit hook: HG_PARENT1=0000000000000000000000000000000000000000
2 2 pretxncommit hook: HG_NODE=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PARENT1=0000000000000000000000000000000000000000 HG_PENDING=true
3 3 0:29b62aeb769f
4 4 commit hook: HG_NODE=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PARENT1=0000000000000000000000000000000000000000
5 5 commit.b hook: HG_NODE=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PARENT1=0000000000000000000000000000000000000000
6 6 updating working directory
7 7 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
8 8 precommit hook: HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
9 9 pretxncommit hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PENDING=true
10 10 1:b702efe96888
11 11 commit hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
12 12 commit.b hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
13 13 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
14 14 precommit hook: HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
15 15 pretxncommit hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PENDING=true
16 16 2:1324a5531bac
17 17 commit hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
18 18 commit.b hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
19 19 created new head
20 20 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
21 21 (branch merge, don't forget to commit)
22 22 precommit hook: HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2
23 23 pretxncommit hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PENDING=true
24 24 3:4c52fb2e4022
25 25 commit hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2
26 26 commit.b hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2
27 27 pre-identify hook: HG_ARGS=id
28 28 warning: pre-identify hook exited with status 1
29 29 pre-cat hook: HG_ARGS=cat b
30 30 post-cat hook: HG_ARGS=cat b HG_RESULT=0
31 31 b
32 32 prechangegroup hook: HG_SOURCE=pull HG_URL=file:
33 33 changegroup hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_SOURCE=pull HG_URL=file:
34 34 incoming hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_SOURCE=pull HG_URL=file:
35 35 incoming hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_SOURCE=pull HG_URL=file:
36 36 incoming hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_SOURCE=pull HG_URL=file:
37 37 pulling from ../a
38 38 searching for changes
39 39 adding changesets
40 40 adding manifests
41 41 adding file changes
42 42 added 3 changesets with 2 changes to 2 files
43 43 (run 'hg update' to get a working copy)
44 44 pretag hook: HG_LOCAL=0 HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_TAG=a
45 45 precommit hook: HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321
46 46 pretxncommit hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321 HG_PENDING=true
47 47 4:8ea2ef7ad3e8
48 48 commit hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321
49 49 commit.b hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321
50 50 tag hook: HG_LOCAL=0 HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_TAG=a
51 51 pretag hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=la
52 52 tag hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=la
53 53 pretag hook: HG_LOCAL=0 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fa
54 54 pretag.forbid hook: HG_LOCAL=0 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fa
55 55 abort: pretag.forbid hook exited with status 1
56 56 pretag hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fla
57 57 pretag.forbid hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fla
58 58 abort: pretag.forbid hook exited with status 1
59 59 4:8ea2ef7ad3e8
60 60 precommit hook: HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
61 61 pretxncommit hook: HG_NODE=fad284daf8c032148abaffcd745dafeceefceb61 HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PENDING=true
62 62 5:fad284daf8c0
63 63 5:fad284daf8c0
64 64 pretxncommit.forbid hook: HG_NODE=fad284daf8c032148abaffcd745dafeceefceb61 HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PENDING=true
65 65 transaction abort!
66 66 rollback completed
67 67 abort: pretxncommit.forbid1 hook exited with status 1
68 68 4:8ea2ef7ad3e8
69 69 precommit hook: HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
70 70 precommit.forbid hook: HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
71 71 abort: precommit.forbid hook exited with status 1
72 72 4:8ea2ef7ad3e8
73 73 preupdate hook: HG_PARENT1=b702efe96888
74 74 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
75 75 preupdate hook: HG_PARENT1=8ea2ef7ad3e8
76 76 update hook: HG_ERROR=0 HG_PARENT1=8ea2ef7ad3e8
77 77 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
78 78 3:4c52fb2e4022
79 79 prechangegroup.forbid hook: HG_SOURCE=pull HG_URL=file:
80 80 pulling from ../a
81 81 searching for changes
82 82 abort: prechangegroup.forbid hook exited with status 1
83 83 4:8ea2ef7ad3e8
84 84 pretxnchangegroup.forbid hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PENDING=true HG_SOURCE=pull HG_URL=file:
85 85 pulling from ../a
86 86 searching for changes
87 87 adding changesets
88 88 adding manifests
89 89 adding file changes
90 90 added 1 changesets with 1 changes to 1 files
91 91 transaction abort!
92 92 rollback completed
93 93 abort: pretxnchangegroup.forbid1 hook exited with status 1
94 94 3:4c52fb2e4022
95 95 preoutgoing hook: HG_SOURCE=pull
96 96 outgoing hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_SOURCE=pull
97 97 pulling from ../a
98 98 searching for changes
99 99 adding changesets
100 100 adding manifests
101 101 adding file changes
102 102 added 1 changesets with 1 changes to 1 files
103 103 (run 'hg update' to get a working copy)
104 104 rolling back last transaction
105 105 preoutgoing hook: HG_SOURCE=pull
106 106 preoutgoing.forbid hook: HG_SOURCE=pull
107 107 pulling from ../a
108 108 searching for changes
109 109 abort: preoutgoing.forbid hook exited with status 1
110 preoutgoing hook: HG_SOURCE=clone
111 outgoing hook: HG_NODE=0000000000000000000000000000000000000000 HG_SOURCE=clone
112 updating working directory
113 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
114 preoutgoing hook: HG_SOURCE=clone
115 preoutgoing.forbid hook: HG_SOURCE=clone
116 abort: preoutgoing.forbid hook exited with status 1
110 117 # test python hooks
111 118 error: preoutgoing.broken hook raised an exception: unsupported operand type(s) for +: 'int' and 'dict'
112 119 error: preoutgoing.raise hook raised an exception: exception from hook
113 120 pulling from ../a
114 121 searching for changes
115 122 error: preoutgoing.abort hook failed: raise abort from hook
116 123 abort: raise abort from hook
117 124 pulling from ../a
118 125 searching for changes
119 126 hook args:
120 127 hooktype preoutgoing
121 128 source pull
122 129 abort: preoutgoing.fail hook failed
123 130 pulling from ../a
124 131 searching for changes
125 132 abort: preoutgoing.uncallable hook is invalid ("hooktests.uncallable" is not callable)
126 133 pulling from ../a
127 134 searching for changes
128 135 abort: preoutgoing.nohook hook is invalid ("hooktests.nohook" is not defined)
129 136 pulling from ../a
130 137 searching for changes
131 138 abort: preoutgoing.nomodule hook is invalid ("nomodule" not in a module)
132 139 pulling from ../a
133 140 searching for changes
134 141 abort: preoutgoing.badmodule hook is invalid (import of "nomodule" failed)
135 142 pulling from ../a
136 143 searching for changes
137 144 abort: preoutgoing.unreachable hook is invalid (import of "hooktests.container" failed)
138 145 pulling from ../a
139 146 searching for changes
140 147 hook args:
141 148 hooktype preoutgoing
142 149 source pull
143 150 adding changesets
144 151 adding manifests
145 152 adding file changes
146 153 added 1 changesets with 1 changes to 1 files
147 154 (run 'hg update' to get a working copy)
148 155 # make sure --traceback works
149 156 Traceback (most recent call last):
150 157 Automatically installed hook
151 158 foo
152 159 calling hook commit.auto: <function autohook>
153 160 Automatically installed hook
154 161 committed changeset 1:52998019f6252a2b893452765fcb0a47351a5708
155 162 hooks.commit.auto=<function autohook>
General Comments 0
You need to be logged in to leave comments. Login now