##// END OF EJS Templates
tests: stabilize test-fix.t for Windows
Matt Harbison -
r37809:72ccb071 stable
parent child Browse files
Show More
@@ -1,1025 +1,1028
1 1 A script that implements uppercasing of specific lines in a file. This
2 2 approximates the behavior of code formatters well enough for our tests.
3 3
4 4 $ UPPERCASEPY="$TESTTMP/uppercase.py"
5 5 $ cat > $UPPERCASEPY <<EOF
6 6 > import sys
7 7 > from mercurial.utils.procutil import setbinary
8 8 > setbinary(sys.stdin)
9 9 > setbinary(sys.stdout)
10 10 > lines = set()
11 11 > for arg in sys.argv[1:]:
12 12 > if arg == 'all':
13 13 > sys.stdout.write(sys.stdin.read().upper())
14 14 > sys.exit(0)
15 15 > else:
16 16 > first, last = arg.split('-')
17 17 > lines.update(range(int(first), int(last) + 1))
18 18 > for i, line in enumerate(sys.stdin.readlines()):
19 19 > if i + 1 in lines:
20 20 > sys.stdout.write(line.upper())
21 21 > else:
22 22 > sys.stdout.write(line)
23 23 > EOF
24 24 $ TESTLINES="foo\nbar\nbaz\nqux\n"
25 25 $ printf $TESTLINES | $PYTHON $UPPERCASEPY
26 26 foo
27 27 bar
28 28 baz
29 29 qux
30 30 $ printf $TESTLINES | $PYTHON $UPPERCASEPY all
31 31 FOO
32 32 BAR
33 33 BAZ
34 34 QUX
35 35 $ printf $TESTLINES | $PYTHON $UPPERCASEPY 1-1
36 36 FOO
37 37 bar
38 38 baz
39 39 qux
40 40 $ printf $TESTLINES | $PYTHON $UPPERCASEPY 1-2
41 41 FOO
42 42 BAR
43 43 baz
44 44 qux
45 45 $ printf $TESTLINES | $PYTHON $UPPERCASEPY 2-3
46 46 foo
47 47 BAR
48 48 BAZ
49 49 qux
50 50 $ printf $TESTLINES | $PYTHON $UPPERCASEPY 2-2 4-4
51 51 foo
52 52 BAR
53 53 baz
54 54 QUX
55 55
56 56 Set up the config with two simple fixers: one that fixes specific line ranges,
57 57 and one that always fixes the whole file. They both "fix" files by converting
58 58 letters to uppercase. They use different file extensions, so each test case can
59 59 choose which behavior to use by naming files.
60 60
61 61 $ cat >> $HGRCPATH <<EOF
62 62 > [extensions]
63 63 > fix =
64 64 > [experimental]
65 65 > evolution.createmarkers=True
66 66 > evolution.allowunstable=True
67 67 > [fix]
68 68 > uppercase-whole-file:command=$PYTHON $UPPERCASEPY all
69 69 > uppercase-whole-file:fileset=set:**.whole
70 70 > uppercase-changed-lines:command=$PYTHON $UPPERCASEPY
71 71 > uppercase-changed-lines:linerange={first}-{last}
72 72 > uppercase-changed-lines:fileset=set:**.changed
73 73 > EOF
74 74
75 75 Help text for fix.
76 76
77 77 $ hg help fix
78 78 hg fix [OPTION]... [FILE]...
79 79
80 80 rewrite file content in changesets or working directory
81 81
82 82 Runs any configured tools to fix the content of files. Only affects files
83 83 with changes, unless file arguments are provided. Only affects changed
84 84 lines of files, unless the --whole flag is used. Some tools may always
85 85 affect the whole file regardless of --whole.
86 86
87 87 If revisions are specified with --rev, those revisions will be checked,
88 88 and they may be replaced with new revisions that have fixed file content.
89 89 It is desirable to specify all descendants of each specified revision, so
90 90 that the fixes propagate to the descendants. If all descendants are fixed
91 91 at the same time, no merging, rebasing, or evolution will be required.
92 92
93 93 If --working-dir is used, files with uncommitted changes in the working
94 94 copy will be fixed. If the checked-out revision is also fixed, the working
95 95 directory will update to the replacement revision.
96 96
97 97 When determining what lines of each file to fix at each revision, the
98 98 whole set of revisions being fixed is considered, so that fixes to earlier
99 99 revisions are not forgotten in later ones. The --base flag can be used to
100 100 override this default behavior, though it is not usually desirable to do
101 101 so.
102 102
103 103 (use 'hg help -e fix' to show help for the fix extension)
104 104
105 105 options ([+] can be repeated):
106 106
107 107 --all fix all non-public non-obsolete revisions
108 108 --base REV [+] revisions to diff against (overrides automatic selection,
109 109 and applies to every revision being fixed)
110 110 -r --rev REV [+] revisions to fix
111 111 -w --working-dir fix the working directory
112 112 --whole always fix every line of a file
113 113
114 114 (some details hidden, use --verbose to show complete help)
115 115
116 116 $ hg help -e fix
117 117 fix extension - rewrite file content in changesets or working copy
118 118 (EXPERIMENTAL)
119 119
120 120 Provides a command that runs configured tools on the contents of modified
121 121 files, writing back any fixes to the working copy or replacing changesets.
122 122
123 123 Here is an example configuration that causes 'hg fix' to apply automatic
124 124 formatting fixes to modified lines in C++ code:
125 125
126 126 [fix]
127 127 clang-format:command=clang-format --assume-filename={rootpath}
128 128 clang-format:linerange=--lines={first}:{last}
129 129 clang-format:fileset=set:**.cpp or **.hpp
130 130
131 131 The :command suboption forms the first part of the shell command that will be
132 132 used to fix a file. The content of the file is passed on standard input, and
133 133 the fixed file content is expected on standard output. If there is any output
134 134 on standard error, the file will not be affected. Some values may be
135 135 substituted into the command:
136 136
137 137 {rootpath} The path of the file being fixed, relative to the repo root
138 138 {basename} The name of the file being fixed, without the directory path
139 139
140 140 If the :linerange suboption is set, the tool will only be run if there are
141 141 changed lines in a file. The value of this suboption is appended to the shell
142 142 command once for every range of changed lines in the file. Some values may be
143 143 substituted into the command:
144 144
145 145 {first} The 1-based line number of the first line in the modified range
146 146 {last} The 1-based line number of the last line in the modified range
147 147
148 148 The :fileset suboption determines which files will be passed through each
149 149 configured tool. See 'hg help fileset' for possible values. If there are file
150 150 arguments to 'hg fix', the intersection of these filesets is used.
151 151
152 152 There is also a configurable limit for the maximum size of file that will be
153 153 processed by 'hg fix':
154 154
155 155 [fix]
156 156 maxfilesize=2MB
157 157
158 158 list of commands:
159 159
160 160 fix rewrite file content in changesets or working directory
161 161
162 162 (use 'hg help -v -e fix' to show built-in aliases and global options)
163 163
164 164 There is no default behavior in the absence of --rev and --working-dir.
165 165
166 166 $ hg init badusage
167 167 $ cd badusage
168 168
169 169 $ hg fix
170 170 abort: no changesets specified
171 171 (use --rev or --working-dir)
172 172 [255]
173 173 $ hg fix --whole
174 174 abort: no changesets specified
175 175 (use --rev or --working-dir)
176 176 [255]
177 177 $ hg fix --base 0
178 178 abort: no changesets specified
179 179 (use --rev or --working-dir)
180 180 [255]
181 181
182 182 Fixing a public revision isn't allowed. It should abort early enough that
183 183 nothing happens, even to the working directory.
184 184
185 185 $ printf "hello\n" > hello.whole
186 186 $ hg commit -Aqm "hello"
187 187 $ hg phase -r 0 --public
188 188 $ hg fix -r 0
189 189 abort: can't fix immutable changeset 0:6470986d2e7b
190 190 [255]
191 191 $ hg fix -r 0 --working-dir
192 192 abort: can't fix immutable changeset 0:6470986d2e7b
193 193 [255]
194 194 $ hg cat -r tip hello.whole
195 195 hello
196 196 $ cat hello.whole
197 197 hello
198 198
199 199 $ cd ..
200 200
201 201 Fixing a clean working directory should do nothing. Even the --whole flag
202 202 shouldn't cause any clean files to be fixed. Specifying a clean file explicitly
203 203 should only fix it if the fixer always fixes the whole file. The combination of
204 204 an explicit filename and --whole should format the entire file regardless.
205 205
206 206 $ hg init fixcleanwdir
207 207 $ cd fixcleanwdir
208 208
209 209 $ printf "hello\n" > hello.changed
210 210 $ printf "world\n" > hello.whole
211 211 $ hg commit -Aqm "foo"
212 212 $ hg fix --working-dir
213 213 $ hg diff
214 214 $ hg fix --working-dir --whole
215 215 $ hg diff
216 216 $ hg fix --working-dir *
217 217 $ cat *
218 218 hello
219 219 WORLD
220 220 $ hg revert --all --no-backup
221 221 reverting hello.whole
222 222 $ hg fix --working-dir * --whole
223 223 $ cat *
224 224 HELLO
225 225 WORLD
226 226
227 227 The same ideas apply to fixing a revision, so we create a revision that doesn't
228 228 modify either of the files in question and try fixing it. This also tests that
229 229 we ignore a file that doesn't match any configured fixer.
230 230
231 231 $ hg revert --all --no-backup
232 232 reverting hello.changed
233 233 reverting hello.whole
234 234 $ printf "unimportant\n" > some.file
235 235 $ hg commit -Aqm "some other file"
236 236
237 237 $ hg fix -r .
238 238 $ hg cat -r tip *
239 239 hello
240 240 world
241 241 unimportant
242 242 $ hg fix -r . --whole
243 243 $ hg cat -r tip *
244 244 hello
245 245 world
246 246 unimportant
247 247 $ hg fix -r . *
248 248 $ hg cat -r tip *
249 249 hello
250 250 WORLD
251 251 unimportant
252 252 $ hg fix -r . * --whole --config experimental.evolution.allowdivergence=true
253 253 2 new content-divergent changesets
254 254 $ hg cat -r tip *
255 255 HELLO
256 256 WORLD
257 257 unimportant
258 258
259 259 $ cd ..
260 260
261 261 Fixing the working directory should still work if there are no revisions.
262 262
263 263 $ hg init norevisions
264 264 $ cd norevisions
265 265
266 266 $ printf "something\n" > something.whole
267 267 $ hg add
268 268 adding something.whole
269 269 $ hg fix --working-dir
270 270 $ cat something.whole
271 271 SOMETHING
272 272
273 273 $ cd ..
274 274
275 275 Test the effect of fixing the working directory for each possible status, with
276 276 and without providing explicit file arguments.
277 277
278 278 $ hg init implicitlyfixstatus
279 279 $ cd implicitlyfixstatus
280 280
281 281 $ printf "modified\n" > modified.whole
282 282 $ printf "removed\n" > removed.whole
283 283 $ printf "deleted\n" > deleted.whole
284 284 $ printf "clean\n" > clean.whole
285 285 $ printf "ignored.whole" > .hgignore
286 286 $ hg commit -Aqm "stuff"
287 287
288 288 $ printf "modified!!!\n" > modified.whole
289 289 $ printf "unknown\n" > unknown.whole
290 290 $ printf "ignored\n" > ignored.whole
291 291 $ printf "added\n" > added.whole
292 292 $ hg add added.whole
293 293 $ hg remove removed.whole
294 294 $ rm deleted.whole
295 295
296 296 $ hg status --all
297 297 M modified.whole
298 298 A added.whole
299 299 R removed.whole
300 300 ! deleted.whole
301 301 ? unknown.whole
302 302 I ignored.whole
303 303 C .hgignore
304 304 C clean.whole
305 305
306 306 $ hg fix --working-dir
307 307
308 308 $ hg status --all
309 309 M modified.whole
310 310 A added.whole
311 311 R removed.whole
312 312 ! deleted.whole
313 313 ? unknown.whole
314 314 I ignored.whole
315 315 C .hgignore
316 316 C clean.whole
317 317
318 318 $ cat *.whole
319 319 ADDED
320 320 clean
321 321 ignored
322 322 MODIFIED!!!
323 323 unknown
324 324
325 325 $ printf "modified!!!\n" > modified.whole
326 326 $ printf "added\n" > added.whole
327 327 $ hg fix --working-dir *.whole
328 328
329 329 $ hg status --all
330 330 M clean.whole
331 331 M modified.whole
332 332 A added.whole
333 333 R removed.whole
334 334 ! deleted.whole
335 335 ? unknown.whole
336 336 I ignored.whole
337 337 C .hgignore
338 338
339 339 It would be better if this also fixed the unknown file.
340 340 $ cat *.whole
341 341 ADDED
342 342 CLEAN
343 343 ignored
344 344 MODIFIED!!!
345 345 unknown
346 346
347 347 $ cd ..
348 348
349 349 Test that incremental fixing works on files with additions, deletions, and
350 350 changes in multiple line ranges. Note that deletions do not generally cause
351 351 neighboring lines to be fixed, so we don't return a line range for purely
352 352 deleted sections. In the future we should support a :deletion config that
353 353 allows fixers to know where deletions are located.
354 354
355 355 $ hg init incrementalfixedlines
356 356 $ cd incrementalfixedlines
357 357
358 358 $ printf "a\nb\nc\nd\ne\nf\ng\n" > foo.txt
359 359 $ hg commit -Aqm "foo"
360 360 $ printf "zz\na\nc\ndd\nee\nff\nf\ngg\n" > foo.txt
361 361
362 362 $ hg --config "fix.fail:command=echo" \
363 363 > --config "fix.fail:linerange={first}:{last}" \
364 364 > --config "fix.fail:fileset=foo.txt" \
365 365 > fix --working-dir
366 366 $ cat foo.txt
367 367 1:1 4:6 8:8
368 368
369 369 $ cd ..
370 370
371 371 Test that --whole fixes all lines regardless of the diffs present.
372 372
373 373 $ hg init wholeignoresdiffs
374 374 $ cd wholeignoresdiffs
375 375
376 376 $ printf "a\nb\nc\nd\ne\nf\ng\n" > foo.changed
377 377 $ hg commit -Aqm "foo"
378 378 $ printf "zz\na\nc\ndd\nee\nff\nf\ngg\n" > foo.changed
379 379 $ hg fix --working-dir --whole
380 380 $ cat foo.changed
381 381 ZZ
382 382 A
383 383 C
384 384 DD
385 385 EE
386 386 FF
387 387 F
388 388 GG
389 389
390 390 $ cd ..
391 391
392 392 We should do nothing with symlinks, and their targets should be unaffected. Any
393 393 other behavior would be more complicated to implement and harder to document.
394 394
395 395 #if symlink
396 396 $ hg init dontmesswithsymlinks
397 397 $ cd dontmesswithsymlinks
398 398
399 399 $ printf "hello\n" > hello.whole
400 400 $ ln -s hello.whole hellolink
401 401 $ hg add
402 402 adding hello.whole
403 403 adding hellolink
404 404 $ hg fix --working-dir hellolink
405 405 $ hg status
406 406 A hello.whole
407 407 A hellolink
408 408
409 409 $ cd ..
410 410 #endif
411 411
412 412 We should allow fixers to run on binary files, even though this doesn't sound
413 413 like a common use case. There's not much benefit to disallowing it, and users
414 414 can add "and not binary()" to their filesets if needed. The Mercurial
415 415 philosophy is generally to not handle binary files specially anyway.
416 416
417 417 $ hg init cantouchbinaryfiles
418 418 $ cd cantouchbinaryfiles
419 419
420 420 $ printf "hello\0\n" > hello.whole
421 421 $ hg add
422 422 adding hello.whole
423 423 $ hg fix --working-dir 'set:binary()'
424 424 $ cat hello.whole
425 425 HELLO\x00 (esc)
426 426
427 427 $ cd ..
428 428
429 429 We have a config for the maximum size of file we will attempt to fix. This can
430 430 be helpful to avoid running unsuspecting fixer tools on huge inputs, which
431 431 could happen by accident without a well considered configuration. A more
432 432 precise configuration could use the size() fileset function if one global limit
433 433 is undesired.
434 434
435 435 $ hg init maxfilesize
436 436 $ cd maxfilesize
437 437
438 438 $ printf "this file is huge\n" > hello.whole
439 439 $ hg add
440 440 adding hello.whole
441 441 $ hg --config fix.maxfilesize=10 fix --working-dir
442 442 ignoring file larger than 10 bytes: hello.whole
443 443 $ cat hello.whole
444 444 this file is huge
445 445
446 446 $ cd ..
447 447
448 448 If we specify a file to fix, other files should be left alone, even if they
449 449 have changes.
450 450
451 451 $ hg init fixonlywhatitellyouto
452 452 $ cd fixonlywhatitellyouto
453 453
454 454 $ printf "fix me!\n" > fixme.whole
455 455 $ printf "not me.\n" > notme.whole
456 456 $ hg add
457 457 adding fixme.whole
458 458 adding notme.whole
459 459 $ hg fix --working-dir fixme.whole
460 460 $ cat *.whole
461 461 FIX ME!
462 462 not me.
463 463
464 464 $ cd ..
465 465
466 466 Specifying a directory name should fix all its files and subdirectories.
467 467
468 468 $ hg init fixdirectory
469 469 $ cd fixdirectory
470 470
471 471 $ mkdir -p dir1/dir2
472 472 $ printf "foo\n" > foo.whole
473 473 $ printf "bar\n" > dir1/bar.whole
474 474 $ printf "baz\n" > dir1/dir2/baz.whole
475 475 $ hg add
476 476 adding dir1/bar.whole
477 477 adding dir1/dir2/baz.whole
478 478 adding foo.whole
479 479 $ hg fix --working-dir dir1
480 480 $ cat foo.whole dir1/bar.whole dir1/dir2/baz.whole
481 481 foo
482 482 BAR
483 483 BAZ
484 484
485 485 $ cd ..
486 486
487 487 Fixing a file in the working directory that needs no fixes should not actually
488 488 write back to the file, so for example the mtime shouldn't change.
489 489
490 490 $ hg init donttouchunfixedfiles
491 491 $ cd donttouchunfixedfiles
492 492
493 493 $ printf "NO FIX NEEDED\n" > foo.whole
494 494 $ hg add
495 495 adding foo.whole
496 496 $ cp foo.whole foo.whole.orig
497 497 $ sleep 2 # mtime has a resolution of one or two seconds.
498 498 $ hg fix --working-dir
499 499 $ f foo.whole --newer foo.whole.orig
500 500 foo.whole: older than foo.whole.orig
501 501
502 502 $ cd ..
503 503
504 504 When a fixer prints to stderr, we assume that it has failed. We should show the
505 505 error messages to the user, and we should not let the failing fixer affect the
506 506 file it was fixing (many code formatters might emit error messages on stderr
507 507 and nothing on stdout, which would cause us the clear the file). We show the
508 508 user which fixer failed and which revision, but we assume that the fixer will
509 509 print the filename if it is relevant.
510 510
511 511 $ hg init showstderr
512 512 $ cd showstderr
513 513
514 514 $ printf "hello\n" > hello.txt
515 515 $ hg add
516 516 adding hello.txt
517 $ hg --config "fix.fail:command=printf 'HELLO\n' ; \
518 > printf '{rootpath}: some\nerror' >&2" \
517 $ cat >> $TESTTMP/cmd.sh <<'EOF'
518 > printf 'HELLO\n'
519 > printf "$@: some\nerror" >&2
520 > EOF
521 $ hg --config "fix.fail:command=sh $TESTTMP/cmd.sh {rootpath}" \
519 522 > --config "fix.fail:fileset=hello.txt" \
520 523 > fix --working-dir
521 524 [wdir] fail: hello.txt: some
522 525 [wdir] fail: error
523 526 $ cat hello.txt
524 527 hello
525 528
526 529 $ cd ..
527 530
528 531 Fixing the working directory and its parent revision at the same time should
529 532 check out the replacement revision for the parent. This prevents any new
530 533 uncommitted changes from appearing. We test this for a clean working directory
531 534 and a dirty one. In both cases, all lines/files changed since the grandparent
532 535 will be fixed. The grandparent is the "baserev" for both the parent and the
533 536 working copy.
534 537
535 538 $ hg init fixdotandcleanwdir
536 539 $ cd fixdotandcleanwdir
537 540
538 541 $ printf "hello\n" > hello.whole
539 542 $ printf "world\n" > world.whole
540 543 $ hg commit -Aqm "the parent commit"
541 544
542 545 $ hg parents --template '{rev} {desc}\n'
543 546 0 the parent commit
544 547 $ hg fix --working-dir -r .
545 548 $ hg parents --template '{rev} {desc}\n'
546 549 1 the parent commit
547 550 $ hg cat -r . *.whole
548 551 HELLO
549 552 WORLD
550 553 $ cat *.whole
551 554 HELLO
552 555 WORLD
553 556 $ hg status
554 557
555 558 $ cd ..
556 559
557 560 Same test with a dirty working copy.
558 561
559 562 $ hg init fixdotanddirtywdir
560 563 $ cd fixdotanddirtywdir
561 564
562 565 $ printf "hello\n" > hello.whole
563 566 $ printf "world\n" > world.whole
564 567 $ hg commit -Aqm "the parent commit"
565 568
566 569 $ printf "hello,\n" > hello.whole
567 570 $ printf "world!\n" > world.whole
568 571
569 572 $ hg parents --template '{rev} {desc}\n'
570 573 0 the parent commit
571 574 $ hg fix --working-dir -r .
572 575 $ hg parents --template '{rev} {desc}\n'
573 576 1 the parent commit
574 577 $ hg cat -r . *.whole
575 578 HELLO
576 579 WORLD
577 580 $ cat *.whole
578 581 HELLO,
579 582 WORLD!
580 583 $ hg status
581 584 M hello.whole
582 585 M world.whole
583 586
584 587 $ cd ..
585 588
586 589 When we have a chain of commits that change mutually exclusive lines of code,
587 590 we should be able to do incremental fixing that causes each commit in the chain
588 591 to include fixes made to the previous commits. This prevents children from
589 592 backing out the fixes made in their parents. A dirty working directory is
590 593 conceptually similar to another commit in the chain.
591 594
592 595 $ hg init incrementallyfixchain
593 596 $ cd incrementallyfixchain
594 597
595 598 $ cat > file.changed <<EOF
596 599 > first
597 600 > second
598 601 > third
599 602 > fourth
600 603 > fifth
601 604 > EOF
602 605 $ hg commit -Aqm "the common ancestor (the baserev)"
603 606 $ cat > file.changed <<EOF
604 607 > first (changed)
605 608 > second
606 609 > third
607 610 > fourth
608 611 > fifth
609 612 > EOF
610 613 $ hg commit -Aqm "the first commit to fix"
611 614 $ cat > file.changed <<EOF
612 615 > first (changed)
613 616 > second
614 617 > third (changed)
615 618 > fourth
616 619 > fifth
617 620 > EOF
618 621 $ hg commit -Aqm "the second commit to fix"
619 622 $ cat > file.changed <<EOF
620 623 > first (changed)
621 624 > second
622 625 > third (changed)
623 626 > fourth
624 627 > fifth (changed)
625 628 > EOF
626 629
627 630 $ hg fix -r . -r '.^' --working-dir
628 631
629 632 $ hg parents --template '{rev}\n'
630 633 4
631 634 $ hg cat -r '.^^' file.changed
632 635 first
633 636 second
634 637 third
635 638 fourth
636 639 fifth
637 640 $ hg cat -r '.^' file.changed
638 641 FIRST (CHANGED)
639 642 second
640 643 third
641 644 fourth
642 645 fifth
643 646 $ hg cat -r . file.changed
644 647 FIRST (CHANGED)
645 648 second
646 649 THIRD (CHANGED)
647 650 fourth
648 651 fifth
649 652 $ cat file.changed
650 653 FIRST (CHANGED)
651 654 second
652 655 THIRD (CHANGED)
653 656 fourth
654 657 FIFTH (CHANGED)
655 658
656 659 $ cd ..
657 660
658 661 If we incrementally fix a merge commit, we should fix any lines that changed
659 662 versus either parent. You could imagine only fixing the intersection or some
660 663 other subset, but this is necessary if either parent is being fixed. It
661 664 prevents us from forgetting fixes made in either parent.
662 665
663 666 $ hg init incrementallyfixmergecommit
664 667 $ cd incrementallyfixmergecommit
665 668
666 669 $ printf "a\nb\nc\n" > file.changed
667 670 $ hg commit -Aqm "ancestor"
668 671
669 672 $ printf "aa\nb\nc\n" > file.changed
670 673 $ hg commit -m "change a"
671 674
672 675 $ hg checkout '.^'
673 676 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
674 677 $ printf "a\nb\ncc\n" > file.changed
675 678 $ hg commit -m "change c"
676 679 created new head
677 680
678 681 $ hg merge
679 682 merging file.changed
680 683 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
681 684 (branch merge, don't forget to commit)
682 685 $ hg commit -m "merge"
683 686 $ hg cat -r . file.changed
684 687 aa
685 688 b
686 689 cc
687 690
688 691 $ hg fix -r . --working-dir
689 692 $ hg cat -r . file.changed
690 693 AA
691 694 b
692 695 CC
693 696
694 697 $ cd ..
695 698
696 699 Abort fixing revisions if there is an unfinished operation. We don't want to
697 700 make things worse by editing files or stripping/obsoleting things. Also abort
698 701 fixing the working directory if there are unresolved merge conflicts.
699 702
700 703 $ hg init abortunresolved
701 704 $ cd abortunresolved
702 705
703 706 $ echo "foo1" > foo.whole
704 707 $ hg commit -Aqm "foo 1"
705 708
706 709 $ hg update null
707 710 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
708 711 $ echo "foo2" > foo.whole
709 712 $ hg commit -Aqm "foo 2"
710 713
711 714 $ hg --config extensions.rebase= rebase -r 1 -d 0
712 715 rebasing 1:c3b6dc0e177a "foo 2" (tip)
713 716 merging foo.whole
714 717 warning: conflicts while merging foo.whole! (edit, then use 'hg resolve --mark')
715 718 unresolved conflicts (see hg resolve, then hg rebase --continue)
716 719 [1]
717 720
718 721 $ hg --config extensions.rebase= fix --working-dir
719 722 abort: unresolved conflicts
720 723 (use 'hg resolve')
721 724 [255]
722 725
723 726 $ hg --config extensions.rebase= fix -r .
724 727 abort: rebase in progress
725 728 (use 'hg rebase --continue' or 'hg rebase --abort')
726 729 [255]
727 730
728 731 When fixing a file that was renamed, we should diff against the source of the
729 732 rename for incremental fixing and we should correctly reproduce the rename in
730 733 the replacement revision.
731 734
732 735 $ hg init fixrenamecommit
733 736 $ cd fixrenamecommit
734 737
735 738 $ printf "a\nb\nc\n" > source.changed
736 739 $ hg commit -Aqm "source revision"
737 740 $ hg move source.changed dest.changed
738 741 $ printf "a\nb\ncc\n" > dest.changed
739 742 $ hg commit -m "dest revision"
740 743
741 744 $ hg fix -r .
742 745 $ hg log -r tip --copies --template "{file_copies}\n"
743 746 dest.changed (source.changed)
744 747 $ hg cat -r tip dest.changed
745 748 a
746 749 b
747 750 CC
748 751
749 752 $ cd ..
750 753
751 754 When fixing revisions that remove files we must ensure that the replacement
752 755 actually removes the file, whereas it could accidentally leave it unchanged or
753 756 write an empty string to it.
754 757
755 758 $ hg init fixremovedfile
756 759 $ cd fixremovedfile
757 760
758 761 $ printf "foo\n" > foo.whole
759 762 $ printf "bar\n" > bar.whole
760 763 $ hg commit -Aqm "add files"
761 764 $ hg remove bar.whole
762 765 $ hg commit -m "remove file"
763 766 $ hg status --change .
764 767 R bar.whole
765 768 $ hg fix -r . foo.whole
766 769 $ hg status --change tip
767 770 M foo.whole
768 771 R bar.whole
769 772
770 773 $ cd ..
771 774
772 775 If fixing a revision finds no fixes to make, no replacement revision should be
773 776 created.
774 777
775 778 $ hg init nofixesneeded
776 779 $ cd nofixesneeded
777 780
778 781 $ printf "FOO\n" > foo.whole
779 782 $ hg commit -Aqm "add file"
780 783 $ hg log --template '{rev}\n'
781 784 0
782 785 $ hg fix -r .
783 786 $ hg log --template '{rev}\n'
784 787 0
785 788
786 789 $ cd ..
787 790
788 791 If fixing a commit reverts all the changes in the commit, we replace it with a
789 792 commit that changes no files.
790 793
791 794 $ hg init nochangesleft
792 795 $ cd nochangesleft
793 796
794 797 $ printf "FOO\n" > foo.whole
795 798 $ hg commit -Aqm "add file"
796 799 $ printf "foo\n" > foo.whole
797 800 $ hg commit -m "edit file"
798 801 $ hg status --change .
799 802 M foo.whole
800 803 $ hg fix -r .
801 804 $ hg status --change tip
802 805
803 806 $ cd ..
804 807
805 808 If we fix a parent and child revision together, the child revision must be
806 809 replaced if the parent is replaced, even if the diffs of the child needed no
807 810 fixes. However, we're free to not replace revisions that need no fixes and have
808 811 no ancestors that are replaced.
809 812
810 813 $ hg init mustreplacechild
811 814 $ cd mustreplacechild
812 815
813 816 $ printf "FOO\n" > foo.whole
814 817 $ hg commit -Aqm "add foo"
815 818 $ printf "foo\n" > foo.whole
816 819 $ hg commit -m "edit foo"
817 820 $ printf "BAR\n" > bar.whole
818 821 $ hg commit -Aqm "add bar"
819 822
820 823 $ hg log --graph --template '{node|shortest} {files}'
821 824 @ bc05 bar.whole
822 825 |
823 826 o 4fd2 foo.whole
824 827 |
825 828 o f9ac foo.whole
826 829
827 830 $ hg fix -r 0:2
828 831 $ hg log --graph --template '{node|shortest} {files}'
829 832 o 3801 bar.whole
830 833 |
831 834 o 38cc
832 835 |
833 836 | @ bc05 bar.whole
834 837 | |
835 838 | x 4fd2 foo.whole
836 839 |/
837 840 o f9ac foo.whole
838 841
839 842
840 843 $ cd ..
841 844
842 845 It's also possible that the child needs absolutely no changes, but we still
843 846 need to replace it to update its parent. If we skipped replacing the child
844 847 because it had no file content changes, it would become an orphan for no good
845 848 reason.
846 849
847 850 $ hg init mustreplacechildevenifnop
848 851 $ cd mustreplacechildevenifnop
849 852
850 853 $ printf "Foo\n" > foo.whole
851 854 $ hg commit -Aqm "add a bad foo"
852 855 $ printf "FOO\n" > foo.whole
853 856 $ hg commit -m "add a good foo"
854 857 $ hg fix -r . -r '.^'
855 858 $ hg log --graph --template '{rev} {desc}'
856 859 o 3 add a good foo
857 860 |
858 861 o 2 add a bad foo
859 862
860 863 @ 1 add a good foo
861 864 |
862 865 x 0 add a bad foo
863 866
864 867
865 868 $ cd ..
866 869
867 870 Similar to the case above, the child revision may become empty as a result of
868 871 fixing its parent. We should still create an empty replacement child.
869 872 TODO: determine how this should interact with ui.allowemptycommit given that
870 873 the empty replacement could have children.
871 874
872 875 $ hg init mustreplacechildevenifempty
873 876 $ cd mustreplacechildevenifempty
874 877
875 878 $ printf "foo\n" > foo.whole
876 879 $ hg commit -Aqm "add foo"
877 880 $ printf "Foo\n" > foo.whole
878 881 $ hg commit -m "edit foo"
879 882 $ hg fix -r . -r '.^'
880 883 $ hg log --graph --template '{rev} {desc}\n' --stat
881 884 o 3 edit foo
882 885 |
883 886 o 2 add foo
884 887 foo.whole | 1 +
885 888 1 files changed, 1 insertions(+), 0 deletions(-)
886 889
887 890 @ 1 edit foo
888 891 | foo.whole | 2 +-
889 892 | 1 files changed, 1 insertions(+), 1 deletions(-)
890 893 |
891 894 x 0 add foo
892 895 foo.whole | 1 +
893 896 1 files changed, 1 insertions(+), 0 deletions(-)
894 897
895 898
896 899 $ cd ..
897 900
898 901 Fixing a secret commit should replace it with another secret commit.
899 902
900 903 $ hg init fixsecretcommit
901 904 $ cd fixsecretcommit
902 905
903 906 $ printf "foo\n" > foo.whole
904 907 $ hg commit -Aqm "add foo" --secret
905 908 $ hg fix -r .
906 909 $ hg log --template '{rev} {phase}\n'
907 910 1 secret
908 911 0 secret
909 912
910 913 $ cd ..
911 914
912 915 We should also preserve phase when fixing a draft commit while the user has
913 916 their default set to secret.
914 917
915 918 $ hg init respectphasesnewcommit
916 919 $ cd respectphasesnewcommit
917 920
918 921 $ printf "foo\n" > foo.whole
919 922 $ hg commit -Aqm "add foo"
920 923 $ hg --config phases.newcommit=secret fix -r .
921 924 $ hg log --template '{rev} {phase}\n'
922 925 1 draft
923 926 0 draft
924 927
925 928 $ cd ..
926 929
927 930 Debug output should show what fixer commands are being subprocessed, which is
928 931 useful for anyone trying to set up a new config.
929 932
930 933 $ hg init debugoutput
931 934 $ cd debugoutput
932 935
933 936 $ printf "foo\nbar\nbaz\n" > foo.changed
934 937 $ hg commit -Aqm "foo"
935 938 $ printf "Foo\nbar\nBaz\n" > foo.changed
936 939 $ hg --debug fix --working-dir
937 940 subprocess: * $TESTTMP/uppercase.py 1-1 3-3 (glob)
938 941
939 942 $ cd ..
940 943
941 944 Fixing an obsolete revision can cause divergence, so we abort unless the user
942 945 configures to allow it. This is not yet smart enough to know whether there is a
943 946 successor, but even then it is not likely intentional or idiomatic to fix an
944 947 obsolete revision.
945 948
946 949 $ hg init abortobsoleterev
947 950 $ cd abortobsoleterev
948 951
949 952 $ printf "foo\n" > foo.changed
950 953 $ hg commit -Aqm "foo"
951 954 $ hg debugobsolete `hg parents --template '{node}'`
952 955 obsoleted 1 changesets
953 956 $ hg --hidden fix -r 0
954 957 abort: fixing obsolete revision could cause divergence
955 958 [255]
956 959
957 960 $ hg --hidden fix -r 0 --config experimental.evolution.allowdivergence=true
958 961 $ hg cat -r tip foo.changed
959 962 FOO
960 963
961 964 $ cd ..
962 965
963 966 Test all of the available substitution values for fixer commands.
964 967
965 968 $ hg init substitution
966 969 $ cd substitution
967 970
968 971 $ mkdir foo
969 972 $ printf "hello\ngoodbye\n" > foo/bar
970 973 $ hg add
971 974 adding foo/bar
972 975 $ hg --config "fix.fail:command=printf '%s\n' '{rootpath}' '{basename}'" \
973 976 > --config "fix.fail:linerange='{first}' '{last}'" \
974 977 > --config "fix.fail:fileset=foo/bar" \
975 978 > fix --working-dir
976 979 $ cat foo/bar
977 980 foo/bar
978 981 bar
979 982 1
980 983 2
981 984
982 985 $ cd ..
983 986
984 987 The --base flag should allow picking the revisions to diff against for changed
985 988 files and incremental line formatting.
986 989
987 990 $ hg init baseflag
988 991 $ cd baseflag
989 992
990 993 $ printf "one\ntwo\n" > foo.changed
991 994 $ printf "bar\n" > bar.changed
992 995 $ hg commit -Aqm "first"
993 996 $ printf "one\nTwo\n" > foo.changed
994 997 $ hg commit -m "second"
995 998 $ hg fix -w --base .
996 999 $ hg status
997 1000 $ hg fix -w --base null
998 1001 $ cat foo.changed
999 1002 ONE
1000 1003 TWO
1001 1004 $ cat bar.changed
1002 1005 BAR
1003 1006
1004 1007 $ cd ..
1005 1008
1006 1009 If the user asks to fix the parent of another commit, they are asking to create
1007 1010 an orphan. We must respect experimental.evolution.allowunstable.
1008 1011
1009 1012 $ hg init allowunstable
1010 1013 $ cd allowunstable
1011 1014
1012 1015 $ printf "one\n" > foo.whole
1013 1016 $ hg commit -Aqm "first"
1014 1017 $ printf "two\n" > foo.whole
1015 1018 $ hg commit -m "second"
1016 1019 $ hg --config experimental.evolution.allowunstable=False fix -r '.^'
1017 1020 abort: can only fix a changeset together with all its descendants
1018 1021 [255]
1019 1022 $ hg fix -r '.^'
1020 1023 1 new orphan changesets
1021 1024 $ hg cat -r 2 foo.whole
1022 1025 ONE
1023 1026
1024 1027 $ cd ..
1025 1028
General Comments 0
You need to be logged in to leave comments. Login now