##// END OF EJS Templates
test-fix: normalize precision of mtime copied by 'cp -p'...
Yuya Nishihara -
r37827:80695628 stable
parent child Browse files
Show More
@@ -1,1028 +1,1029 b''
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 -p foo.whole foo.whole.orig
497 $ cp -p foo.whole.orig foo.whole
497 498 $ sleep 2 # mtime has a resolution of one or two seconds.
498 499 $ hg fix --working-dir
499 500 $ f foo.whole.orig --newer foo.whole
500 501 foo.whole.orig: newer than foo.whole
501 502
502 503 $ cd ..
503 504
504 505 When a fixer prints to stderr, we assume that it has failed. We should show the
505 506 error messages to the user, and we should not let the failing fixer affect the
506 507 file it was fixing (many code formatters might emit error messages on stderr
507 508 and nothing on stdout, which would cause us the clear the file). We show the
508 509 user which fixer failed and which revision, but we assume that the fixer will
509 510 print the filename if it is relevant.
510 511
511 512 $ hg init showstderr
512 513 $ cd showstderr
513 514
514 515 $ printf "hello\n" > hello.txt
515 516 $ hg add
516 517 adding hello.txt
517 518 $ cat >> $TESTTMP/cmd.sh <<'EOF'
518 519 > printf 'HELLO\n'
519 520 > printf "$@: some\nerror" >&2
520 521 > EOF
521 522 $ hg --config "fix.fail:command=sh $TESTTMP/cmd.sh {rootpath}" \
522 523 > --config "fix.fail:fileset=hello.txt" \
523 524 > fix --working-dir
524 525 [wdir] fail: hello.txt: some
525 526 [wdir] fail: error
526 527 $ cat hello.txt
527 528 hello
528 529
529 530 $ cd ..
530 531
531 532 Fixing the working directory and its parent revision at the same time should
532 533 check out the replacement revision for the parent. This prevents any new
533 534 uncommitted changes from appearing. We test this for a clean working directory
534 535 and a dirty one. In both cases, all lines/files changed since the grandparent
535 536 will be fixed. The grandparent is the "baserev" for both the parent and the
536 537 working copy.
537 538
538 539 $ hg init fixdotandcleanwdir
539 540 $ cd fixdotandcleanwdir
540 541
541 542 $ printf "hello\n" > hello.whole
542 543 $ printf "world\n" > world.whole
543 544 $ hg commit -Aqm "the parent commit"
544 545
545 546 $ hg parents --template '{rev} {desc}\n'
546 547 0 the parent commit
547 548 $ hg fix --working-dir -r .
548 549 $ hg parents --template '{rev} {desc}\n'
549 550 1 the parent commit
550 551 $ hg cat -r . *.whole
551 552 HELLO
552 553 WORLD
553 554 $ cat *.whole
554 555 HELLO
555 556 WORLD
556 557 $ hg status
557 558
558 559 $ cd ..
559 560
560 561 Same test with a dirty working copy.
561 562
562 563 $ hg init fixdotanddirtywdir
563 564 $ cd fixdotanddirtywdir
564 565
565 566 $ printf "hello\n" > hello.whole
566 567 $ printf "world\n" > world.whole
567 568 $ hg commit -Aqm "the parent commit"
568 569
569 570 $ printf "hello,\n" > hello.whole
570 571 $ printf "world!\n" > world.whole
571 572
572 573 $ hg parents --template '{rev} {desc}\n'
573 574 0 the parent commit
574 575 $ hg fix --working-dir -r .
575 576 $ hg parents --template '{rev} {desc}\n'
576 577 1 the parent commit
577 578 $ hg cat -r . *.whole
578 579 HELLO
579 580 WORLD
580 581 $ cat *.whole
581 582 HELLO,
582 583 WORLD!
583 584 $ hg status
584 585 M hello.whole
585 586 M world.whole
586 587
587 588 $ cd ..
588 589
589 590 When we have a chain of commits that change mutually exclusive lines of code,
590 591 we should be able to do incremental fixing that causes each commit in the chain
591 592 to include fixes made to the previous commits. This prevents children from
592 593 backing out the fixes made in their parents. A dirty working directory is
593 594 conceptually similar to another commit in the chain.
594 595
595 596 $ hg init incrementallyfixchain
596 597 $ cd incrementallyfixchain
597 598
598 599 $ cat > file.changed <<EOF
599 600 > first
600 601 > second
601 602 > third
602 603 > fourth
603 604 > fifth
604 605 > EOF
605 606 $ hg commit -Aqm "the common ancestor (the baserev)"
606 607 $ cat > file.changed <<EOF
607 608 > first (changed)
608 609 > second
609 610 > third
610 611 > fourth
611 612 > fifth
612 613 > EOF
613 614 $ hg commit -Aqm "the first commit to fix"
614 615 $ cat > file.changed <<EOF
615 616 > first (changed)
616 617 > second
617 618 > third (changed)
618 619 > fourth
619 620 > fifth
620 621 > EOF
621 622 $ hg commit -Aqm "the second commit to fix"
622 623 $ cat > file.changed <<EOF
623 624 > first (changed)
624 625 > second
625 626 > third (changed)
626 627 > fourth
627 628 > fifth (changed)
628 629 > EOF
629 630
630 631 $ hg fix -r . -r '.^' --working-dir
631 632
632 633 $ hg parents --template '{rev}\n'
633 634 4
634 635 $ hg cat -r '.^^' file.changed
635 636 first
636 637 second
637 638 third
638 639 fourth
639 640 fifth
640 641 $ hg cat -r '.^' file.changed
641 642 FIRST (CHANGED)
642 643 second
643 644 third
644 645 fourth
645 646 fifth
646 647 $ hg cat -r . file.changed
647 648 FIRST (CHANGED)
648 649 second
649 650 THIRD (CHANGED)
650 651 fourth
651 652 fifth
652 653 $ cat file.changed
653 654 FIRST (CHANGED)
654 655 second
655 656 THIRD (CHANGED)
656 657 fourth
657 658 FIFTH (CHANGED)
658 659
659 660 $ cd ..
660 661
661 662 If we incrementally fix a merge commit, we should fix any lines that changed
662 663 versus either parent. You could imagine only fixing the intersection or some
663 664 other subset, but this is necessary if either parent is being fixed. It
664 665 prevents us from forgetting fixes made in either parent.
665 666
666 667 $ hg init incrementallyfixmergecommit
667 668 $ cd incrementallyfixmergecommit
668 669
669 670 $ printf "a\nb\nc\n" > file.changed
670 671 $ hg commit -Aqm "ancestor"
671 672
672 673 $ printf "aa\nb\nc\n" > file.changed
673 674 $ hg commit -m "change a"
674 675
675 676 $ hg checkout '.^'
676 677 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
677 678 $ printf "a\nb\ncc\n" > file.changed
678 679 $ hg commit -m "change c"
679 680 created new head
680 681
681 682 $ hg merge
682 683 merging file.changed
683 684 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
684 685 (branch merge, don't forget to commit)
685 686 $ hg commit -m "merge"
686 687 $ hg cat -r . file.changed
687 688 aa
688 689 b
689 690 cc
690 691
691 692 $ hg fix -r . --working-dir
692 693 $ hg cat -r . file.changed
693 694 AA
694 695 b
695 696 CC
696 697
697 698 $ cd ..
698 699
699 700 Abort fixing revisions if there is an unfinished operation. We don't want to
700 701 make things worse by editing files or stripping/obsoleting things. Also abort
701 702 fixing the working directory if there are unresolved merge conflicts.
702 703
703 704 $ hg init abortunresolved
704 705 $ cd abortunresolved
705 706
706 707 $ echo "foo1" > foo.whole
707 708 $ hg commit -Aqm "foo 1"
708 709
709 710 $ hg update null
710 711 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
711 712 $ echo "foo2" > foo.whole
712 713 $ hg commit -Aqm "foo 2"
713 714
714 715 $ hg --config extensions.rebase= rebase -r 1 -d 0
715 716 rebasing 1:c3b6dc0e177a "foo 2" (tip)
716 717 merging foo.whole
717 718 warning: conflicts while merging foo.whole! (edit, then use 'hg resolve --mark')
718 719 unresolved conflicts (see hg resolve, then hg rebase --continue)
719 720 [1]
720 721
721 722 $ hg --config extensions.rebase= fix --working-dir
722 723 abort: unresolved conflicts
723 724 (use 'hg resolve')
724 725 [255]
725 726
726 727 $ hg --config extensions.rebase= fix -r .
727 728 abort: rebase in progress
728 729 (use 'hg rebase --continue' or 'hg rebase --abort')
729 730 [255]
730 731
731 732 When fixing a file that was renamed, we should diff against the source of the
732 733 rename for incremental fixing and we should correctly reproduce the rename in
733 734 the replacement revision.
734 735
735 736 $ hg init fixrenamecommit
736 737 $ cd fixrenamecommit
737 738
738 739 $ printf "a\nb\nc\n" > source.changed
739 740 $ hg commit -Aqm "source revision"
740 741 $ hg move source.changed dest.changed
741 742 $ printf "a\nb\ncc\n" > dest.changed
742 743 $ hg commit -m "dest revision"
743 744
744 745 $ hg fix -r .
745 746 $ hg log -r tip --copies --template "{file_copies}\n"
746 747 dest.changed (source.changed)
747 748 $ hg cat -r tip dest.changed
748 749 a
749 750 b
750 751 CC
751 752
752 753 $ cd ..
753 754
754 755 When fixing revisions that remove files we must ensure that the replacement
755 756 actually removes the file, whereas it could accidentally leave it unchanged or
756 757 write an empty string to it.
757 758
758 759 $ hg init fixremovedfile
759 760 $ cd fixremovedfile
760 761
761 762 $ printf "foo\n" > foo.whole
762 763 $ printf "bar\n" > bar.whole
763 764 $ hg commit -Aqm "add files"
764 765 $ hg remove bar.whole
765 766 $ hg commit -m "remove file"
766 767 $ hg status --change .
767 768 R bar.whole
768 769 $ hg fix -r . foo.whole
769 770 $ hg status --change tip
770 771 M foo.whole
771 772 R bar.whole
772 773
773 774 $ cd ..
774 775
775 776 If fixing a revision finds no fixes to make, no replacement revision should be
776 777 created.
777 778
778 779 $ hg init nofixesneeded
779 780 $ cd nofixesneeded
780 781
781 782 $ printf "FOO\n" > foo.whole
782 783 $ hg commit -Aqm "add file"
783 784 $ hg log --template '{rev}\n'
784 785 0
785 786 $ hg fix -r .
786 787 $ hg log --template '{rev}\n'
787 788 0
788 789
789 790 $ cd ..
790 791
791 792 If fixing a commit reverts all the changes in the commit, we replace it with a
792 793 commit that changes no files.
793 794
794 795 $ hg init nochangesleft
795 796 $ cd nochangesleft
796 797
797 798 $ printf "FOO\n" > foo.whole
798 799 $ hg commit -Aqm "add file"
799 800 $ printf "foo\n" > foo.whole
800 801 $ hg commit -m "edit file"
801 802 $ hg status --change .
802 803 M foo.whole
803 804 $ hg fix -r .
804 805 $ hg status --change tip
805 806
806 807 $ cd ..
807 808
808 809 If we fix a parent and child revision together, the child revision must be
809 810 replaced if the parent is replaced, even if the diffs of the child needed no
810 811 fixes. However, we're free to not replace revisions that need no fixes and have
811 812 no ancestors that are replaced.
812 813
813 814 $ hg init mustreplacechild
814 815 $ cd mustreplacechild
815 816
816 817 $ printf "FOO\n" > foo.whole
817 818 $ hg commit -Aqm "add foo"
818 819 $ printf "foo\n" > foo.whole
819 820 $ hg commit -m "edit foo"
820 821 $ printf "BAR\n" > bar.whole
821 822 $ hg commit -Aqm "add bar"
822 823
823 824 $ hg log --graph --template '{node|shortest} {files}'
824 825 @ bc05 bar.whole
825 826 |
826 827 o 4fd2 foo.whole
827 828 |
828 829 o f9ac foo.whole
829 830
830 831 $ hg fix -r 0:2
831 832 $ hg log --graph --template '{node|shortest} {files}'
832 833 o 3801 bar.whole
833 834 |
834 835 o 38cc
835 836 |
836 837 | @ bc05 bar.whole
837 838 | |
838 839 | x 4fd2 foo.whole
839 840 |/
840 841 o f9ac foo.whole
841 842
842 843
843 844 $ cd ..
844 845
845 846 It's also possible that the child needs absolutely no changes, but we still
846 847 need to replace it to update its parent. If we skipped replacing the child
847 848 because it had no file content changes, it would become an orphan for no good
848 849 reason.
849 850
850 851 $ hg init mustreplacechildevenifnop
851 852 $ cd mustreplacechildevenifnop
852 853
853 854 $ printf "Foo\n" > foo.whole
854 855 $ hg commit -Aqm "add a bad foo"
855 856 $ printf "FOO\n" > foo.whole
856 857 $ hg commit -m "add a good foo"
857 858 $ hg fix -r . -r '.^'
858 859 $ hg log --graph --template '{rev} {desc}'
859 860 o 3 add a good foo
860 861 |
861 862 o 2 add a bad foo
862 863
863 864 @ 1 add a good foo
864 865 |
865 866 x 0 add a bad foo
866 867
867 868
868 869 $ cd ..
869 870
870 871 Similar to the case above, the child revision may become empty as a result of
871 872 fixing its parent. We should still create an empty replacement child.
872 873 TODO: determine how this should interact with ui.allowemptycommit given that
873 874 the empty replacement could have children.
874 875
875 876 $ hg init mustreplacechildevenifempty
876 877 $ cd mustreplacechildevenifempty
877 878
878 879 $ printf "foo\n" > foo.whole
879 880 $ hg commit -Aqm "add foo"
880 881 $ printf "Foo\n" > foo.whole
881 882 $ hg commit -m "edit foo"
882 883 $ hg fix -r . -r '.^'
883 884 $ hg log --graph --template '{rev} {desc}\n' --stat
884 885 o 3 edit foo
885 886 |
886 887 o 2 add foo
887 888 foo.whole | 1 +
888 889 1 files changed, 1 insertions(+), 0 deletions(-)
889 890
890 891 @ 1 edit foo
891 892 | foo.whole | 2 +-
892 893 | 1 files changed, 1 insertions(+), 1 deletions(-)
893 894 |
894 895 x 0 add foo
895 896 foo.whole | 1 +
896 897 1 files changed, 1 insertions(+), 0 deletions(-)
897 898
898 899
899 900 $ cd ..
900 901
901 902 Fixing a secret commit should replace it with another secret commit.
902 903
903 904 $ hg init fixsecretcommit
904 905 $ cd fixsecretcommit
905 906
906 907 $ printf "foo\n" > foo.whole
907 908 $ hg commit -Aqm "add foo" --secret
908 909 $ hg fix -r .
909 910 $ hg log --template '{rev} {phase}\n'
910 911 1 secret
911 912 0 secret
912 913
913 914 $ cd ..
914 915
915 916 We should also preserve phase when fixing a draft commit while the user has
916 917 their default set to secret.
917 918
918 919 $ hg init respectphasesnewcommit
919 920 $ cd respectphasesnewcommit
920 921
921 922 $ printf "foo\n" > foo.whole
922 923 $ hg commit -Aqm "add foo"
923 924 $ hg --config phases.newcommit=secret fix -r .
924 925 $ hg log --template '{rev} {phase}\n'
925 926 1 draft
926 927 0 draft
927 928
928 929 $ cd ..
929 930
930 931 Debug output should show what fixer commands are being subprocessed, which is
931 932 useful for anyone trying to set up a new config.
932 933
933 934 $ hg init debugoutput
934 935 $ cd debugoutput
935 936
936 937 $ printf "foo\nbar\nbaz\n" > foo.changed
937 938 $ hg commit -Aqm "foo"
938 939 $ printf "Foo\nbar\nBaz\n" > foo.changed
939 940 $ hg --debug fix --working-dir
940 941 subprocess: * $TESTTMP/uppercase.py 1-1 3-3 (glob)
941 942
942 943 $ cd ..
943 944
944 945 Fixing an obsolete revision can cause divergence, so we abort unless the user
945 946 configures to allow it. This is not yet smart enough to know whether there is a
946 947 successor, but even then it is not likely intentional or idiomatic to fix an
947 948 obsolete revision.
948 949
949 950 $ hg init abortobsoleterev
950 951 $ cd abortobsoleterev
951 952
952 953 $ printf "foo\n" > foo.changed
953 954 $ hg commit -Aqm "foo"
954 955 $ hg debugobsolete `hg parents --template '{node}'`
955 956 obsoleted 1 changesets
956 957 $ hg --hidden fix -r 0
957 958 abort: fixing obsolete revision could cause divergence
958 959 [255]
959 960
960 961 $ hg --hidden fix -r 0 --config experimental.evolution.allowdivergence=true
961 962 $ hg cat -r tip foo.changed
962 963 FOO
963 964
964 965 $ cd ..
965 966
966 967 Test all of the available substitution values for fixer commands.
967 968
968 969 $ hg init substitution
969 970 $ cd substitution
970 971
971 972 $ mkdir foo
972 973 $ printf "hello\ngoodbye\n" > foo/bar
973 974 $ hg add
974 975 adding foo/bar
975 976 $ hg --config "fix.fail:command=printf '%s\n' '{rootpath}' '{basename}'" \
976 977 > --config "fix.fail:linerange='{first}' '{last}'" \
977 978 > --config "fix.fail:fileset=foo/bar" \
978 979 > fix --working-dir
979 980 $ cat foo/bar
980 981 foo/bar
981 982 bar
982 983 1
983 984 2
984 985
985 986 $ cd ..
986 987
987 988 The --base flag should allow picking the revisions to diff against for changed
988 989 files and incremental line formatting.
989 990
990 991 $ hg init baseflag
991 992 $ cd baseflag
992 993
993 994 $ printf "one\ntwo\n" > foo.changed
994 995 $ printf "bar\n" > bar.changed
995 996 $ hg commit -Aqm "first"
996 997 $ printf "one\nTwo\n" > foo.changed
997 998 $ hg commit -m "second"
998 999 $ hg fix -w --base .
999 1000 $ hg status
1000 1001 $ hg fix -w --base null
1001 1002 $ cat foo.changed
1002 1003 ONE
1003 1004 TWO
1004 1005 $ cat bar.changed
1005 1006 BAR
1006 1007
1007 1008 $ cd ..
1008 1009
1009 1010 If the user asks to fix the parent of another commit, they are asking to create
1010 1011 an orphan. We must respect experimental.evolution.allowunstable.
1011 1012
1012 1013 $ hg init allowunstable
1013 1014 $ cd allowunstable
1014 1015
1015 1016 $ printf "one\n" > foo.whole
1016 1017 $ hg commit -Aqm "first"
1017 1018 $ printf "two\n" > foo.whole
1018 1019 $ hg commit -m "second"
1019 1020 $ hg --config experimental.evolution.allowunstable=False fix -r '.^'
1020 1021 abort: can only fix a changeset together with all its descendants
1021 1022 [255]
1022 1023 $ hg fix -r '.^'
1023 1024 1 new orphan changesets
1024 1025 $ hg cat -r 2 foo.whole
1025 1026 ONE
1026 1027
1027 1028 $ cd ..
1028 1029
General Comments 0
You need to be logged in to leave comments. Login now