##// END OF EJS Templates
test-revert: add methodical revert to parent for working directory...
Pierre-Yves David -
r22128:db23fb4e default
parent child Browse files
Show More
@@ -1,553 +1,574
1 1 $ hg init repo
2 2 $ cd repo
3 3 $ echo 123 > a
4 4 $ echo 123 > c
5 5 $ echo 123 > e
6 6 $ hg add a c e
7 7 $ hg commit -m "first" a c e
8 8
9 9 nothing changed
10 10
11 11 $ hg revert
12 12 abort: no files or directories specified
13 13 (use --all to revert all files)
14 14 [255]
15 15 $ hg revert --all
16 16
17 17 Introduce some changes and revert them
18 18 --------------------------------------
19 19
20 20 $ echo 123 > b
21 21
22 22 $ hg status
23 23 ? b
24 24 $ echo 12 > c
25 25
26 26 $ hg status
27 27 M c
28 28 ? b
29 29 $ hg add b
30 30
31 31 $ hg status
32 32 M c
33 33 A b
34 34 $ hg rm a
35 35
36 36 $ hg status
37 37 M c
38 38 A b
39 39 R a
40 40
41 41 revert removal of a file
42 42
43 43 $ hg revert a
44 44 $ hg status
45 45 M c
46 46 A b
47 47
48 48 revert addition of a file
49 49
50 50 $ hg revert b
51 51 $ hg status
52 52 M c
53 53 ? b
54 54
55 55 revert modification of a file (--no-backup)
56 56
57 57 $ hg revert --no-backup c
58 58 $ hg status
59 59 ? b
60 60
61 61 revert deletion (! status) of a added file
62 62 ------------------------------------------
63 63
64 64 $ hg add b
65 65
66 66 $ hg status b
67 67 A b
68 68 $ rm b
69 69 $ hg status b
70 70 ! b
71 71 $ hg revert -v b
72 72 forgetting b
73 73 $ hg status b
74 74 b: * (glob)
75 75
76 76 $ ls
77 77 a
78 78 c
79 79 e
80 80
81 81 Test creation of backup (.orig) files
82 82 -------------------------------------
83 83
84 84 $ echo z > e
85 85 $ hg revert --all -v
86 86 saving current version of e as e.orig
87 87 reverting e
88 88
89 89 revert on clean file (no change)
90 90 --------------------------------
91 91
92 92 $ hg revert a
93 93 no changes needed to a
94 94
95 95 revert on an untracked file
96 96 ---------------------------
97 97
98 98 $ echo q > q
99 99 $ hg revert q
100 100 file not managed: q
101 101 $ rm q
102 102
103 103 revert on file that does not exists
104 104 -----------------------------------
105 105
106 106 $ hg revert notfound
107 107 notfound: no such file in rev 334a9e57682c
108 108 $ touch d
109 109 $ hg add d
110 110 $ hg rm a
111 111 $ hg commit -m "second"
112 112 $ echo z > z
113 113 $ hg add z
114 114 $ hg st
115 115 A z
116 116 ? e.orig
117 117
118 118 revert to another revision (--rev)
119 119 ----------------------------------
120 120
121 121 $ hg revert --all -r0
122 122 adding a
123 123 removing d
124 124 forgetting z
125 125
126 126 revert explicitly to parent (--rev)
127 127 -----------------------------------
128 128
129 129 $ hg revert --all -rtip
130 130 forgetting a
131 131 undeleting d
132 132 $ rm a *.orig
133 133
134 134 revert to another revision (--rev) and exact match
135 135 --------------------------------------------------
136 136
137 137 exact match are more silent
138 138
139 139 $ hg revert -r0 a
140 140 $ hg st a
141 141 A a
142 142 $ hg rm d
143 143 $ hg st d
144 144 R d
145 145
146 146 should silently keep d removed
147 147
148 148 $ hg revert -r0 d
149 149 $ hg st d
150 150 R d
151 151
152 152 $ hg update -C
153 153 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
154 154
155 155 revert of exec bit
156 156 ------------------
157 157
158 158 #if execbit
159 159 $ chmod +x c
160 160 $ hg revert --all
161 161 reverting c
162 162
163 163 $ test -x c || echo non-executable
164 164 non-executable
165 165
166 166 $ chmod +x c
167 167 $ hg commit -m exe
168 168
169 169 $ chmod -x c
170 170 $ hg revert --all
171 171 reverting c
172 172
173 173 $ test -x c && echo executable
174 174 executable
175 175 #endif
176 176
177 177 $ cd ..
178 178
179 179
180 180 Issue241: update and revert produces inconsistent repositories
181 181 --------------------------------------------------------------
182 182
183 183 $ hg init a
184 184 $ cd a
185 185 $ echo a >> a
186 186 $ hg commit -A -d '1 0' -m a
187 187 adding a
188 188 $ echo a >> a
189 189 $ hg commit -d '2 0' -m a
190 190 $ hg update 0
191 191 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
192 192 $ mkdir b
193 193 $ echo b > b/b
194 194
195 195 call `hg revert` with no file specified
196 196 ---------------------------------------
197 197
198 198 $ hg revert -rtip
199 199 abort: no files or directories specified
200 200 (use --all to revert all files, or 'hg update 1' to update)
201 201 [255]
202 202
203 203 call `hg revert` with --all
204 204 ---------------------------
205 205
206 206 $ hg revert --all -rtip
207 207 reverting a
208 208
209 209
210 210 Issue332: confusing message when reverting directory
211 211 ----------------------------------------------------
212 212
213 213 $ hg ci -A -m b
214 214 adding b/b
215 215 created new head
216 216 $ echo foobar > b/b
217 217 $ mkdir newdir
218 218 $ echo foo > newdir/newfile
219 219 $ hg add newdir/newfile
220 220 $ hg revert b newdir
221 221 reverting b/b (glob)
222 222 forgetting newdir/newfile (glob)
223 223 $ echo foobar > b/b
224 224 $ hg revert .
225 225 reverting b/b (glob)
226 226
227 227
228 228 reverting a rename target should revert the source
229 229 --------------------------------------------------
230 230
231 231 $ hg mv a newa
232 232 $ hg revert newa
233 233 $ hg st a newa
234 234 ? newa
235 235
236 236 $ cd ..
237 237
238 238 $ hg init ignored
239 239 $ cd ignored
240 240 $ echo '^ignored$' > .hgignore
241 241 $ echo '^ignoreddir$' >> .hgignore
242 242 $ echo '^removed$' >> .hgignore
243 243
244 244 $ mkdir ignoreddir
245 245 $ touch ignoreddir/file
246 246 $ touch ignoreddir/removed
247 247 $ touch ignored
248 248 $ touch removed
249 249
250 250 4 ignored files (we will add/commit everything)
251 251
252 252 $ hg st -A -X .hgignore
253 253 I ignored
254 254 I ignoreddir/file
255 255 I ignoreddir/removed
256 256 I removed
257 257 $ hg ci -qAm 'add files' ignored ignoreddir/file ignoreddir/removed removed
258 258
259 259 $ echo >> ignored
260 260 $ echo >> ignoreddir/file
261 261 $ hg rm removed ignoreddir/removed
262 262
263 263 should revert ignored* and undelete *removed
264 264 --------------------------------------------
265 265
266 266 $ hg revert -a --no-backup
267 267 reverting ignored
268 268 reverting ignoreddir/file (glob)
269 269 undeleting ignoreddir/removed (glob)
270 270 undeleting removed
271 271 $ hg st -mardi
272 272
273 273 $ hg up -qC
274 274 $ echo >> ignored
275 275 $ hg rm removed
276 276
277 277 should silently revert the named files
278 278 --------------------------------------
279 279
280 280 $ hg revert --no-backup ignored removed
281 281 $ hg st -mardi
282 282
283 283 Reverting copy (issue3920)
284 284 --------------------------
285 285
286 286 someone set up us the copies
287 287
288 288 $ rm .hgignore
289 289 $ hg update -C
290 290 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
291 291 $ hg mv ignored allyour
292 292 $ hg copy removed base
293 293 $ hg commit -m rename
294 294
295 295 copies and renames, you have no chance to survive make your time (issue3920)
296 296
297 297 $ hg update '.^'
298 298 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
299 299 $ hg revert -rtip -a
300 300 adding allyour
301 301 adding base
302 302 removing ignored
303 303 $ hg status -C
304 304 A allyour
305 305 ignored
306 306 A base
307 307 removed
308 308 R ignored
309 309
310 310 Test revert of a file added by one side of the merge
311 311 ====================================================
312 312
313 313 remove any pending change
314 314
315 315 $ hg revert --all
316 316 forgetting allyour
317 317 forgetting base
318 318 undeleting ignored
319 319 $ hg purge --all --config extensions.purge=
320 320
321 321 Adds a new commit
322 322
323 323 $ echo foo > newadd
324 324 $ hg add newadd
325 325 $ hg commit -m 'other adds'
326 326 created new head
327 327
328 328
329 329 merge it with the other head
330 330
331 331 $ hg merge # merge 1 into 2
332 332 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
333 333 (branch merge, don't forget to commit)
334 334 $ hg summary
335 335 parent: 2:b8ec310b2d4e tip
336 336 other adds
337 337 parent: 1:f6180deb8fbe
338 338 rename
339 339 branch: default
340 340 commit: 2 modified, 1 removed (merge)
341 341 update: (current)
342 342
343 343 clarifies who added what
344 344
345 345 $ hg status
346 346 M allyour
347 347 M base
348 348 R ignored
349 349 $ hg status --change 'p1()'
350 350 A newadd
351 351 $ hg status --change 'p2()'
352 352 A allyour
353 353 A base
354 354 R ignored
355 355
356 356 revert file added by p1() to p1() state
357 357 -----------------------------------------
358 358
359 359 $ hg revert -r 'p1()' 'glob:newad?'
360 360 $ hg status
361 361 M allyour
362 362 M base
363 363 R ignored
364 364
365 365 revert file added by p1() to p2() state
366 366 ------------------------------------------
367 367
368 368 $ hg revert -r 'p2()' 'glob:newad?'
369 369 removing newadd
370 370 $ hg status
371 371 M allyour
372 372 M base
373 373 R ignored
374 374 R newadd
375 375
376 376 revert file added by p2() to p2() state
377 377 ------------------------------------------
378 378
379 379 $ hg revert -r 'p2()' 'glob:allyou?'
380 380 $ hg status
381 381 M allyour
382 382 M base
383 383 R ignored
384 384 R newadd
385 385
386 386 revert file added by p2() to p1() state
387 387 ------------------------------------------
388 388
389 389 $ hg revert -r 'p1()' 'glob:allyou?'
390 390 removing allyour
391 391 $ hg status
392 392 M base
393 393 R allyour
394 394 R ignored
395 395 R newadd
396 396
397 397 Systematic behavior validation of most possible cases
398 398 =====================================================
399 399
400 400 This section tests most of the possible combinations of working directory
401 401 changes and inter-revision changes. The number of possible cases is significant
402 402 but they all have a slighly different handling. So this section commits to
403 403 generating and testing all of them to allow safe refactoring of the revert code.
404 404
405 405 A python script is used to generate a file history for each combination of
406 406 changes between, on one side the working directory and its parent and on
407 407 the other side, changes between a revert target (--rev) and working directory
408 408 parent. The three states generated are:
409 409
410 410 - a "base" revision
411 411 - a "parent" revision
412 412 - the working directory (based on "parent")
413 413
414 414 The file generated have names of the form:
415 415
416 416 <changeset-state>_<working-copy-state>
417 417
418 418 Here, "changeset-state" conveys the state in "base" and "parent" (or the change
419 419 that happen between them), "working-copy-state" is self explanatory.
420 420
421 421 All known states are not tested yet. See inline documentation for details.
422 422 Special cases from merge and rename are not tested by this section.
423 423
424 424 There are also multiple cases where the current revert implementation is known to
425 425 slightly misbehave.
426 426
427 427 Write the python script to disk
428 428 -------------------------------
429 429
430 430 $ cat << EOF > gen-revert-cases.py
431 431 > # generate proper file state to test revert behavior
432 432 > import sys
433 433 >
434 434 > # content of the file in "base" and "parent"
435 435 > ctxcontent = {
436 436 > # modified: file content change from base to parent
437 437 > 'modified': ['base', 'parent'],
438 438 > }
439 439 >
440 440 > # content of file in working copy
441 441 > wccontent = {
442 442 > # clean: wc content is the same as parent
443 443 > 'clean': lambda cc: cc[1],
444 444 > }
445 445 >
446 446 > # build the combination of possible states
447 447 > combination = []
448 448 > for ctxkey in ctxcontent:
449 449 > for wckey in wccontent:
450 450 > filename = "%s_%s" % (ctxkey, wckey)
451 451 > combination.append((filename, ctxkey, wckey))
452 452 >
453 453 > # make sure we have stable output
454 454 > combination.sort()
455 455 >
456 456 > # retrieve the state we must generate
457 457 > target = sys.argv[1]
458 458 >
459 459 > # compute file content
460 460 > content = []
461 461 > for filename, ctxkey, wckey in combination:
462 462 > cc = ctxcontent[ctxkey]
463 463 > if target == 'filelist':
464 464 > print filename
465 465 > elif target == 'base':
466 466 > content.append((filename, cc[0]))
467 467 > elif target == 'parent':
468 468 > content.append((filename, cc[1]))
469 469 > elif target == 'wc':
470 470 > content.append((filename, wccontent[wckey](cc)))
471 471 > else:
472 472 > print >> sys.stderr, "unknown target:", target
473 473 > sys.exit(1)
474 474 >
475 475 > # write actual content
476 476 > for filename, data in content:
477 477 > f = open(filename, 'w')
478 478 > f.write(data + '\n')
479 479 > f.close()
480 480 > EOF
481 481
482 482 check list of planned files
483 483
484 484 $ python gen-revert-cases.py filelist
485 485 modified_clean
486 486
487 487 Script to make a simple text version of the content
488 488 ---------------------------------------------------
489 489
490 490 $ cat << EOF >> dircontent.py
491 491 > # generate a simple text view of the directory for easy comparison
492 492 > import os
493 493 > files = os.listdir('.')
494 494 > files.sort()
495 495 > for filename in files:
496 496 > if os.path.isdir(filename):
497 497 > continue
498 498 > content = open(filename).read()
499 499 > print '%-6s %s' % (content.strip(), filename)
500 500 > EOF
501 501
502 502 Generate appropriate repo state
503 503 -------------------------------
504 504
505 505 $ hg init revert-ref
506 506 $ cd revert-ref
507 507
508 508 Generate base changeset
509 509
510 510 $ python ../gen-revert-cases.py base
511 511 $ hg addremove --similarity 0
512 512 adding modified_clean
513 513 $ hg status
514 514 A modified_clean
515 515 $ hg commit -m 'base'
516 516
517 517 (create a simple text version of the content)
518 518
519 519 $ python ../dircontent.py > ../content-base.txt
520 520 $ cat ../content-base.txt
521 521 base modified_clean
522 522
523 523 Create parent changeset
524 524
525 525 $ python ../gen-revert-cases.py parent
526 526 $ hg addremove --similarity 0
527 527 $ hg status
528 528 M modified_clean
529 529 $ hg commit -m 'parent'
530 530
531 531 (create a simple text version of the content)
532 532
533 533 $ python ../dircontent.py > ../content-parent.txt
534 534 $ cat ../content-parent.txt
535 535 parent modified_clean
536 536
537 537 Setup working directory
538 538
539 539 $ python ../gen-revert-cases.py wc | cat
540 540 $ hg addremove --similarity 0
541 541 $ hg status
542 542
543 543 $ hg status --rev 'desc("base")'
544 544 M modified_clean
545 545
546 546 (create a simple text version of the content)
547 547
548 548 $ python ../dircontent.py > ../content-wc.txt
549 549 $ cat ../content-wc.txt
550 550 parent modified_clean
551 551
552 552 $ cd ..
553 553
554 Test revert --all to parent content
555 -----------------------------------
556
557 (setup from reference repo)
558
559 $ cp -r revert-ref revert-parent-all
560 $ cd revert-parent-all
561
562 check revert output
563
564 $ hg revert --all
565
566 Compare resulting directory with revert target.
567
568 The diff is filtered to include change only. The only difference should be
569 additional `.orig` backup file when applicable.
570
571 $ python ../dircontent.py > ../content-parent-all.txt
572 $ cd ..
573 $ diff -U 0 -- content-parent.txt content-parent-all.txt | grep _
574 [1]
General Comments 0
You need to be logged in to leave comments. Login now