##// END OF EJS Templates
test-revert: add case where file is added between "base" and "parent"
Pierre-Yves David -
r22133:d732ff67 default
parent child Browse files
Show More
@@ -1,652 +1,671 b''
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 > import os
433 434 >
434 435 > # content of the file in "base" and "parent"
436 > # None means no file at all
435 437 > ctxcontent = {
436 438 > # modified: file content change from base to parent
437 439 > 'modified': ['base', 'parent'],
440 > # added: file is missing from base and added in parent
441 > 'added': [None, 'parent'],
438 442 > }
439 443 >
440 444 > # content of file in working copy
441 445 > wccontent = {
442 446 > # clean: wc content is the same as parent
443 447 > 'clean': lambda cc: cc[1],
444 448 > }
445 449 >
446 450 > # build the combination of possible states
447 451 > combination = []
448 452 > for ctxkey in ctxcontent:
449 453 > for wckey in wccontent:
450 454 > filename = "%s_%s" % (ctxkey, wckey)
451 455 > combination.append((filename, ctxkey, wckey))
452 456 >
453 457 > # make sure we have stable output
454 458 > combination.sort()
455 459 >
456 460 > # retrieve the state we must generate
457 461 > target = sys.argv[1]
458 462 >
459 463 > # compute file content
460 464 > content = []
461 465 > for filename, ctxkey, wckey in combination:
462 466 > cc = ctxcontent[ctxkey]
463 467 > if target == 'filelist':
464 468 > print filename
465 469 > elif target == 'base':
466 470 > content.append((filename, cc[0]))
467 471 > elif target == 'parent':
468 472 > content.append((filename, cc[1]))
469 473 > elif target == 'wc':
470 474 > content.append((filename, wccontent[wckey](cc)))
471 475 > else:
472 476 > print >> sys.stderr, "unknown target:", target
473 477 > sys.exit(1)
474 478 >
475 479 > # write actual content
476 480 > for filename, data in content:
477 > f = open(filename, 'w')
478 > f.write(data + '\n')
479 > f.close()
481 > if data is not None:
482 > f = open(filename, 'w')
483 > f.write(data + '\n')
484 > f.close()
485 > elif os.path.exists(filename):
486 > os.remove(filename)
480 487 > EOF
481 488
482 489 check list of planned files
483 490
484 491 $ python gen-revert-cases.py filelist
492 added_clean
485 493 modified_clean
486 494
487 495 Script to make a simple text version of the content
488 496 ---------------------------------------------------
489 497
490 498 $ cat << EOF >> dircontent.py
491 499 > # generate a simple text view of the directory for easy comparison
492 500 > import os
493 501 > files = os.listdir('.')
494 502 > files.sort()
495 503 > for filename in files:
496 504 > if os.path.isdir(filename):
497 505 > continue
498 506 > content = open(filename).read()
499 507 > print '%-6s %s' % (content.strip(), filename)
500 508 > EOF
501 509
502 510 Generate appropriate repo state
503 511 -------------------------------
504 512
505 513 $ hg init revert-ref
506 514 $ cd revert-ref
507 515
508 516 Generate base changeset
509 517
510 518 $ python ../gen-revert-cases.py base
511 519 $ hg addremove --similarity 0
512 520 adding modified_clean
513 521 $ hg status
514 522 A modified_clean
515 523 $ hg commit -m 'base'
516 524
517 525 (create a simple text version of the content)
518 526
519 527 $ python ../dircontent.py > ../content-base.txt
520 528 $ cat ../content-base.txt
521 529 base modified_clean
522 530
523 531 Create parent changeset
524 532
525 533 $ python ../gen-revert-cases.py parent
526 534 $ hg addremove --similarity 0
535 adding added_clean
527 536 $ hg status
528 537 M modified_clean
538 A added_clean
529 539 $ hg commit -m 'parent'
530 540
531 541 (create a simple text version of the content)
532 542
533 543 $ python ../dircontent.py > ../content-parent.txt
534 544 $ cat ../content-parent.txt
545 parent added_clean
535 546 parent modified_clean
536 547
537 548 Setup working directory
538 549
539 550 $ python ../gen-revert-cases.py wc | cat
540 551 $ hg addremove --similarity 0
541 552 $ hg status
542 553
543 554 $ hg status --rev 'desc("base")'
544 555 M modified_clean
556 A added_clean
545 557
546 558 (create a simple text version of the content)
547 559
548 560 $ python ../dircontent.py > ../content-wc.txt
549 561 $ cat ../content-wc.txt
562 parent added_clean
550 563 parent modified_clean
551 564
552 565 $ cd ..
553 566
554 567 Test revert --all to parent content
555 568 -----------------------------------
556 569
557 570 (setup from reference repo)
558 571
559 572 $ cp -r revert-ref revert-parent-all
560 573 $ cd revert-parent-all
561 574
562 575 check revert output
563 576
564 577 $ hg revert --all
565 578
566 579 Compare resulting directory with revert target.
567 580
568 581 The diff is filtered to include change only. The only difference should be
569 582 additional `.orig` backup file when applicable.
570 583
571 584 $ python ../dircontent.py > ../content-parent-all.txt
572 585 $ cd ..
573 586 $ diff -U 0 -- content-parent.txt content-parent-all.txt | grep _
574 587 [1]
575 588
576 589 Test revert --all to "base" content
577 590 -----------------------------------
578 591
579 592 (setup from reference repo)
580 593
581 594 $ cp -r revert-ref revert-base-all
582 595 $ cd revert-base-all
583 596
584 597 check revert output
585 598
586 599 $ hg revert --all --rev 'desc(base)'
600 removing added_clean
587 601 reverting modified_clean
588 602
589 603 Compare resulting directory with revert target.
590 604
591 605 The diff is filtered to include change only. The only difference should be
592 606 additional `.orig` backup file when applicable.
593 607
594 608 $ python ../dircontent.py > ../content-base-all.txt
595 609 $ cd ..
596 610 $ diff -U 0 -- content-base.txt content-base-all.txt | grep _
597 611 [1]
598 612
599 613 Test revert to parent content with explicit file name
600 614 -----------------------------------------------------
601 615
602 616 (setup from reference repo)
603 617
604 618 $ cp -r revert-ref revert-parent-explicit
605 619 $ cd revert-parent-explicit
606 620
607 621 revert all files individually and check the output
608 622 (output is expected to be different than in the --all case)
609 623
610 624 $ for file in `python ../gen-revert-cases.py filelist`; do
611 625 > echo '### revert for:' $file;
612 626 > hg revert $file;
613 627 > echo
614 628 > done
629 ### revert for: added_clean
630 no changes needed to added_clean
631
615 632 ### revert for: modified_clean
616 633 no changes needed to modified_clean
617 634
618 635
619 636 check resulting directory againt the --all run
620 637 (There should be no difference)
621 638
622 639 $ python ../dircontent.py > ../content-parent-explicit.txt
623 640 $ cd ..
624 641 $ diff -U 0 -- content-parent-all.txt content-parent-explicit.txt | grep _
625 642 [1]
626 643
627 644 Test revert to "base" content with explicit file name
628 645 -----------------------------------------------------
629 646
630 647 (setup from reference repo)
631 648
632 649 $ cp -r revert-ref revert-base-explicit
633 650 $ cd revert-base-explicit
634 651
635 652 revert all files individually and check the output
636 653 (output is expected to be different than in the --all case)
637 654
638 655 $ for file in `python ../gen-revert-cases.py filelist`; do
639 656 > echo '### revert for:' $file;
640 657 > hg revert $file --rev 'desc(base)';
641 658 > echo
642 659 > done
660 ### revert for: added_clean
661
643 662 ### revert for: modified_clean
644 663
645 664
646 665 check resulting directory againt the --all run
647 666 (There should be no difference)
648 667
649 668 $ python ../dircontent.py > ../content-base-explicit.txt
650 669 $ cd ..
651 670 $ diff -U 0 -- content-base-all.txt content-base-explicit.txt | grep _
652 671 [1]
General Comments 0
You need to be logged in to leave comments. Login now