##// END OF EJS Templates
tests: show cache of audited paths is never invalidated
Yuya Nishihara -
r33721:47ea2829 stable
parent child Browse files
Show More
@@ -1,131 +1,232 b''
1 1 $ hg init
2 2
3 3 audit of .hg
4 4
5 5 $ hg add .hg/00changelog.i
6 6 abort: path contains illegal component: .hg/00changelog.i (glob)
7 7 [255]
8 8
9 9 #if symlink
10 10
11 11 Symlinks
12 12
13 13 $ mkdir a
14 14 $ echo a > a/a
15 15 $ hg ci -Ama
16 16 adding a/a
17 17 $ ln -s a b
18 18 $ echo b > a/b
19 19 $ hg add b/b
20 20 abort: path 'b/b' traverses symbolic link 'b' (glob)
21 21 [255]
22 22 $ hg add b
23 23
24 24 should still fail - maybe
25 25
26 26 $ hg add b/b
27 27 abort: path 'b/b' traverses symbolic link 'b' (glob)
28 28 [255]
29 29
30 30 $ hg commit -m 'add symlink b'
31 31
32 32
33 33 Test symlink traversing when accessing history:
34 34 -----------------------------------------------
35 35
36 36 (build a changeset where the path exists as a directory)
37 37
38 38 $ hg up 0
39 39 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
40 40 $ mkdir b
41 41 $ echo c > b/a
42 42 $ hg add b/a
43 43 $ hg ci -m 'add directory b'
44 44 created new head
45 45
46 46 Test that hg cat does not do anything wrong the working copy has 'b' as directory
47 47
48 48 $ hg cat b/a
49 49 c
50 50 $ hg cat -r "desc(directory)" b/a
51 51 c
52 52 $ hg cat -r "desc(symlink)" b/a
53 53 b/a: no such file in rev bc151a1f53bd
54 54 [1]
55 55
56 56 Test that hg cat does not do anything wrong the working copy has 'b' as a symlink (issue4749)
57 57
58 58 $ hg up 'desc(symlink)'
59 59 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
60 60 $ hg cat b/a
61 61 b/a: no such file in rev bc151a1f53bd
62 62 [1]
63 63 $ hg cat -r "desc(directory)" b/a
64 64 c
65 65 $ hg cat -r "desc(symlink)" b/a
66 66 b/a: no such file in rev bc151a1f53bd
67 67 [1]
68 68
69 69 #endif
70 70
71 71
72 72 unbundle tampered bundle
73 73
74 74 $ hg init target
75 75 $ cd target
76 76 $ hg unbundle "$TESTDIR/bundles/tampered.hg"
77 77 adding changesets
78 78 adding manifests
79 79 adding file changes
80 80 added 5 changesets with 6 changes to 6 files (+4 heads)
81 81 (run 'hg heads' to see heads, 'hg merge' to merge)
82 82
83 83 attack .hg/test
84 84
85 85 $ hg manifest -r0
86 86 .hg/test
87 87 $ hg update -Cr0
88 88 abort: path contains illegal component: .hg/test (glob)
89 89 [255]
90 90
91 91 attack foo/.hg/test
92 92
93 93 $ hg manifest -r1
94 94 foo/.hg/test
95 95 $ hg update -Cr1
96 96 abort: path 'foo/.hg/test' is inside nested repo 'foo' (glob)
97 97 [255]
98 98
99 99 attack back/test where back symlinks to ..
100 100
101 101 $ hg manifest -r2
102 102 back
103 103 back/test
104 104 #if symlink
105 105 $ hg update -Cr2
106 106 abort: path 'back/test' traverses symbolic link 'back'
107 107 [255]
108 108 #else
109 109 ('back' will be a file and cause some other system specific error)
110 110 $ hg update -Cr2
111 111 abort: * (glob)
112 112 [255]
113 113 #endif
114 114
115 115 attack ../test
116 116
117 117 $ hg manifest -r3
118 118 ../test
119 119 $ hg update -Cr3
120 120 abort: path contains illegal component: ../test (glob)
121 121 [255]
122 122
123 123 attack /tmp/test
124 124
125 125 $ hg manifest -r4
126 126 /tmp/test
127 127 $ hg update -Cr4
128 128 abort: path contains illegal component: /tmp/test (glob)
129 129 [255]
130 130
131 131 $ cd ..
132
133 Test symlink traversal on merge:
134 --------------------------------
135
136 #if symlink
137
138 set up symlink hell
139
140 $ mkdir merge-symlink-out
141 $ hg init merge-symlink
142 $ cd merge-symlink
143 $ touch base
144 $ hg commit -qAm base
145 $ ln -s ../merge-symlink-out a
146 $ hg commit -qAm 'symlink a -> ../merge-symlink-out'
147 $ hg up -q 0
148 $ mkdir a
149 $ touch a/poisoned
150 $ hg commit -qAm 'file a/poisoned'
151 $ hg log -G -T '{rev}: {desc}\n'
152 @ 2: file a/poisoned
153 |
154 | o 1: symlink a -> ../merge-symlink-out
155 |/
156 o 0: base
157
158
159 try trivial merge
160
161 $ hg up -qC 1
162 $ hg merge 2
163 abort: path 'a/poisoned' traverses symbolic link 'a'
164 [255]
165
166 try rebase onto other revision: cache of audited paths should be discarded,
167 and the rebase should fail (issue5628)
168
169 $ hg up -qC 2
170 $ hg rebase -s 2 -d 1 --config extensions.rebase=
171 rebasing 2:e73c21d6b244 "file a/poisoned" (tip)
172 saved backup bundle to * (glob)
173 $ ls ../merge-symlink-out
174 poisoned
175
176 $ cd ..
177
178 Test symlink traversal on update:
179 ---------------------------------
180
181 $ mkdir update-symlink-out
182 $ hg init update-symlink
183 $ cd update-symlink
184 $ ln -s ../update-symlink-out a
185 $ hg commit -qAm 'symlink a -> ../update-symlink-out'
186 $ hg rm a
187 $ mkdir a && touch a/b
188 $ hg ci -qAm 'file a/b' a/b
189 $ hg up -qC 0
190 $ hg rm a
191 $ mkdir a && touch a/c
192 $ hg ci -qAm 'rm a, file a/c'
193 $ hg log -G -T '{rev}: {desc}\n'
194 @ 2: rm a, file a/c
195 |
196 | o 1: file a/b
197 |/
198 o 0: symlink a -> ../update-symlink-out
199
200
201 try linear update where symlink already exists:
202
203 $ hg up -qC 0
204 $ hg up 1
205 abort: path 'a/b' traverses symbolic link 'a'
206 [255]
207
208 try linear update including symlinked directory and its content: paths are
209 audited first by calculateupdates(), where no symlink is created so both
210 'a' and 'a/b' are taken as good paths. still applyupdates() should fail.
211
212 $ hg up -qC null
213 $ hg up 1
214 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
215 $ ls ../update-symlink-out
216 b
217 $ rm ../update-symlink-out/b
218
219 try branch update replacing directory with symlink, and its content: the
220 path 'a' is audited as a directory first, which should be audited again as
221 a symlink.
222
223 $ rm -f a
224 $ hg up -qC 2
225 $ hg up 1
226 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
227 $ ls ../update-symlink-out
228 b
229
230 $ cd ..
231
232 #endif
@@ -1,910 +1,987 b''
1 1 #if windows
2 2 $ PYTHONPATH="$TESTDIR/../contrib;$PYTHONPATH"
3 3 #else
4 4 $ PYTHONPATH="$TESTDIR/../contrib:$PYTHONPATH"
5 5 #endif
6 6 $ export PYTHONPATH
7 7
8 8 typical client does not want echo-back messages, so test without it:
9 9
10 10 $ grep -v '^promptecho ' < $HGRCPATH >> $HGRCPATH.new
11 11 $ mv $HGRCPATH.new $HGRCPATH
12 12
13 13 $ hg init repo
14 14 $ cd repo
15 15
16 16 >>> from __future__ import print_function
17 17 >>> from hgclient import readchannel, runcommand, check
18 18 >>> @check
19 19 ... def hellomessage(server):
20 20 ... ch, data = readchannel(server)
21 21 ... print('%c, %r' % (ch, data))
22 22 ... # run an arbitrary command to make sure the next thing the server
23 23 ... # sends isn't part of the hello message
24 24 ... runcommand(server, ['id'])
25 25 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
26 26 *** runcommand id
27 27 000000000000 tip
28 28
29 29 >>> from hgclient import check
30 30 >>> @check
31 31 ... def unknowncommand(server):
32 32 ... server.stdin.write('unknowncommand\n')
33 33 abort: unknown command unknowncommand
34 34
35 35 >>> from hgclient import readchannel, runcommand, check
36 36 >>> @check
37 37 ... def checkruncommand(server):
38 38 ... # hello block
39 39 ... readchannel(server)
40 40 ...
41 41 ... # no args
42 42 ... runcommand(server, [])
43 43 ...
44 44 ... # global options
45 45 ... runcommand(server, ['id', '--quiet'])
46 46 ...
47 47 ... # make sure global options don't stick through requests
48 48 ... runcommand(server, ['id'])
49 49 ...
50 50 ... # --config
51 51 ... runcommand(server, ['id', '--config', 'ui.quiet=True'])
52 52 ...
53 53 ... # make sure --config doesn't stick
54 54 ... runcommand(server, ['id'])
55 55 ...
56 56 ... # negative return code should be masked
57 57 ... runcommand(server, ['id', '-runknown'])
58 58 *** runcommand
59 59 Mercurial Distributed SCM
60 60
61 61 basic commands:
62 62
63 63 add add the specified files on the next commit
64 64 annotate show changeset information by line for each file
65 65 clone make a copy of an existing repository
66 66 commit commit the specified files or all outstanding changes
67 67 diff diff repository (or selected files)
68 68 export dump the header and diffs for one or more changesets
69 69 forget forget the specified files on the next commit
70 70 init create a new repository in the given directory
71 71 log show revision history of entire repository or files
72 72 merge merge another revision into working directory
73 73 pull pull changes from the specified source
74 74 push push changes to the specified destination
75 75 remove remove the specified files on the next commit
76 76 serve start stand-alone webserver
77 77 status show changed files in the working directory
78 78 summary summarize working directory state
79 79 update update working directory (or switch revisions)
80 80
81 81 (use 'hg help' for the full list of commands or 'hg -v' for details)
82 82 *** runcommand id --quiet
83 83 000000000000
84 84 *** runcommand id
85 85 000000000000 tip
86 86 *** runcommand id --config ui.quiet=True
87 87 000000000000
88 88 *** runcommand id
89 89 000000000000 tip
90 90 *** runcommand id -runknown
91 91 abort: unknown revision 'unknown'!
92 92 [255]
93 93
94 94 >>> from hgclient import readchannel, check
95 95 >>> @check
96 96 ... def inputeof(server):
97 97 ... readchannel(server)
98 98 ... server.stdin.write('runcommand\n')
99 99 ... # close stdin while server is waiting for input
100 100 ... server.stdin.close()
101 101 ...
102 102 ... # server exits with 1 if the pipe closed while reading the command
103 103 ... print('server exit code =', server.wait())
104 104 server exit code = 1
105 105
106 106 >>> from hgclient import readchannel, runcommand, check, stringio
107 107 >>> @check
108 108 ... def serverinput(server):
109 109 ... readchannel(server)
110 110 ...
111 111 ... patch = """
112 112 ... # HG changeset patch
113 113 ... # User test
114 114 ... # Date 0 0
115 115 ... # Node ID c103a3dec114d882c98382d684d8af798d09d857
116 116 ... # Parent 0000000000000000000000000000000000000000
117 117 ... 1
118 118 ...
119 119 ... diff -r 000000000000 -r c103a3dec114 a
120 120 ... --- /dev/null Thu Jan 01 00:00:00 1970 +0000
121 121 ... +++ b/a Thu Jan 01 00:00:00 1970 +0000
122 122 ... @@ -0,0 +1,1 @@
123 123 ... +1
124 124 ... """
125 125 ...
126 126 ... runcommand(server, ['import', '-'], input=stringio(patch))
127 127 ... runcommand(server, ['log'])
128 128 *** runcommand import -
129 129 applying patch from stdin
130 130 *** runcommand log
131 131 changeset: 0:eff892de26ec
132 132 tag: tip
133 133 user: test
134 134 date: Thu Jan 01 00:00:00 1970 +0000
135 135 summary: 1
136 136
137 137
138 138 check that "histedit --commands=-" can read rules from the input channel:
139 139
140 140 >>> import cStringIO
141 141 >>> from hgclient import readchannel, runcommand, check
142 142 >>> @check
143 143 ... def serverinput(server):
144 144 ... readchannel(server)
145 145 ... rules = 'pick eff892de26ec\n'
146 146 ... runcommand(server, ['histedit', '0', '--commands=-',
147 147 ... '--config', 'extensions.histedit='],
148 148 ... input=cStringIO.StringIO(rules))
149 149 *** runcommand histedit 0 --commands=- --config extensions.histedit=
150 150
151 151 check that --cwd doesn't persist between requests:
152 152
153 153 $ mkdir foo
154 154 $ touch foo/bar
155 155 >>> from hgclient import readchannel, runcommand, check
156 156 >>> @check
157 157 ... def cwd(server):
158 158 ... readchannel(server)
159 159 ... runcommand(server, ['--cwd', 'foo', 'st', 'bar'])
160 160 ... runcommand(server, ['st', 'foo/bar'])
161 161 *** runcommand --cwd foo st bar
162 162 ? bar
163 163 *** runcommand st foo/bar
164 164 ? foo/bar
165 165
166 166 $ rm foo/bar
167 167
168 168
169 169 check that local configs for the cached repo aren't inherited when -R is used:
170 170
171 171 $ cat <<EOF >> .hg/hgrc
172 172 > [ui]
173 173 > foo = bar
174 174 > EOF
175 175
176 176 >>> from hgclient import readchannel, sep, runcommand, check
177 177 >>> @check
178 178 ... def localhgrc(server):
179 179 ... readchannel(server)
180 180 ...
181 181 ... # the cached repo local hgrc contains ui.foo=bar, so showconfig should
182 182 ... # show it
183 183 ... runcommand(server, ['showconfig'], outfilter=sep)
184 184 ...
185 185 ... # but not for this repo
186 186 ... runcommand(server, ['init', 'foo'])
187 187 ... runcommand(server, ['-R', 'foo', 'showconfig', 'ui', 'defaults'])
188 188 *** runcommand showconfig
189 189 bundle.mainreporoot=$TESTTMP/repo
190 190 devel.all-warnings=true
191 191 devel.default-date=0 0
192 192 extensions.fsmonitor= (fsmonitor !)
193 193 largefiles.usercache=$TESTTMP/.cache/largefiles
194 194 ui.slash=True
195 195 ui.interactive=False
196 196 ui.mergemarkers=detailed
197 197 ui.usehttp2=true (?)
198 198 ui.foo=bar
199 199 ui.nontty=true
200 200 web.address=localhost
201 201 web\.ipv6=(?:True|False) (re)
202 202 *** runcommand init foo
203 203 *** runcommand -R foo showconfig ui defaults
204 204 ui.slash=True
205 205 ui.interactive=False
206 206 ui.mergemarkers=detailed
207 207 ui.usehttp2=true (?)
208 208 ui.nontty=true
209 209
210 210 $ rm -R foo
211 211
212 212 #if windows
213 213 $ PYTHONPATH="$TESTTMP/repo;$PYTHONPATH"
214 214 #else
215 215 $ PYTHONPATH="$TESTTMP/repo:$PYTHONPATH"
216 216 #endif
217 217
218 218 $ cat <<EOF > hook.py
219 219 > from __future__ import print_function
220 220 > import sys
221 221 > def hook(**args):
222 222 > print('hook talking')
223 223 > print('now try to read something: %r' % sys.stdin.read())
224 224 > EOF
225 225
226 226 >>> from hgclient import readchannel, runcommand, check, stringio
227 227 >>> @check
228 228 ... def hookoutput(server):
229 229 ... readchannel(server)
230 230 ... runcommand(server, ['--config',
231 231 ... 'hooks.pre-identify=python:hook.hook',
232 232 ... 'id'],
233 233 ... input=stringio('some input'))
234 234 *** runcommand --config hooks.pre-identify=python:hook.hook id
235 235 eff892de26ec tip
236 236
237 237 Clean hook cached version
238 238 $ rm hook.py*
239 239 $ rm -Rf __pycache__
240 240
241 241 $ echo a >> a
242 242 >>> import os
243 243 >>> from hgclient import readchannel, runcommand, check
244 244 >>> @check
245 245 ... def outsidechanges(server):
246 246 ... readchannel(server)
247 247 ... runcommand(server, ['status'])
248 248 ... os.system('hg ci -Am2')
249 249 ... runcommand(server, ['tip'])
250 250 ... runcommand(server, ['status'])
251 251 *** runcommand status
252 252 M a
253 253 *** runcommand tip
254 254 changeset: 1:d3a0a68be6de
255 255 tag: tip
256 256 user: test
257 257 date: Thu Jan 01 00:00:00 1970 +0000
258 258 summary: 2
259 259
260 260 *** runcommand status
261 261
262 262 >>> import os
263 263 >>> from hgclient import readchannel, runcommand, check
264 264 >>> @check
265 265 ... def bookmarks(server):
266 266 ... readchannel(server)
267 267 ... runcommand(server, ['bookmarks'])
268 268 ...
269 269 ... # changes .hg/bookmarks
270 270 ... os.system('hg bookmark -i bm1')
271 271 ... os.system('hg bookmark -i bm2')
272 272 ... runcommand(server, ['bookmarks'])
273 273 ...
274 274 ... # changes .hg/bookmarks.current
275 275 ... os.system('hg upd bm1 -q')
276 276 ... runcommand(server, ['bookmarks'])
277 277 ...
278 278 ... runcommand(server, ['bookmarks', 'bm3'])
279 279 ... f = open('a', 'ab')
280 280 ... f.write('a\n')
281 281 ... f.close()
282 282 ... runcommand(server, ['commit', '-Amm'])
283 283 ... runcommand(server, ['bookmarks'])
284 284 *** runcommand bookmarks
285 285 no bookmarks set
286 286 *** runcommand bookmarks
287 287 bm1 1:d3a0a68be6de
288 288 bm2 1:d3a0a68be6de
289 289 *** runcommand bookmarks
290 290 * bm1 1:d3a0a68be6de
291 291 bm2 1:d3a0a68be6de
292 292 *** runcommand bookmarks bm3
293 293 *** runcommand commit -Amm
294 294 *** runcommand bookmarks
295 295 bm1 1:d3a0a68be6de
296 296 bm2 1:d3a0a68be6de
297 297 * bm3 2:aef17e88f5f0
298 298
299 299 >>> import os
300 300 >>> from hgclient import readchannel, runcommand, check
301 301 >>> @check
302 302 ... def tagscache(server):
303 303 ... readchannel(server)
304 304 ... runcommand(server, ['id', '-t', '-r', '0'])
305 305 ... os.system('hg tag -r 0 foo')
306 306 ... runcommand(server, ['id', '-t', '-r', '0'])
307 307 *** runcommand id -t -r 0
308 308
309 309 *** runcommand id -t -r 0
310 310 foo
311 311
312 312 >>> import os
313 313 >>> from hgclient import readchannel, runcommand, check
314 314 >>> @check
315 315 ... def setphase(server):
316 316 ... readchannel(server)
317 317 ... runcommand(server, ['phase', '-r', '.'])
318 318 ... os.system('hg phase -r . -p')
319 319 ... runcommand(server, ['phase', '-r', '.'])
320 320 *** runcommand phase -r .
321 321 3: draft
322 322 *** runcommand phase -r .
323 323 3: public
324 324
325 325 $ echo a >> a
326 326 >>> from hgclient import readchannel, runcommand, check
327 327 >>> @check
328 328 ... def rollback(server):
329 329 ... readchannel(server)
330 330 ... runcommand(server, ['phase', '-r', '.', '-p'])
331 331 ... runcommand(server, ['commit', '-Am.'])
332 332 ... runcommand(server, ['rollback'])
333 333 ... runcommand(server, ['phase', '-r', '.'])
334 334 *** runcommand phase -r . -p
335 335 no phases changed
336 336 *** runcommand commit -Am.
337 337 *** runcommand rollback
338 338 repository tip rolled back to revision 3 (undo commit)
339 339 working directory now based on revision 3
340 340 *** runcommand phase -r .
341 341 3: public
342 342
343 343 >>> import os
344 344 >>> from hgclient import readchannel, runcommand, check
345 345 >>> @check
346 346 ... def branch(server):
347 347 ... readchannel(server)
348 348 ... runcommand(server, ['branch'])
349 349 ... os.system('hg branch foo')
350 350 ... runcommand(server, ['branch'])
351 351 ... os.system('hg branch default')
352 352 *** runcommand branch
353 353 default
354 354 marked working directory as branch foo
355 355 (branches are permanent and global, did you want a bookmark?)
356 356 *** runcommand branch
357 357 foo
358 358 marked working directory as branch default
359 359 (branches are permanent and global, did you want a bookmark?)
360 360
361 361 $ touch .hgignore
362 362 >>> import os
363 363 >>> from hgclient import readchannel, runcommand, check
364 364 >>> @check
365 365 ... def hgignore(server):
366 366 ... readchannel(server)
367 367 ... runcommand(server, ['commit', '-Am.'])
368 368 ... f = open('ignored-file', 'ab')
369 369 ... f.write('')
370 370 ... f.close()
371 371 ... f = open('.hgignore', 'ab')
372 372 ... f.write('ignored-file')
373 373 ... f.close()
374 374 ... runcommand(server, ['status', '-i', '-u'])
375 375 *** runcommand commit -Am.
376 376 adding .hgignore
377 377 *** runcommand status -i -u
378 378 I ignored-file
379 379
380 380 cache of non-public revisions should be invalidated on repository change
381 381 (issue4855):
382 382
383 383 >>> import os
384 384 >>> from hgclient import readchannel, runcommand, check
385 385 >>> @check
386 386 ... def phasesetscacheaftercommit(server):
387 387 ... readchannel(server)
388 388 ... # load _phasecache._phaserevs and _phasesets
389 389 ... runcommand(server, ['log', '-qr', 'draft()'])
390 390 ... # create draft commits by another process
391 391 ... for i in xrange(5, 7):
392 392 ... f = open('a', 'ab')
393 393 ... f.seek(0, os.SEEK_END)
394 394 ... f.write('a\n')
395 395 ... f.close()
396 396 ... os.system('hg commit -Aqm%d' % i)
397 397 ... # new commits should be listed as draft revisions
398 398 ... runcommand(server, ['log', '-qr', 'draft()'])
399 399 *** runcommand log -qr draft()
400 400 4:7966c8e3734d
401 401 *** runcommand log -qr draft()
402 402 4:7966c8e3734d
403 403 5:41f6602d1c4f
404 404 6:10501e202c35
405 405
406 406 >>> import os
407 407 >>> from hgclient import readchannel, runcommand, check
408 408 >>> @check
409 409 ... def phasesetscacheafterstrip(server):
410 410 ... readchannel(server)
411 411 ... # load _phasecache._phaserevs and _phasesets
412 412 ... runcommand(server, ['log', '-qr', 'draft()'])
413 413 ... # strip cached revisions by another process
414 414 ... os.system('hg --config extensions.strip= strip -q 5')
415 415 ... # shouldn't abort by "unknown revision '6'"
416 416 ... runcommand(server, ['log', '-qr', 'draft()'])
417 417 *** runcommand log -qr draft()
418 418 4:7966c8e3734d
419 419 5:41f6602d1c4f
420 420 6:10501e202c35
421 421 *** runcommand log -qr draft()
422 422 4:7966c8e3734d
423 423
424 424 cache of phase roots should be invalidated on strip (issue3827):
425 425
426 426 >>> import os
427 427 >>> from hgclient import readchannel, sep, runcommand, check
428 428 >>> @check
429 429 ... def phasecacheafterstrip(server):
430 430 ... readchannel(server)
431 431 ...
432 432 ... # create new head, 5:731265503d86
433 433 ... runcommand(server, ['update', '-C', '0'])
434 434 ... f = open('a', 'ab')
435 435 ... f.write('a\n')
436 436 ... f.close()
437 437 ... runcommand(server, ['commit', '-Am.', 'a'])
438 438 ... runcommand(server, ['log', '-Gq'])
439 439 ...
440 440 ... # make it public; draft marker moves to 4:7966c8e3734d
441 441 ... runcommand(server, ['phase', '-p', '.'])
442 442 ... # load _phasecache.phaseroots
443 443 ... runcommand(server, ['phase', '.'], outfilter=sep)
444 444 ...
445 445 ... # strip 1::4 outside server
446 446 ... os.system('hg -q --config extensions.mq= strip 1')
447 447 ...
448 448 ... # shouldn't raise "7966c8e3734d: no node!"
449 449 ... runcommand(server, ['branches'])
450 450 *** runcommand update -C 0
451 451 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
452 452 (leaving bookmark bm3)
453 453 *** runcommand commit -Am. a
454 454 created new head
455 455 *** runcommand log -Gq
456 456 @ 5:731265503d86
457 457 |
458 458 | o 4:7966c8e3734d
459 459 | |
460 460 | o 3:b9b85890c400
461 461 | |
462 462 | o 2:aef17e88f5f0
463 463 | |
464 464 | o 1:d3a0a68be6de
465 465 |/
466 466 o 0:eff892de26ec
467 467
468 468 *** runcommand phase -p .
469 469 *** runcommand phase .
470 470 5: public
471 471 *** runcommand branches
472 472 default 1:731265503d86
473 473
474 474 in-memory cache must be reloaded if transaction is aborted. otherwise
475 475 changelog and manifest would have invalid node:
476 476
477 477 $ echo a >> a
478 478 >>> from hgclient import readchannel, runcommand, check
479 479 >>> @check
480 480 ... def txabort(server):
481 481 ... readchannel(server)
482 482 ... runcommand(server, ['commit', '--config', 'hooks.pretxncommit=false',
483 483 ... '-mfoo'])
484 484 ... runcommand(server, ['verify'])
485 485 *** runcommand commit --config hooks.pretxncommit=false -mfoo
486 486 transaction abort!
487 487 rollback completed
488 488 abort: pretxncommit hook exited with status 1
489 489 [255]
490 490 *** runcommand verify
491 491 checking changesets
492 492 checking manifests
493 493 crosschecking files in changesets and manifests
494 494 checking files
495 495 1 files, 2 changesets, 2 total revisions
496 496 $ hg revert --no-backup -aq
497 497
498 498 $ cat >> .hg/hgrc << EOF
499 499 > [experimental]
500 500 > evolution=createmarkers
501 501 > EOF
502 502
503 503 >>> import os
504 504 >>> from hgclient import readchannel, runcommand, check
505 505 >>> @check
506 506 ... def obsolete(server):
507 507 ... readchannel(server)
508 508 ...
509 509 ... runcommand(server, ['up', 'null'])
510 510 ... runcommand(server, ['phase', '-df', 'tip'])
511 511 ... cmd = 'hg debugobsolete `hg log -r tip --template {node}`'
512 512 ... if os.name == 'nt':
513 513 ... cmd = 'sh -c "%s"' % cmd # run in sh, not cmd.exe
514 514 ... os.system(cmd)
515 515 ... runcommand(server, ['log', '--hidden'])
516 516 ... runcommand(server, ['log'])
517 517 *** runcommand up null
518 518 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
519 519 *** runcommand phase -df tip
520 520 obsoleted 1 changesets
521 521 *** runcommand log --hidden
522 522 changeset: 1:731265503d86
523 523 tag: tip
524 524 user: test
525 525 date: Thu Jan 01 00:00:00 1970 +0000
526 526 summary: .
527 527
528 528 changeset: 0:eff892de26ec
529 529 bookmark: bm1
530 530 bookmark: bm2
531 531 bookmark: bm3
532 532 user: test
533 533 date: Thu Jan 01 00:00:00 1970 +0000
534 534 summary: 1
535 535
536 536 *** runcommand log
537 537 changeset: 0:eff892de26ec
538 538 bookmark: bm1
539 539 bookmark: bm2
540 540 bookmark: bm3
541 541 tag: tip
542 542 user: test
543 543 date: Thu Jan 01 00:00:00 1970 +0000
544 544 summary: 1
545 545
546 546
547 547 $ cat <<EOF >> .hg/hgrc
548 548 > [extensions]
549 549 > mq =
550 550 > EOF
551 551
552 552 >>> import os
553 553 >>> from hgclient import readchannel, runcommand, check
554 554 >>> @check
555 555 ... def mqoutsidechanges(server):
556 556 ... readchannel(server)
557 557 ...
558 558 ... # load repo.mq
559 559 ... runcommand(server, ['qapplied'])
560 560 ... os.system('hg qnew 0.diff')
561 561 ... # repo.mq should be invalidated
562 562 ... runcommand(server, ['qapplied'])
563 563 ...
564 564 ... runcommand(server, ['qpop', '--all'])
565 565 ... os.system('hg qqueue --create foo')
566 566 ... # repo.mq should be recreated to point to new queue
567 567 ... runcommand(server, ['qqueue', '--active'])
568 568 *** runcommand qapplied
569 569 *** runcommand qapplied
570 570 0.diff
571 571 *** runcommand qpop --all
572 572 popping 0.diff
573 573 patch queue now empty
574 574 *** runcommand qqueue --active
575 575 foo
576 576
577 577 $ cat <<EOF > dbgui.py
578 578 > import os, sys
579 579 > from mercurial import commands, registrar
580 580 > cmdtable = {}
581 581 > command = registrar.command(cmdtable)
582 582 > @command(b"debuggetpass", norepo=True)
583 583 > def debuggetpass(ui):
584 584 > ui.write("%s\\n" % ui.getpass())
585 585 > @command(b"debugprompt", norepo=True)
586 586 > def debugprompt(ui):
587 587 > ui.write("%s\\n" % ui.prompt("prompt:"))
588 588 > @command(b"debugreadstdin", norepo=True)
589 589 > def debugreadstdin(ui):
590 590 > ui.write("read: %r\n" % sys.stdin.read(1))
591 591 > @command(b"debugwritestdout", norepo=True)
592 592 > def debugwritestdout(ui):
593 593 > os.write(1, "low-level stdout fd and\n")
594 594 > sys.stdout.write("stdout should be redirected to /dev/null\n")
595 595 > sys.stdout.flush()
596 596 > EOF
597 597 $ cat <<EOF >> .hg/hgrc
598 598 > [extensions]
599 599 > dbgui = dbgui.py
600 600 > EOF
601 601
602 602 >>> from hgclient import readchannel, runcommand, check, stringio
603 603 >>> @check
604 604 ... def getpass(server):
605 605 ... readchannel(server)
606 606 ... runcommand(server, ['debuggetpass', '--config',
607 607 ... 'ui.interactive=True'],
608 608 ... input=stringio('1234\n'))
609 609 ... runcommand(server, ['debuggetpass', '--config',
610 610 ... 'ui.interactive=True'],
611 611 ... input=stringio('\n'))
612 612 ... runcommand(server, ['debuggetpass', '--config',
613 613 ... 'ui.interactive=True'],
614 614 ... input=stringio(''))
615 615 ... runcommand(server, ['debugprompt', '--config',
616 616 ... 'ui.interactive=True'],
617 617 ... input=stringio('5678\n'))
618 618 ... runcommand(server, ['debugreadstdin'])
619 619 ... runcommand(server, ['debugwritestdout'])
620 620 *** runcommand debuggetpass --config ui.interactive=True
621 621 password: 1234
622 622 *** runcommand debuggetpass --config ui.interactive=True
623 623 password:
624 624 *** runcommand debuggetpass --config ui.interactive=True
625 625 password: abort: response expected
626 626 [255]
627 627 *** runcommand debugprompt --config ui.interactive=True
628 628 prompt: 5678
629 629 *** runcommand debugreadstdin
630 630 read: ''
631 631 *** runcommand debugwritestdout
632 632
633 633
634 634 run commandserver in commandserver, which is silly but should work:
635 635
636 636 >>> from __future__ import print_function
637 637 >>> from hgclient import readchannel, runcommand, check, stringio
638 638 >>> @check
639 639 ... def nested(server):
640 640 ... print('%c, %r' % readchannel(server))
641 641 ... class nestedserver(object):
642 642 ... stdin = stringio('getencoding\n')
643 643 ... stdout = stringio()
644 644 ... runcommand(server, ['serve', '--cmdserver', 'pipe'],
645 645 ... output=nestedserver.stdout, input=nestedserver.stdin)
646 646 ... nestedserver.stdout.seek(0)
647 647 ... print('%c, %r' % readchannel(nestedserver)) # hello
648 648 ... print('%c, %r' % readchannel(nestedserver)) # getencoding
649 649 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
650 650 *** runcommand serve --cmdserver pipe
651 651 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
652 652 r, '*' (glob)
653 653
654 654
655 655 start without repository:
656 656
657 657 $ cd ..
658 658
659 659 >>> from __future__ import print_function
660 660 >>> from hgclient import readchannel, runcommand, check
661 661 >>> @check
662 662 ... def hellomessage(server):
663 663 ... ch, data = readchannel(server)
664 664 ... print('%c, %r' % (ch, data))
665 665 ... # run an arbitrary command to make sure the next thing the server
666 666 ... # sends isn't part of the hello message
667 667 ... runcommand(server, ['id'])
668 668 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
669 669 *** runcommand id
670 670 abort: there is no Mercurial repository here (.hg not found)
671 671 [255]
672 672
673 673 >>> from hgclient import readchannel, runcommand, check
674 674 >>> @check
675 675 ... def startwithoutrepo(server):
676 676 ... readchannel(server)
677 677 ... runcommand(server, ['init', 'repo2'])
678 678 ... runcommand(server, ['id', '-R', 'repo2'])
679 679 *** runcommand init repo2
680 680 *** runcommand id -R repo2
681 681 000000000000 tip
682 682
683 683
684 684 don't fall back to cwd if invalid -R path is specified (issue4805):
685 685
686 686 $ cd repo
687 687 $ hg serve --cmdserver pipe -R ../nonexistent
688 688 abort: repository ../nonexistent not found!
689 689 [255]
690 690 $ cd ..
691 691
692 692
693 693 unix domain socket:
694 694
695 695 $ cd repo
696 696 $ hg update -q
697 697
698 698 #if unix-socket unix-permissions
699 699
700 700 >>> from __future__ import print_function
701 701 >>> from hgclient import unixserver, readchannel, runcommand, check, stringio
702 702 >>> server = unixserver('.hg/server.sock', '.hg/server.log')
703 703 >>> def hellomessage(conn):
704 704 ... ch, data = readchannel(conn)
705 705 ... print('%c, %r' % (ch, data))
706 706 ... runcommand(conn, ['id'])
707 707 >>> check(hellomessage, server.connect)
708 708 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
709 709 *** runcommand id
710 710 eff892de26ec tip bm1/bm2/bm3
711 711 >>> def unknowncommand(conn):
712 712 ... readchannel(conn)
713 713 ... conn.stdin.write('unknowncommand\n')
714 714 >>> check(unknowncommand, server.connect) # error sent to server.log
715 715 >>> def serverinput(conn):
716 716 ... readchannel(conn)
717 717 ... patch = """
718 718 ... # HG changeset patch
719 719 ... # User test
720 720 ... # Date 0 0
721 721 ... 2
722 722 ...
723 723 ... diff -r eff892de26ec -r 1ed24be7e7a0 a
724 724 ... --- a/a
725 725 ... +++ b/a
726 726 ... @@ -1,1 +1,2 @@
727 727 ... 1
728 728 ... +2
729 729 ... """
730 730 ... runcommand(conn, ['import', '-'], input=stringio(patch))
731 731 ... runcommand(conn, ['log', '-rtip', '-q'])
732 732 >>> check(serverinput, server.connect)
733 733 *** runcommand import -
734 734 applying patch from stdin
735 735 *** runcommand log -rtip -q
736 736 2:1ed24be7e7a0
737 737 >>> server.shutdown()
738 738
739 739 $ cat .hg/server.log
740 740 listening at .hg/server.sock
741 741 abort: unknown command unknowncommand
742 742 killed!
743 743 $ rm .hg/server.log
744 744
745 745 if server crashed before hello, traceback will be sent to 'e' channel as
746 746 last ditch:
747 747
748 748 $ cat <<EOF >> .hg/hgrc
749 749 > [cmdserver]
750 750 > log = inexistent/path.log
751 751 > EOF
752 752 >>> from __future__ import print_function
753 753 >>> from hgclient import unixserver, readchannel, check
754 754 >>> server = unixserver('.hg/server.sock', '.hg/server.log')
755 755 >>> def earlycrash(conn):
756 756 ... while True:
757 757 ... try:
758 758 ... ch, data = readchannel(conn)
759 759 ... if not data.startswith(' '):
760 760 ... print('%c, %r' % (ch, data))
761 761 ... except EOFError:
762 762 ... break
763 763 >>> check(earlycrash, server.connect)
764 764 e, 'Traceback (most recent call last):\n'
765 765 e, "IOError: *" (glob)
766 766 >>> server.shutdown()
767 767
768 768 $ cat .hg/server.log | grep -v '^ '
769 769 listening at .hg/server.sock
770 770 Traceback (most recent call last):
771 771 IOError: * (glob)
772 772 killed!
773 773 #endif
774 774 #if no-unix-socket
775 775
776 776 $ hg serve --cmdserver unix -a .hg/server.sock
777 777 abort: unsupported platform
778 778 [255]
779 779
780 780 #endif
781 781
782 782 $ cd ..
783 783
784 784 Test that accessing to invalid changelog cache is avoided at
785 785 subsequent operations even if repo object is reused even after failure
786 786 of transaction (see 0a7610758c42 also)
787 787
788 788 "hg log" after failure of transaction is needed to detect invalid
789 789 cache in repoview: this can't detect by "hg verify" only.
790 790
791 791 Combination of "finalization" and "empty-ness of changelog" (2 x 2 =
792 792 4) are tested, because '00changelog.i' are differently changed in each
793 793 cases.
794 794
795 795 $ cat > $TESTTMP/failafterfinalize.py <<EOF
796 796 > # extension to abort transaction after finalization forcibly
797 797 > from mercurial import commands, error, extensions, lock as lockmod
798 798 > def fail(tr):
799 799 > raise error.Abort('fail after finalization')
800 800 > def reposetup(ui, repo):
801 801 > class failrepo(repo.__class__):
802 802 > def commitctx(self, ctx, error=False):
803 803 > if self.ui.configbool('failafterfinalize', 'fail'):
804 804 > # 'sorted()' by ASCII code on category names causes
805 805 > # invoking 'fail' after finalization of changelog
806 806 > # using "'cl-%i' % id(self)" as category name
807 807 > self.currenttransaction().addfinalize('zzzzzzzz', fail)
808 808 > return super(failrepo, self).commitctx(ctx, error)
809 809 > repo.__class__ = failrepo
810 810 > EOF
811 811
812 812 $ hg init repo3
813 813 $ cd repo3
814 814
815 815 $ cat <<EOF >> $HGRCPATH
816 816 > [ui]
817 817 > logtemplate = {rev} {desc|firstline} ({files})\n
818 818 >
819 819 > [extensions]
820 820 > failafterfinalize = $TESTTMP/failafterfinalize.py
821 821 > EOF
822 822
823 823 - test failure with "empty changelog"
824 824
825 825 $ echo foo > foo
826 826 $ hg add foo
827 827
828 828 (failure before finalization)
829 829
830 830 >>> from hgclient import readchannel, runcommand, check
831 831 >>> @check
832 832 ... def abort(server):
833 833 ... readchannel(server)
834 834 ... runcommand(server, ['commit',
835 835 ... '--config', 'hooks.pretxncommit=false',
836 836 ... '-mfoo'])
837 837 ... runcommand(server, ['log'])
838 838 ... runcommand(server, ['verify', '-q'])
839 839 *** runcommand commit --config hooks.pretxncommit=false -mfoo
840 840 transaction abort!
841 841 rollback completed
842 842 abort: pretxncommit hook exited with status 1
843 843 [255]
844 844 *** runcommand log
845 845 *** runcommand verify -q
846 846
847 847 (failure after finalization)
848 848
849 849 >>> from hgclient import readchannel, runcommand, check
850 850 >>> @check
851 851 ... def abort(server):
852 852 ... readchannel(server)
853 853 ... runcommand(server, ['commit',
854 854 ... '--config', 'failafterfinalize.fail=true',
855 855 ... '-mfoo'])
856 856 ... runcommand(server, ['log'])
857 857 ... runcommand(server, ['verify', '-q'])
858 858 *** runcommand commit --config failafterfinalize.fail=true -mfoo
859 859 transaction abort!
860 860 rollback completed
861 861 abort: fail after finalization
862 862 [255]
863 863 *** runcommand log
864 864 *** runcommand verify -q
865 865
866 866 - test failure with "not-empty changelog"
867 867
868 868 $ echo bar > bar
869 869 $ hg add bar
870 870 $ hg commit -mbar bar
871 871
872 872 (failure before finalization)
873 873
874 874 >>> from hgclient import readchannel, runcommand, check
875 875 >>> @check
876 876 ... def abort(server):
877 877 ... readchannel(server)
878 878 ... runcommand(server, ['commit',
879 879 ... '--config', 'hooks.pretxncommit=false',
880 880 ... '-mfoo', 'foo'])
881 881 ... runcommand(server, ['log'])
882 882 ... runcommand(server, ['verify', '-q'])
883 883 *** runcommand commit --config hooks.pretxncommit=false -mfoo foo
884 884 transaction abort!
885 885 rollback completed
886 886 abort: pretxncommit hook exited with status 1
887 887 [255]
888 888 *** runcommand log
889 889 0 bar (bar)
890 890 *** runcommand verify -q
891 891
892 892 (failure after finalization)
893 893
894 894 >>> from hgclient import readchannel, runcommand, check
895 895 >>> @check
896 896 ... def abort(server):
897 897 ... readchannel(server)
898 898 ... runcommand(server, ['commit',
899 899 ... '--config', 'failafterfinalize.fail=true',
900 900 ... '-mfoo', 'foo'])
901 901 ... runcommand(server, ['log'])
902 902 ... runcommand(server, ['verify', '-q'])
903 903 *** runcommand commit --config failafterfinalize.fail=true -mfoo foo
904 904 transaction abort!
905 905 rollback completed
906 906 abort: fail after finalization
907 907 [255]
908 908 *** runcommand log
909 909 0 bar (bar)
910 910 *** runcommand verify -q
911
912 $ cd ..
913
914 Test symlink traversal over cached audited paths:
915 -------------------------------------------------
916
917 #if symlink
918
919 set up symlink hell
920
921 $ mkdir merge-symlink-out
922 $ hg init merge-symlink
923 $ cd merge-symlink
924 $ touch base
925 $ hg commit -qAm base
926 $ ln -s ../merge-symlink-out a
927 $ hg commit -qAm 'symlink a -> ../merge-symlink-out'
928 $ hg up -q 0
929 $ mkdir a
930 $ touch a/poisoned
931 $ hg commit -qAm 'file a/poisoned'
932 $ hg log -G -T '{rev}: {desc}\n'
933 @ 2: file a/poisoned
934 |
935 | o 1: symlink a -> ../merge-symlink-out
936 |/
937 o 0: base
938
939
940 try trivial merge after update: cache of audited paths should be discarded,
941 and the merge should fail (issue5628)
942
943 $ hg up -q null
944 >>> from hgclient import readchannel, runcommand, check
945 >>> @check
946 ... def merge(server):
947 ... readchannel(server)
948 ... # audit a/poisoned as a good path
949 ... runcommand(server, ['up', '-qC', '2'])
950 ... runcommand(server, ['up', '-qC', '1'])
951 ... # here a is a symlink, so a/poisoned is bad
952 ... runcommand(server, ['merge', '2'])
953 *** runcommand up -qC 2
954 *** runcommand up -qC 1
955 *** runcommand merge 2
956 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
957 (branch merge, don't forget to commit)
958 $ ls ../merge-symlink-out
959 poisoned
960
961 cache of repo.auditor should be discarded, so matcher would never traverse
962 symlinks:
963
964 $ hg up -qC 0
965 $ touch ../merge-symlink-out/poisoned
966 >>> from hgclient import readchannel, runcommand, check
967 >>> @check
968 ... def files(server):
969 ... readchannel(server)
970 ... runcommand(server, ['up', '-qC', '2'])
971 ... # audit a/poisoned as a good path
972 ... runcommand(server, ['files', 'a/poisoned'])
973 ... runcommand(server, ['up', '-qC', '0'])
974 ... runcommand(server, ['up', '-qC', '1'])
975 ... # here 'a' is a symlink, so a/poisoned should be warned
976 ... runcommand(server, ['files', 'a/poisoned'])
977 *** runcommand up -qC 2
978 *** runcommand files a/poisoned
979 a/poisoned
980 *** runcommand up -qC 0
981 *** runcommand up -qC 1
982 *** runcommand files a/poisoned
983 [1]
984
985 $ cd ..
986
987 #endif
General Comments 0
You need to be logged in to leave comments. Login now