##// END OF EJS Templates
tests: show cache of audited paths is never invalidated
Yuya Nishihara -
r33704:0134d839 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,913 +1,990 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 defaults.backout=-d "0 0"
191 191 defaults.commit=-d "0 0"
192 192 defaults.shelve=--date "0 0"
193 193 defaults.tag=-d "0 0"
194 194 devel.all-warnings=true
195 195 largefiles.usercache=$TESTTMP/.cache/largefiles
196 196 ui.slash=True
197 197 ui.interactive=False
198 198 ui.mergemarkers=detailed
199 199 ui.usehttp2=true (?)
200 200 ui.foo=bar
201 201 ui.nontty=true
202 202 web.address=localhost
203 203 web\.ipv6=(?:True|False) (re)
204 204 *** runcommand init foo
205 205 *** runcommand -R foo showconfig ui defaults
206 206 defaults.backout=-d "0 0"
207 207 defaults.commit=-d "0 0"
208 208 defaults.shelve=--date "0 0"
209 209 defaults.tag=-d "0 0"
210 210 ui.slash=True
211 211 ui.interactive=False
212 212 ui.mergemarkers=detailed
213 213 ui.usehttp2=true (?)
214 214 ui.nontty=true
215 215
216 216 $ rm -R foo
217 217
218 218 #if windows
219 219 $ PYTHONPATH="$TESTTMP/repo;$PYTHONPATH"
220 220 #else
221 221 $ PYTHONPATH="$TESTTMP/repo:$PYTHONPATH"
222 222 #endif
223 223
224 224 $ cat <<EOF > hook.py
225 225 > from __future__ import print_function
226 226 > import sys
227 227 > def hook(**args):
228 228 > print('hook talking')
229 229 > print('now try to read something: %r' % sys.stdin.read())
230 230 > EOF
231 231
232 232 >>> from hgclient import readchannel, runcommand, check, stringio
233 233 >>> @check
234 234 ... def hookoutput(server):
235 235 ... readchannel(server)
236 236 ... runcommand(server, ['--config',
237 237 ... 'hooks.pre-identify=python:hook.hook',
238 238 ... 'id'],
239 239 ... input=stringio('some input'))
240 240 *** runcommand --config hooks.pre-identify=python:hook.hook id
241 241 eff892de26ec tip
242 242
243 243 $ rm hook.py*
244 244
245 245 $ echo a >> a
246 246 >>> import os
247 247 >>> from hgclient import readchannel, runcommand, check
248 248 >>> @check
249 249 ... def outsidechanges(server):
250 250 ... readchannel(server)
251 251 ... runcommand(server, ['status'])
252 252 ... os.system('hg ci -Am2')
253 253 ... runcommand(server, ['tip'])
254 254 ... runcommand(server, ['status'])
255 255 *** runcommand status
256 256 M a
257 257 *** runcommand tip
258 258 changeset: 1:d3a0a68be6de
259 259 tag: tip
260 260 user: test
261 261 date: Thu Jan 01 00:00:00 1970 +0000
262 262 summary: 2
263 263
264 264 *** runcommand status
265 265
266 266 >>> import os
267 267 >>> from hgclient import readchannel, runcommand, check
268 268 >>> @check
269 269 ... def bookmarks(server):
270 270 ... readchannel(server)
271 271 ... runcommand(server, ['bookmarks'])
272 272 ...
273 273 ... # changes .hg/bookmarks
274 274 ... os.system('hg bookmark -i bm1')
275 275 ... os.system('hg bookmark -i bm2')
276 276 ... runcommand(server, ['bookmarks'])
277 277 ...
278 278 ... # changes .hg/bookmarks.current
279 279 ... os.system('hg upd bm1 -q')
280 280 ... runcommand(server, ['bookmarks'])
281 281 ...
282 282 ... runcommand(server, ['bookmarks', 'bm3'])
283 283 ... f = open('a', 'ab')
284 284 ... f.write('a\n')
285 285 ... f.close()
286 286 ... runcommand(server, ['commit', '-Amm'])
287 287 ... runcommand(server, ['bookmarks'])
288 288 *** runcommand bookmarks
289 289 no bookmarks set
290 290 *** runcommand bookmarks
291 291 bm1 1:d3a0a68be6de
292 292 bm2 1:d3a0a68be6de
293 293 *** runcommand bookmarks
294 294 * bm1 1:d3a0a68be6de
295 295 bm2 1:d3a0a68be6de
296 296 *** runcommand bookmarks bm3
297 297 *** runcommand commit -Amm
298 298 *** runcommand bookmarks
299 299 bm1 1:d3a0a68be6de
300 300 bm2 1:d3a0a68be6de
301 301 * bm3 2:aef17e88f5f0
302 302
303 303 >>> import os
304 304 >>> from hgclient import readchannel, runcommand, check
305 305 >>> @check
306 306 ... def tagscache(server):
307 307 ... readchannel(server)
308 308 ... runcommand(server, ['id', '-t', '-r', '0'])
309 309 ... os.system('hg tag -r 0 foo')
310 310 ... runcommand(server, ['id', '-t', '-r', '0'])
311 311 *** runcommand id -t -r 0
312 312
313 313 *** runcommand id -t -r 0
314 314 foo
315 315
316 316 >>> import os
317 317 >>> from hgclient import readchannel, runcommand, check
318 318 >>> @check
319 319 ... def setphase(server):
320 320 ... readchannel(server)
321 321 ... runcommand(server, ['phase', '-r', '.'])
322 322 ... os.system('hg phase -r . -p')
323 323 ... runcommand(server, ['phase', '-r', '.'])
324 324 *** runcommand phase -r .
325 325 3: draft
326 326 *** runcommand phase -r .
327 327 3: public
328 328
329 329 $ echo a >> a
330 330 >>> from hgclient import readchannel, runcommand, check
331 331 >>> @check
332 332 ... def rollback(server):
333 333 ... readchannel(server)
334 334 ... runcommand(server, ['phase', '-r', '.', '-p'])
335 335 ... runcommand(server, ['commit', '-Am.'])
336 336 ... runcommand(server, ['rollback'])
337 337 ... runcommand(server, ['phase', '-r', '.'])
338 338 *** runcommand phase -r . -p
339 339 no phases changed
340 340 *** runcommand commit -Am.
341 341 *** runcommand rollback
342 342 repository tip rolled back to revision 3 (undo commit)
343 343 working directory now based on revision 3
344 344 *** runcommand phase -r .
345 345 3: public
346 346
347 347 >>> import os
348 348 >>> from hgclient import readchannel, runcommand, check
349 349 >>> @check
350 350 ... def branch(server):
351 351 ... readchannel(server)
352 352 ... runcommand(server, ['branch'])
353 353 ... os.system('hg branch foo')
354 354 ... runcommand(server, ['branch'])
355 355 ... os.system('hg branch default')
356 356 *** runcommand branch
357 357 default
358 358 marked working directory as branch foo
359 359 (branches are permanent and global, did you want a bookmark?)
360 360 *** runcommand branch
361 361 foo
362 362 marked working directory as branch default
363 363 (branches are permanent and global, did you want a bookmark?)
364 364
365 365 $ touch .hgignore
366 366 >>> import os
367 367 >>> from hgclient import readchannel, runcommand, check
368 368 >>> @check
369 369 ... def hgignore(server):
370 370 ... readchannel(server)
371 371 ... runcommand(server, ['commit', '-Am.'])
372 372 ... f = open('ignored-file', 'ab')
373 373 ... f.write('')
374 374 ... f.close()
375 375 ... f = open('.hgignore', 'ab')
376 376 ... f.write('ignored-file')
377 377 ... f.close()
378 378 ... runcommand(server, ['status', '-i', '-u'])
379 379 *** runcommand commit -Am.
380 380 adding .hgignore
381 381 *** runcommand status -i -u
382 382 I ignored-file
383 383
384 384 cache of non-public revisions should be invalidated on repository change
385 385 (issue4855):
386 386
387 387 >>> import os
388 388 >>> from hgclient import readchannel, runcommand, check
389 389 >>> @check
390 390 ... def phasesetscacheaftercommit(server):
391 391 ... readchannel(server)
392 392 ... # load _phasecache._phaserevs and _phasesets
393 393 ... runcommand(server, ['log', '-qr', 'draft()'])
394 394 ... # create draft commits by another process
395 395 ... for i in xrange(5, 7):
396 396 ... f = open('a', 'ab')
397 397 ... f.seek(0, os.SEEK_END)
398 398 ... f.write('a\n')
399 399 ... f.close()
400 400 ... os.system('hg commit -Aqm%d' % i)
401 401 ... # new commits should be listed as draft revisions
402 402 ... runcommand(server, ['log', '-qr', 'draft()'])
403 403 *** runcommand log -qr draft()
404 404 4:7966c8e3734d
405 405 *** runcommand log -qr draft()
406 406 4:7966c8e3734d
407 407 5:41f6602d1c4f
408 408 6:10501e202c35
409 409
410 410 >>> import os
411 411 >>> from hgclient import readchannel, runcommand, check
412 412 >>> @check
413 413 ... def phasesetscacheafterstrip(server):
414 414 ... readchannel(server)
415 415 ... # load _phasecache._phaserevs and _phasesets
416 416 ... runcommand(server, ['log', '-qr', 'draft()'])
417 417 ... # strip cached revisions by another process
418 418 ... os.system('hg --config extensions.strip= strip -q 5')
419 419 ... # shouldn't abort by "unknown revision '6'"
420 420 ... runcommand(server, ['log', '-qr', 'draft()'])
421 421 *** runcommand log -qr draft()
422 422 4:7966c8e3734d
423 423 5:41f6602d1c4f
424 424 6:10501e202c35
425 425 *** runcommand log -qr draft()
426 426 4:7966c8e3734d
427 427
428 428 cache of phase roots should be invalidated on strip (issue3827):
429 429
430 430 >>> import os
431 431 >>> from hgclient import readchannel, sep, runcommand, check
432 432 >>> @check
433 433 ... def phasecacheafterstrip(server):
434 434 ... readchannel(server)
435 435 ...
436 436 ... # create new head, 5:731265503d86
437 437 ... runcommand(server, ['update', '-C', '0'])
438 438 ... f = open('a', 'ab')
439 439 ... f.write('a\n')
440 440 ... f.close()
441 441 ... runcommand(server, ['commit', '-Am.', 'a'])
442 442 ... runcommand(server, ['log', '-Gq'])
443 443 ...
444 444 ... # make it public; draft marker moves to 4:7966c8e3734d
445 445 ... runcommand(server, ['phase', '-p', '.'])
446 446 ... # load _phasecache.phaseroots
447 447 ... runcommand(server, ['phase', '.'], outfilter=sep)
448 448 ...
449 449 ... # strip 1::4 outside server
450 450 ... os.system('hg -q --config extensions.mq= strip 1')
451 451 ...
452 452 ... # shouldn't raise "7966c8e3734d: no node!"
453 453 ... runcommand(server, ['branches'])
454 454 *** runcommand update -C 0
455 455 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
456 456 (leaving bookmark bm3)
457 457 *** runcommand commit -Am. a
458 458 created new head
459 459 *** runcommand log -Gq
460 460 @ 5:731265503d86
461 461 |
462 462 | o 4:7966c8e3734d
463 463 | |
464 464 | o 3:b9b85890c400
465 465 | |
466 466 | o 2:aef17e88f5f0
467 467 | |
468 468 | o 1:d3a0a68be6de
469 469 |/
470 470 o 0:eff892de26ec
471 471
472 472 *** runcommand phase -p .
473 473 *** runcommand phase .
474 474 5: public
475 475 *** runcommand branches
476 476 default 1:731265503d86
477 477
478 478 in-memory cache must be reloaded if transaction is aborted. otherwise
479 479 changelog and manifest would have invalid node:
480 480
481 481 $ echo a >> a
482 482 >>> from hgclient import readchannel, runcommand, check
483 483 >>> @check
484 484 ... def txabort(server):
485 485 ... readchannel(server)
486 486 ... runcommand(server, ['commit', '--config', 'hooks.pretxncommit=false',
487 487 ... '-mfoo'])
488 488 ... runcommand(server, ['verify'])
489 489 *** runcommand commit --config hooks.pretxncommit=false -mfoo
490 490 transaction abort!
491 491 rollback completed
492 492 abort: pretxncommit hook exited with status 1
493 493 [255]
494 494 *** runcommand verify
495 495 checking changesets
496 496 checking manifests
497 497 crosschecking files in changesets and manifests
498 498 checking files
499 499 1 files, 2 changesets, 2 total revisions
500 500 $ hg revert --no-backup -aq
501 501
502 502 $ cat >> .hg/hgrc << EOF
503 503 > [experimental]
504 504 > evolution=createmarkers
505 505 > EOF
506 506
507 507 >>> import os
508 508 >>> from hgclient import readchannel, runcommand, check
509 509 >>> @check
510 510 ... def obsolete(server):
511 511 ... readchannel(server)
512 512 ...
513 513 ... runcommand(server, ['up', 'null'])
514 514 ... runcommand(server, ['phase', '-df', 'tip'])
515 515 ... cmd = 'hg debugobsolete `hg log -r tip --template {node}`'
516 516 ... if os.name == 'nt':
517 517 ... cmd = 'sh -c "%s"' % cmd # run in sh, not cmd.exe
518 518 ... os.system(cmd)
519 519 ... runcommand(server, ['log', '--hidden'])
520 520 ... runcommand(server, ['log'])
521 521 *** runcommand up null
522 522 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
523 523 *** runcommand phase -df tip
524 524 *** runcommand log --hidden
525 525 changeset: 1:731265503d86
526 526 tag: tip
527 527 user: test
528 528 date: Thu Jan 01 00:00:00 1970 +0000
529 529 summary: .
530 530
531 531 changeset: 0:eff892de26ec
532 532 bookmark: bm1
533 533 bookmark: bm2
534 534 bookmark: bm3
535 535 user: test
536 536 date: Thu Jan 01 00:00:00 1970 +0000
537 537 summary: 1
538 538
539 539 *** runcommand log
540 540 changeset: 0:eff892de26ec
541 541 bookmark: bm1
542 542 bookmark: bm2
543 543 bookmark: bm3
544 544 tag: tip
545 545 user: test
546 546 date: Thu Jan 01 00:00:00 1970 +0000
547 547 summary: 1
548 548
549 549
550 550 $ cat <<EOF >> .hg/hgrc
551 551 > [extensions]
552 552 > mq =
553 553 > EOF
554 554
555 555 >>> import os
556 556 >>> from hgclient import readchannel, runcommand, check
557 557 >>> @check
558 558 ... def mqoutsidechanges(server):
559 559 ... readchannel(server)
560 560 ...
561 561 ... # load repo.mq
562 562 ... runcommand(server, ['qapplied'])
563 563 ... os.system('hg qnew 0.diff')
564 564 ... # repo.mq should be invalidated
565 565 ... runcommand(server, ['qapplied'])
566 566 ...
567 567 ... runcommand(server, ['qpop', '--all'])
568 568 ... os.system('hg qqueue --create foo')
569 569 ... # repo.mq should be recreated to point to new queue
570 570 ... runcommand(server, ['qqueue', '--active'])
571 571 *** runcommand qapplied
572 572 *** runcommand qapplied
573 573 0.diff
574 574 *** runcommand qpop --all
575 575 popping 0.diff
576 576 patch queue now empty
577 577 *** runcommand qqueue --active
578 578 foo
579 579
580 580 $ cat <<EOF > dbgui.py
581 581 > import os, sys
582 582 > from mercurial import cmdutil, commands
583 583 > cmdtable = {}
584 584 > command = cmdutil.command(cmdtable)
585 585 > @command("debuggetpass", norepo=True)
586 586 > def debuggetpass(ui):
587 587 > ui.write("%s\\n" % ui.getpass())
588 588 > @command("debugprompt", norepo=True)
589 589 > def debugprompt(ui):
590 590 > ui.write("%s\\n" % ui.prompt("prompt:"))
591 591 > @command("debugreadstdin", norepo=True)
592 592 > def debugreadstdin(ui):
593 593 > ui.write("read: %r\n" % sys.stdin.read(1))
594 594 > @command("debugwritestdout", norepo=True)
595 595 > def debugwritestdout(ui):
596 596 > os.write(1, "low-level stdout fd and\n")
597 597 > sys.stdout.write("stdout should be redirected to /dev/null\n")
598 598 > sys.stdout.flush()
599 599 > EOF
600 600 $ cat <<EOF >> .hg/hgrc
601 601 > [extensions]
602 602 > dbgui = dbgui.py
603 603 > EOF
604 604
605 605 >>> from hgclient import readchannel, runcommand, check, stringio
606 606 >>> @check
607 607 ... def getpass(server):
608 608 ... readchannel(server)
609 609 ... runcommand(server, ['debuggetpass', '--config',
610 610 ... 'ui.interactive=True'],
611 611 ... input=stringio('1234\n'))
612 612 ... runcommand(server, ['debuggetpass', '--config',
613 613 ... 'ui.interactive=True'],
614 614 ... input=stringio('\n'))
615 615 ... runcommand(server, ['debuggetpass', '--config',
616 616 ... 'ui.interactive=True'],
617 617 ... input=stringio(''))
618 618 ... runcommand(server, ['debugprompt', '--config',
619 619 ... 'ui.interactive=True'],
620 620 ... input=stringio('5678\n'))
621 621 ... runcommand(server, ['debugreadstdin'])
622 622 ... runcommand(server, ['debugwritestdout'])
623 623 *** runcommand debuggetpass --config ui.interactive=True
624 624 password: 1234
625 625 *** runcommand debuggetpass --config ui.interactive=True
626 626 password:
627 627 *** runcommand debuggetpass --config ui.interactive=True
628 628 password: abort: response expected
629 629 [255]
630 630 *** runcommand debugprompt --config ui.interactive=True
631 631 prompt: 5678
632 632 *** runcommand debugreadstdin
633 633 read: ''
634 634 *** runcommand debugwritestdout
635 635
636 636
637 637 run commandserver in commandserver, which is silly but should work:
638 638
639 639 >>> from __future__ import print_function
640 640 >>> from hgclient import readchannel, runcommand, check, stringio
641 641 >>> @check
642 642 ... def nested(server):
643 643 ... print('%c, %r' % readchannel(server))
644 644 ... class nestedserver(object):
645 645 ... stdin = stringio('getencoding\n')
646 646 ... stdout = stringio()
647 647 ... runcommand(server, ['serve', '--cmdserver', 'pipe'],
648 648 ... output=nestedserver.stdout, input=nestedserver.stdin)
649 649 ... nestedserver.stdout.seek(0)
650 650 ... print('%c, %r' % readchannel(nestedserver)) # hello
651 651 ... print('%c, %r' % readchannel(nestedserver)) # getencoding
652 652 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
653 653 *** runcommand serve --cmdserver pipe
654 654 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
655 655 r, '*' (glob)
656 656
657 657
658 658 start without repository:
659 659
660 660 $ cd ..
661 661
662 662 >>> from __future__ import print_function
663 663 >>> from hgclient import readchannel, runcommand, check
664 664 >>> @check
665 665 ... def hellomessage(server):
666 666 ... ch, data = readchannel(server)
667 667 ... print('%c, %r' % (ch, data))
668 668 ... # run an arbitrary command to make sure the next thing the server
669 669 ... # sends isn't part of the hello message
670 670 ... runcommand(server, ['id'])
671 671 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
672 672 *** runcommand id
673 673 abort: there is no Mercurial repository here (.hg not found)
674 674 [255]
675 675
676 676 >>> from hgclient import readchannel, runcommand, check
677 677 >>> @check
678 678 ... def startwithoutrepo(server):
679 679 ... readchannel(server)
680 680 ... runcommand(server, ['init', 'repo2'])
681 681 ... runcommand(server, ['id', '-R', 'repo2'])
682 682 *** runcommand init repo2
683 683 *** runcommand id -R repo2
684 684 000000000000 tip
685 685
686 686
687 687 don't fall back to cwd if invalid -R path is specified (issue4805):
688 688
689 689 $ cd repo
690 690 $ hg serve --cmdserver pipe -R ../nonexistent
691 691 abort: repository ../nonexistent not found!
692 692 [255]
693 693 $ cd ..
694 694
695 695
696 696 unix domain socket:
697 697
698 698 $ cd repo
699 699 $ hg update -q
700 700
701 701 #if unix-socket unix-permissions
702 702
703 703 >>> from __future__ import print_function
704 704 >>> from hgclient import unixserver, readchannel, runcommand, check, stringio
705 705 >>> server = unixserver('.hg/server.sock', '.hg/server.log')
706 706 >>> def hellomessage(conn):
707 707 ... ch, data = readchannel(conn)
708 708 ... print('%c, %r' % (ch, data))
709 709 ... runcommand(conn, ['id'])
710 710 >>> check(hellomessage, server.connect)
711 711 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
712 712 *** runcommand id
713 713 eff892de26ec tip bm1/bm2/bm3
714 714 >>> def unknowncommand(conn):
715 715 ... readchannel(conn)
716 716 ... conn.stdin.write('unknowncommand\n')
717 717 >>> check(unknowncommand, server.connect) # error sent to server.log
718 718 >>> def serverinput(conn):
719 719 ... readchannel(conn)
720 720 ... patch = """
721 721 ... # HG changeset patch
722 722 ... # User test
723 723 ... # Date 0 0
724 724 ... 2
725 725 ...
726 726 ... diff -r eff892de26ec -r 1ed24be7e7a0 a
727 727 ... --- a/a
728 728 ... +++ b/a
729 729 ... @@ -1,1 +1,2 @@
730 730 ... 1
731 731 ... +2
732 732 ... """
733 733 ... runcommand(conn, ['import', '-'], input=stringio(patch))
734 734 ... runcommand(conn, ['log', '-rtip', '-q'])
735 735 >>> check(serverinput, server.connect)
736 736 *** runcommand import -
737 737 applying patch from stdin
738 738 *** runcommand log -rtip -q
739 739 2:1ed24be7e7a0
740 740 >>> server.shutdown()
741 741
742 742 $ cat .hg/server.log
743 743 listening at .hg/server.sock
744 744 abort: unknown command unknowncommand
745 745 killed!
746 746 $ rm .hg/server.log
747 747
748 748 if server crashed before hello, traceback will be sent to 'e' channel as
749 749 last ditch:
750 750
751 751 $ cat <<EOF >> .hg/hgrc
752 752 > [cmdserver]
753 753 > log = inexistent/path.log
754 754 > EOF
755 755 >>> from __future__ import print_function
756 756 >>> from hgclient import unixserver, readchannel, check
757 757 >>> server = unixserver('.hg/server.sock', '.hg/server.log')
758 758 >>> def earlycrash(conn):
759 759 ... while True:
760 760 ... try:
761 761 ... ch, data = readchannel(conn)
762 762 ... if not data.startswith(' '):
763 763 ... print('%c, %r' % (ch, data))
764 764 ... except EOFError:
765 765 ... break
766 766 >>> check(earlycrash, server.connect)
767 767 e, 'Traceback (most recent call last):\n'
768 768 e, "IOError: *" (glob)
769 769 >>> server.shutdown()
770 770
771 771 $ cat .hg/server.log | grep -v '^ '
772 772 listening at .hg/server.sock
773 773 Traceback (most recent call last):
774 774 IOError: * (glob)
775 775 killed!
776 776 #endif
777 777 #if no-unix-socket
778 778
779 779 $ hg serve --cmdserver unix -a .hg/server.sock
780 780 abort: unsupported platform
781 781 [255]
782 782
783 783 #endif
784 784
785 785 $ cd ..
786 786
787 787 Test that accessing to invalid changelog cache is avoided at
788 788 subsequent operations even if repo object is reused even after failure
789 789 of transaction (see 0a7610758c42 also)
790 790
791 791 "hg log" after failure of transaction is needed to detect invalid
792 792 cache in repoview: this can't detect by "hg verify" only.
793 793
794 794 Combination of "finalization" and "empty-ness of changelog" (2 x 2 =
795 795 4) are tested, because '00changelog.i' are differently changed in each
796 796 cases.
797 797
798 798 $ cat > $TESTTMP/failafterfinalize.py <<EOF
799 799 > # extension to abort transaction after finalization forcibly
800 800 > from mercurial import commands, error, extensions, lock as lockmod
801 801 > def fail(tr):
802 802 > raise error.Abort('fail after finalization')
803 803 > def reposetup(ui, repo):
804 804 > class failrepo(repo.__class__):
805 805 > def commitctx(self, ctx, error=False):
806 806 > if self.ui.configbool('failafterfinalize', 'fail'):
807 807 > # 'sorted()' by ASCII code on category names causes
808 808 > # invoking 'fail' after finalization of changelog
809 809 > # using "'cl-%i' % id(self)" as category name
810 810 > self.currenttransaction().addfinalize('zzzzzzzz', fail)
811 811 > return super(failrepo, self).commitctx(ctx, error)
812 812 > repo.__class__ = failrepo
813 813 > EOF
814 814
815 815 $ hg init repo3
816 816 $ cd repo3
817 817
818 818 $ cat <<EOF >> $HGRCPATH
819 819 > [ui]
820 820 > logtemplate = {rev} {desc|firstline} ({files})\n
821 821 >
822 822 > [extensions]
823 823 > failafterfinalize = $TESTTMP/failafterfinalize.py
824 824 > EOF
825 825
826 826 - test failure with "empty changelog"
827 827
828 828 $ echo foo > foo
829 829 $ hg add foo
830 830
831 831 (failure before finalization)
832 832
833 833 >>> from hgclient import readchannel, runcommand, check
834 834 >>> @check
835 835 ... def abort(server):
836 836 ... readchannel(server)
837 837 ... runcommand(server, ['commit',
838 838 ... '--config', 'hooks.pretxncommit=false',
839 839 ... '-mfoo'])
840 840 ... runcommand(server, ['log'])
841 841 ... runcommand(server, ['verify', '-q'])
842 842 *** runcommand commit --config hooks.pretxncommit=false -mfoo
843 843 transaction abort!
844 844 rollback completed
845 845 abort: pretxncommit hook exited with status 1
846 846 [255]
847 847 *** runcommand log
848 848 *** runcommand verify -q
849 849
850 850 (failure after finalization)
851 851
852 852 >>> from hgclient import readchannel, runcommand, check
853 853 >>> @check
854 854 ... def abort(server):
855 855 ... readchannel(server)
856 856 ... runcommand(server, ['commit',
857 857 ... '--config', 'failafterfinalize.fail=true',
858 858 ... '-mfoo'])
859 859 ... runcommand(server, ['log'])
860 860 ... runcommand(server, ['verify', '-q'])
861 861 *** runcommand commit --config failafterfinalize.fail=true -mfoo
862 862 transaction abort!
863 863 rollback completed
864 864 abort: fail after finalization
865 865 [255]
866 866 *** runcommand log
867 867 *** runcommand verify -q
868 868
869 869 - test failure with "not-empty changelog"
870 870
871 871 $ echo bar > bar
872 872 $ hg add bar
873 873 $ hg commit -mbar bar
874 874
875 875 (failure before finalization)
876 876
877 877 >>> from hgclient import readchannel, runcommand, check
878 878 >>> @check
879 879 ... def abort(server):
880 880 ... readchannel(server)
881 881 ... runcommand(server, ['commit',
882 882 ... '--config', 'hooks.pretxncommit=false',
883 883 ... '-mfoo', 'foo'])
884 884 ... runcommand(server, ['log'])
885 885 ... runcommand(server, ['verify', '-q'])
886 886 *** runcommand commit --config hooks.pretxncommit=false -mfoo foo
887 887 transaction abort!
888 888 rollback completed
889 889 abort: pretxncommit hook exited with status 1
890 890 [255]
891 891 *** runcommand log
892 892 0 bar (bar)
893 893 *** runcommand verify -q
894 894
895 895 (failure after finalization)
896 896
897 897 >>> from hgclient import readchannel, runcommand, check
898 898 >>> @check
899 899 ... def abort(server):
900 900 ... readchannel(server)
901 901 ... runcommand(server, ['commit',
902 902 ... '--config', 'failafterfinalize.fail=true',
903 903 ... '-mfoo', 'foo'])
904 904 ... runcommand(server, ['log'])
905 905 ... runcommand(server, ['verify', '-q'])
906 906 *** runcommand commit --config failafterfinalize.fail=true -mfoo foo
907 907 transaction abort!
908 908 rollback completed
909 909 abort: fail after finalization
910 910 [255]
911 911 *** runcommand log
912 912 0 bar (bar)
913 913 *** runcommand verify -q
914
915 $ cd ..
916
917 Test symlink traversal over cached audited paths:
918 -------------------------------------------------
919
920 #if symlink
921
922 set up symlink hell
923
924 $ mkdir merge-symlink-out
925 $ hg init merge-symlink
926 $ cd merge-symlink
927 $ touch base
928 $ hg commit -qAm base
929 $ ln -s ../merge-symlink-out a
930 $ hg commit -qAm 'symlink a -> ../merge-symlink-out'
931 $ hg up -q 0
932 $ mkdir a
933 $ touch a/poisoned
934 $ hg commit -qAm 'file a/poisoned'
935 $ hg log -G -T '{rev}: {desc}\n'
936 @ 2: file a/poisoned
937 |
938 | o 1: symlink a -> ../merge-symlink-out
939 |/
940 o 0: base
941
942
943 try trivial merge after update: cache of audited paths should be discarded,
944 and the merge should fail (issue5628)
945
946 $ hg up -q null
947 >>> from hgclient import readchannel, runcommand, check
948 >>> @check
949 ... def merge(server):
950 ... readchannel(server)
951 ... # audit a/poisoned as a good path
952 ... runcommand(server, ['up', '-qC', '2'])
953 ... runcommand(server, ['up', '-qC', '1'])
954 ... # here a is a symlink, so a/poisoned is bad
955 ... runcommand(server, ['merge', '2'])
956 *** runcommand up -qC 2
957 *** runcommand up -qC 1
958 *** runcommand merge 2
959 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
960 (branch merge, don't forget to commit)
961 $ ls ../merge-symlink-out
962 poisoned
963
964 cache of repo.auditor should be discarded, so matcher would never traverse
965 symlinks:
966
967 $ hg up -qC 0
968 $ touch ../merge-symlink-out/poisoned
969 >>> from hgclient import readchannel, runcommand, check
970 >>> @check
971 ... def files(server):
972 ... readchannel(server)
973 ... runcommand(server, ['up', '-qC', '2'])
974 ... # audit a/poisoned as a good path
975 ... runcommand(server, ['files', 'a/poisoned'])
976 ... runcommand(server, ['up', '-qC', '0'])
977 ... runcommand(server, ['up', '-qC', '1'])
978 ... # here 'a' is a symlink, so a/poisoned should be warned
979 ... runcommand(server, ['files', 'a/poisoned'])
980 *** runcommand up -qC 2
981 *** runcommand files a/poisoned
982 a/poisoned
983 *** runcommand up -qC 0
984 *** runcommand up -qC 1
985 *** runcommand files a/poisoned
986 [1]
987
988 $ cd ..
989
990 #endif
General Comments 0
You need to be logged in to leave comments. Login now