##// END OF EJS Templates
tests: stabilize test-fix.t on Windows...
Matt Harbison -
r43208:a2dffe68 default
parent child Browse files
Show More
@@ -1,1399 +1,1405 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:pattern=set:**.whole
70 70 > uppercase-changed-lines:command="$PYTHON" $UPPERCASEPY
71 71 > uppercase-changed-lines:linerange={first}-{last}
72 72 > uppercase-changed-lines:pattern=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:pattern=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. Any output on standard
134 134 error will be displayed as a warning. If the exit status is not zero, the file
135 135 will not be affected. A placeholder warning is displayed if there is a non-
136 136 zero exit status but no standard error output. Some values may be substituted
137 137 into the command:
138 138
139 139 {rootpath} The path of the file being fixed, relative to the repo root
140 140 {basename} The name of the file being fixed, without the directory path
141 141
142 142 If the :linerange suboption is set, the tool will only be run if there are
143 143 changed lines in a file. The value of this suboption is appended to the shell
144 144 command once for every range of changed lines in the file. Some values may be
145 145 substituted into the command:
146 146
147 147 {first} The 1-based line number of the first line in the modified range
148 148 {last} The 1-based line number of the last line in the modified range
149 149
150 150 Deleted sections of a file will be ignored by :linerange, because there is no
151 151 corresponding line range in the version being fixed.
152 152
153 153 By default, tools that set :linerange will only be executed if there is at
154 154 least one changed line range. This is meant to prevent accidents like running
155 155 a code formatter in such a way that it unexpectedly reformats the whole file.
156 156 If such a tool needs to operate on unchanged files, it should set the
157 157 :skipclean suboption to false.
158 158
159 159 The :pattern suboption determines which files will be passed through each
160 160 configured tool. See 'hg help patterns' for possible values. If there are file
161 161 arguments to 'hg fix', the intersection of these patterns is used.
162 162
163 163 There is also a configurable limit for the maximum size of file that will be
164 164 processed by 'hg fix':
165 165
166 166 [fix]
167 167 maxfilesize = 2MB
168 168
169 169 Normally, execution of configured tools will continue after a failure
170 170 (indicated by a non-zero exit status). It can also be configured to abort
171 171 after the first such failure, so that no files will be affected if any tool
172 172 fails. This abort will also cause 'hg fix' to exit with a non-zero status:
173 173
174 174 [fix]
175 175 failure = abort
176 176
177 177 When multiple tools are configured to affect a file, they execute in an order
178 178 defined by the :priority suboption. The priority suboption has a default value
179 179 of zero for each tool. Tools are executed in order of descending priority. The
180 180 execution order of tools with equal priority is unspecified. For example, you
181 181 could use the 'sort' and 'head' utilities to keep only the 10 smallest numbers
182 182 in a text file by ensuring that 'sort' runs before 'head':
183 183
184 184 [fix]
185 185 sort:command = sort -n
186 186 head:command = head -n 10
187 187 sort:pattern = numbers.txt
188 188 head:pattern = numbers.txt
189 189 sort:priority = 2
190 190 head:priority = 1
191 191
192 192 To account for changes made by each tool, the line numbers used for
193 193 incremental formatting are recomputed before executing the next tool. So, each
194 194 tool may see different values for the arguments added by the :linerange
195 195 suboption.
196 196
197 197 Each fixer tool is allowed to return some metadata in addition to the fixed
198 198 file content. The metadata must be placed before the file content on stdout,
199 199 separated from the file content by a zero byte. The metadata is parsed as a
200 200 JSON value (so, it should be UTF-8 encoded and contain no zero bytes). A fixer
201 201 tool is expected to produce this metadata encoding if and only if the
202 202 :metadata suboption is true:
203 203
204 204 [fix]
205 205 tool:command = tool --prepend-json-metadata
206 206 tool:metadata = true
207 207
208 208 The metadata values are passed to hooks, which can be used to print summaries
209 209 or perform other post-fixing work. The supported hooks are:
210 210
211 211 "postfixfile"
212 212 Run once for each file in each revision where any fixer tools made changes
213 213 to the file content. Provides "$HG_REV" and "$HG_PATH" to identify the file,
214 214 and "$HG_METADATA" with a map of fixer names to metadata values from fixer
215 215 tools that affected the file. Fixer tools that didn't affect the file have a
216 216 valueof None. Only fixer tools that executed are present in the metadata.
217 217
218 218 "postfix"
219 219 Run once after all files and revisions have been handled. Provides
220 220 "$HG_REPLACEMENTS" with information about what revisions were created and
221 221 made obsolete. Provides a boolean "$HG_WDIRWRITTEN" to indicate whether any
222 222 files in the working copy were updated. Provides a list "$HG_METADATA"
223 223 mapping fixer tool names to lists of metadata values returned from
224 224 executions that modified a file. This aggregates the same metadata
225 225 previously passed to the "postfixfile" hook.
226 226
227 227 Fixer tools are run the in repository's root directory. This allows them to
228 228 read configuration files from the working copy, or even write to the working
229 229 copy. The working copy is not updated to match the revision being fixed. In
230 230 fact, several revisions may be fixed in parallel. Writes to the working copy
231 231 are not amended into the revision being fixed; fixer tools should always write
232 232 fixed file content back to stdout as documented above.
233 233
234 234 list of commands:
235 235
236 236 fix rewrite file content in changesets or working directory
237 237
238 238 (use 'hg help -v -e fix' to show built-in aliases and global options)
239 239
240 240 There is no default behavior in the absence of --rev and --working-dir.
241 241
242 242 $ hg init badusage
243 243 $ cd badusage
244 244
245 245 $ hg fix
246 246 abort: no changesets specified
247 247 (use --rev or --working-dir)
248 248 [255]
249 249 $ hg fix --whole
250 250 abort: no changesets specified
251 251 (use --rev or --working-dir)
252 252 [255]
253 253 $ hg fix --base 0
254 254 abort: no changesets specified
255 255 (use --rev or --working-dir)
256 256 [255]
257 257
258 258 Fixing a public revision isn't allowed. It should abort early enough that
259 259 nothing happens, even to the working directory.
260 260
261 261 $ printf "hello\n" > hello.whole
262 262 $ hg commit -Aqm "hello"
263 263 $ hg phase -r 0 --public
264 264 $ hg fix -r 0
265 265 abort: can't fix immutable changeset 0:6470986d2e7b
266 266 [255]
267 267 $ hg fix -r 0 --working-dir
268 268 abort: can't fix immutable changeset 0:6470986d2e7b
269 269 [255]
270 270 $ hg cat -r tip hello.whole
271 271 hello
272 272 $ cat hello.whole
273 273 hello
274 274
275 275 $ cd ..
276 276
277 277 Fixing a clean working directory should do nothing. Even the --whole flag
278 278 shouldn't cause any clean files to be fixed. Specifying a clean file explicitly
279 279 should only fix it if the fixer always fixes the whole file. The combination of
280 280 an explicit filename and --whole should format the entire file regardless.
281 281
282 282 $ hg init fixcleanwdir
283 283 $ cd fixcleanwdir
284 284
285 285 $ printf "hello\n" > hello.changed
286 286 $ printf "world\n" > hello.whole
287 287 $ hg commit -Aqm "foo"
288 288 $ hg fix --working-dir
289 289 $ hg diff
290 290 $ hg fix --working-dir --whole
291 291 $ hg diff
292 292 $ hg fix --working-dir *
293 293 $ cat *
294 294 hello
295 295 WORLD
296 296 $ hg revert --all --no-backup
297 297 reverting hello.whole
298 298 $ hg fix --working-dir * --whole
299 299 $ cat *
300 300 HELLO
301 301 WORLD
302 302
303 303 The same ideas apply to fixing a revision, so we create a revision that doesn't
304 304 modify either of the files in question and try fixing it. This also tests that
305 305 we ignore a file that doesn't match any configured fixer.
306 306
307 307 $ hg revert --all --no-backup
308 308 reverting hello.changed
309 309 reverting hello.whole
310 310 $ printf "unimportant\n" > some.file
311 311 $ hg commit -Aqm "some other file"
312 312
313 313 $ hg fix -r .
314 314 $ hg cat -r tip *
315 315 hello
316 316 world
317 317 unimportant
318 318 $ hg fix -r . --whole
319 319 $ hg cat -r tip *
320 320 hello
321 321 world
322 322 unimportant
323 323 $ hg fix -r . *
324 324 $ hg cat -r tip *
325 325 hello
326 326 WORLD
327 327 unimportant
328 328 $ hg fix -r . * --whole --config experimental.evolution.allowdivergence=true
329 329 2 new content-divergent changesets
330 330 $ hg cat -r tip *
331 331 HELLO
332 332 WORLD
333 333 unimportant
334 334
335 335 $ cd ..
336 336
337 337 Fixing the working directory should still work if there are no revisions.
338 338
339 339 $ hg init norevisions
340 340 $ cd norevisions
341 341
342 342 $ printf "something\n" > something.whole
343 343 $ hg add
344 344 adding something.whole
345 345 $ hg fix --working-dir
346 346 $ cat something.whole
347 347 SOMETHING
348 348
349 349 $ cd ..
350 350
351 351 Test the effect of fixing the working directory for each possible status, with
352 352 and without providing explicit file arguments.
353 353
354 354 $ hg init implicitlyfixstatus
355 355 $ cd implicitlyfixstatus
356 356
357 357 $ printf "modified\n" > modified.whole
358 358 $ printf "removed\n" > removed.whole
359 359 $ printf "deleted\n" > deleted.whole
360 360 $ printf "clean\n" > clean.whole
361 361 $ printf "ignored.whole" > .hgignore
362 362 $ hg commit -Aqm "stuff"
363 363
364 364 $ printf "modified!!!\n" > modified.whole
365 365 $ printf "unknown\n" > unknown.whole
366 366 $ printf "ignored\n" > ignored.whole
367 367 $ printf "added\n" > added.whole
368 368 $ hg add added.whole
369 369 $ hg remove removed.whole
370 370 $ rm deleted.whole
371 371
372 372 $ hg status --all
373 373 M modified.whole
374 374 A added.whole
375 375 R removed.whole
376 376 ! deleted.whole
377 377 ? unknown.whole
378 378 I ignored.whole
379 379 C .hgignore
380 380 C clean.whole
381 381
382 382 $ hg fix --working-dir
383 383
384 384 $ hg status --all
385 385 M modified.whole
386 386 A added.whole
387 387 R removed.whole
388 388 ! deleted.whole
389 389 ? unknown.whole
390 390 I ignored.whole
391 391 C .hgignore
392 392 C clean.whole
393 393
394 394 $ cat *.whole
395 395 ADDED
396 396 clean
397 397 ignored
398 398 MODIFIED!!!
399 399 unknown
400 400
401 401 $ printf "modified!!!\n" > modified.whole
402 402 $ printf "added\n" > added.whole
403 403
404 404 Listing the files explicitly causes untracked files to also be fixed, but
405 405 ignored files are still unaffected.
406 406
407 407 $ hg fix --working-dir *.whole
408 408
409 409 $ hg status --all
410 410 M clean.whole
411 411 M modified.whole
412 412 A added.whole
413 413 R removed.whole
414 414 ! deleted.whole
415 415 ? unknown.whole
416 416 I ignored.whole
417 417 C .hgignore
418 418
419 419 $ cat *.whole
420 420 ADDED
421 421 CLEAN
422 422 ignored
423 423 MODIFIED!!!
424 424 UNKNOWN
425 425
426 426 $ cd ..
427 427
428 428 Test that incremental fixing works on files with additions, deletions, and
429 429 changes in multiple line ranges. Note that deletions do not generally cause
430 430 neighboring lines to be fixed, so we don't return a line range for purely
431 431 deleted sections. In the future we should support a :deletion config that
432 432 allows fixers to know where deletions are located.
433 433
434 434 $ hg init incrementalfixedlines
435 435 $ cd incrementalfixedlines
436 436
437 437 $ printf "a\nb\nc\nd\ne\nf\ng\n" > foo.txt
438 438 $ hg commit -Aqm "foo"
439 439 $ printf "zz\na\nc\ndd\nee\nff\nf\ngg\n" > foo.txt
440 440
441 441 $ hg --config "fix.fail:command=echo" \
442 442 > --config "fix.fail:linerange={first}:{last}" \
443 443 > --config "fix.fail:pattern=foo.txt" \
444 444 > fix --working-dir
445 445 $ cat foo.txt
446 446 1:1 4:6 8:8
447 447
448 448 $ cd ..
449 449
450 450 Test that --whole fixes all lines regardless of the diffs present.
451 451
452 452 $ hg init wholeignoresdiffs
453 453 $ cd wholeignoresdiffs
454 454
455 455 $ printf "a\nb\nc\nd\ne\nf\ng\n" > foo.changed
456 456 $ hg commit -Aqm "foo"
457 457 $ printf "zz\na\nc\ndd\nee\nff\nf\ngg\n" > foo.changed
458 458
459 459 $ hg fix --working-dir
460 460 $ cat foo.changed
461 461 ZZ
462 462 a
463 463 c
464 464 DD
465 465 EE
466 466 FF
467 467 f
468 468 GG
469 469
470 470 $ hg fix --working-dir --whole
471 471 $ cat foo.changed
472 472 ZZ
473 473 A
474 474 C
475 475 DD
476 476 EE
477 477 FF
478 478 F
479 479 GG
480 480
481 481 $ cd ..
482 482
483 483 We should do nothing with symlinks, and their targets should be unaffected. Any
484 484 other behavior would be more complicated to implement and harder to document.
485 485
486 486 #if symlink
487 487 $ hg init dontmesswithsymlinks
488 488 $ cd dontmesswithsymlinks
489 489
490 490 $ printf "hello\n" > hello.whole
491 491 $ ln -s hello.whole hellolink
492 492 $ hg add
493 493 adding hello.whole
494 494 adding hellolink
495 495 $ hg fix --working-dir hellolink
496 496 $ hg status
497 497 A hello.whole
498 498 A hellolink
499 499
500 500 $ cd ..
501 501 #endif
502 502
503 503 We should allow fixers to run on binary files, even though this doesn't sound
504 504 like a common use case. There's not much benefit to disallowing it, and users
505 505 can add "and not binary()" to their filesets if needed. The Mercurial
506 506 philosophy is generally to not handle binary files specially anyway.
507 507
508 508 $ hg init cantouchbinaryfiles
509 509 $ cd cantouchbinaryfiles
510 510
511 511 $ printf "hello\0\n" > hello.whole
512 512 $ hg add
513 513 adding hello.whole
514 514 $ hg fix --working-dir 'set:binary()'
515 515 $ cat hello.whole
516 516 HELLO\x00 (esc)
517 517
518 518 $ cd ..
519 519
520 520 We have a config for the maximum size of file we will attempt to fix. This can
521 521 be helpful to avoid running unsuspecting fixer tools on huge inputs, which
522 522 could happen by accident without a well considered configuration. A more
523 523 precise configuration could use the size() fileset function if one global limit
524 524 is undesired.
525 525
526 526 $ hg init maxfilesize
527 527 $ cd maxfilesize
528 528
529 529 $ printf "this file is huge\n" > hello.whole
530 530 $ hg add
531 531 adding hello.whole
532 532 $ hg --config fix.maxfilesize=10 fix --working-dir
533 533 ignoring file larger than 10 bytes: hello.whole
534 534 $ cat hello.whole
535 535 this file is huge
536 536
537 537 $ cd ..
538 538
539 539 If we specify a file to fix, other files should be left alone, even if they
540 540 have changes.
541 541
542 542 $ hg init fixonlywhatitellyouto
543 543 $ cd fixonlywhatitellyouto
544 544
545 545 $ printf "fix me!\n" > fixme.whole
546 546 $ printf "not me.\n" > notme.whole
547 547 $ hg add
548 548 adding fixme.whole
549 549 adding notme.whole
550 550 $ hg fix --working-dir fixme.whole
551 551 $ cat *.whole
552 552 FIX ME!
553 553 not me.
554 554
555 555 $ cd ..
556 556
557 557 If we try to fix a missing file, we still fix other files.
558 558
559 559 $ hg init fixmissingfile
560 560 $ cd fixmissingfile
561 561
562 562 $ printf "fix me!\n" > foo.whole
563 563 $ hg add
564 564 adding foo.whole
565 565 $ hg fix --working-dir foo.whole bar.whole
566 566 bar.whole: $ENOENT$
567 567 $ cat *.whole
568 568 FIX ME!
569 569
570 570 $ cd ..
571 571
572 572 Specifying a directory name should fix all its files and subdirectories.
573 573
574 574 $ hg init fixdirectory
575 575 $ cd fixdirectory
576 576
577 577 $ mkdir -p dir1/dir2
578 578 $ printf "foo\n" > foo.whole
579 579 $ printf "bar\n" > dir1/bar.whole
580 580 $ printf "baz\n" > dir1/dir2/baz.whole
581 581 $ hg add
582 582 adding dir1/bar.whole
583 583 adding dir1/dir2/baz.whole
584 584 adding foo.whole
585 585 $ hg fix --working-dir dir1
586 586 $ cat foo.whole dir1/bar.whole dir1/dir2/baz.whole
587 587 foo
588 588 BAR
589 589 BAZ
590 590
591 591 $ cd ..
592 592
593 593 Fixing a file in the working directory that needs no fixes should not actually
594 594 write back to the file, so for example the mtime shouldn't change.
595 595
596 596 $ hg init donttouchunfixedfiles
597 597 $ cd donttouchunfixedfiles
598 598
599 599 $ printf "NO FIX NEEDED\n" > foo.whole
600 600 $ hg add
601 601 adding foo.whole
602 602 $ cp -p foo.whole foo.whole.orig
603 603 $ cp -p foo.whole.orig foo.whole
604 604 $ sleep 2 # mtime has a resolution of one or two seconds.
605 605 $ hg fix --working-dir
606 606 $ f foo.whole.orig --newer foo.whole
607 607 foo.whole.orig: newer than foo.whole
608 608
609 609 $ cd ..
610 610
611 611 When a fixer prints to stderr, we don't assume that it has failed. We show the
612 612 error messages to the user, and we still let the fixer affect the file it was
613 613 fixing if its exit code is zero. Some code formatters might emit error messages
614 614 on stderr and nothing on stdout, which would cause us the clear the file,
615 615 except that they also exit with a non-zero code. We show the user which fixer
616 616 emitted the stderr, and which revision, but we assume that the fixer will print
617 617 the filename if it is relevant (since the issue may be non-specific). There is
618 618 also a config to abort (without affecting any files whatsoever) if we see any
619 619 tool with a non-zero exit status.
620 620
621 621 $ hg init showstderr
622 622 $ cd showstderr
623 623
624 624 $ printf "hello\n" > hello.txt
625 625 $ hg add
626 626 adding hello.txt
627 627 $ cat > $TESTTMP/work.sh <<'EOF'
628 628 > printf 'HELLO\n'
629 629 > printf "$@: some\nerror that didn't stop the tool" >&2
630 630 > exit 0 # success despite the stderr output
631 631 > EOF
632 632 $ hg --config "fix.work:command=sh $TESTTMP/work.sh {rootpath}" \
633 633 > --config "fix.work:pattern=hello.txt" \
634 634 > fix --working-dir
635 635 [wdir] work: hello.txt: some
636 636 [wdir] work: error that didn't stop the tool
637 637 $ cat hello.txt
638 638 HELLO
639 639
640 640 $ printf "goodbye\n" > hello.txt
641 641 $ printf "foo\n" > foo.whole
642 642 $ hg add
643 643 adding foo.whole
644 644 $ cat > $TESTTMP/fail.sh <<'EOF'
645 645 > printf 'GOODBYE\n'
646 646 > printf "$@: some\nerror that did stop the tool\n" >&2
647 647 > exit 42 # success despite the stdout output
648 648 > EOF
649 649 $ hg --config "fix.fail:command=sh $TESTTMP/fail.sh {rootpath}" \
650 650 > --config "fix.fail:pattern=hello.txt" \
651 651 > --config "fix.failure=abort" \
652 652 > fix --working-dir
653 653 [wdir] fail: hello.txt: some
654 654 [wdir] fail: error that did stop the tool
655 655 abort: no fixes will be applied
656 656 (use --config fix.failure=continue to apply any successful fixes anyway)
657 657 [255]
658 658 $ cat hello.txt
659 659 goodbye
660 660 $ cat foo.whole
661 661 foo
662 662
663 663 $ hg --config "fix.fail:command=sh $TESTTMP/fail.sh {rootpath}" \
664 664 > --config "fix.fail:pattern=hello.txt" \
665 665 > fix --working-dir
666 666 [wdir] fail: hello.txt: some
667 667 [wdir] fail: error that did stop the tool
668 668 $ cat hello.txt
669 669 goodbye
670 670 $ cat foo.whole
671 671 FOO
672 672
673 673 $ hg --config "fix.fail:command=exit 42" \
674 674 > --config "fix.fail:pattern=hello.txt" \
675 675 > fix --working-dir
676 676 [wdir] fail: exited with status 42
677 677
678 678 $ cd ..
679 679
680 680 Fixing the working directory and its parent revision at the same time should
681 681 check out the replacement revision for the parent. This prevents any new
682 682 uncommitted changes from appearing. We test this for a clean working directory
683 683 and a dirty one. In both cases, all lines/files changed since the grandparent
684 684 will be fixed. The grandparent is the "baserev" for both the parent and the
685 685 working copy.
686 686
687 687 $ hg init fixdotandcleanwdir
688 688 $ cd fixdotandcleanwdir
689 689
690 690 $ printf "hello\n" > hello.whole
691 691 $ printf "world\n" > world.whole
692 692 $ hg commit -Aqm "the parent commit"
693 693
694 694 $ hg parents --template '{rev} {desc}\n'
695 695 0 the parent commit
696 696 $ hg fix --working-dir -r .
697 697 $ hg parents --template '{rev} {desc}\n'
698 698 1 the parent commit
699 699 $ hg cat -r . *.whole
700 700 HELLO
701 701 WORLD
702 702 $ cat *.whole
703 703 HELLO
704 704 WORLD
705 705 $ hg status
706 706
707 707 $ cd ..
708 708
709 709 Same test with a dirty working copy.
710 710
711 711 $ hg init fixdotanddirtywdir
712 712 $ cd fixdotanddirtywdir
713 713
714 714 $ printf "hello\n" > hello.whole
715 715 $ printf "world\n" > world.whole
716 716 $ hg commit -Aqm "the parent commit"
717 717
718 718 $ printf "hello,\n" > hello.whole
719 719 $ printf "world!\n" > world.whole
720 720
721 721 $ hg parents --template '{rev} {desc}\n'
722 722 0 the parent commit
723 723 $ hg fix --working-dir -r .
724 724 $ hg parents --template '{rev} {desc}\n'
725 725 1 the parent commit
726 726 $ hg cat -r . *.whole
727 727 HELLO
728 728 WORLD
729 729 $ cat *.whole
730 730 HELLO,
731 731 WORLD!
732 732 $ hg status
733 733 M hello.whole
734 734 M world.whole
735 735
736 736 $ cd ..
737 737
738 738 When we have a chain of commits that change mutually exclusive lines of code,
739 739 we should be able to do incremental fixing that causes each commit in the chain
740 740 to include fixes made to the previous commits. This prevents children from
741 741 backing out the fixes made in their parents. A dirty working directory is
742 742 conceptually similar to another commit in the chain.
743 743
744 744 $ hg init incrementallyfixchain
745 745 $ cd incrementallyfixchain
746 746
747 747 $ cat > file.changed <<EOF
748 748 > first
749 749 > second
750 750 > third
751 751 > fourth
752 752 > fifth
753 753 > EOF
754 754 $ hg commit -Aqm "the common ancestor (the baserev)"
755 755 $ cat > file.changed <<EOF
756 756 > first (changed)
757 757 > second
758 758 > third
759 759 > fourth
760 760 > fifth
761 761 > EOF
762 762 $ hg commit -Aqm "the first commit to fix"
763 763 $ cat > file.changed <<EOF
764 764 > first (changed)
765 765 > second
766 766 > third (changed)
767 767 > fourth
768 768 > fifth
769 769 > EOF
770 770 $ hg commit -Aqm "the second commit to fix"
771 771 $ cat > file.changed <<EOF
772 772 > first (changed)
773 773 > second
774 774 > third (changed)
775 775 > fourth
776 776 > fifth (changed)
777 777 > EOF
778 778
779 779 $ hg fix -r . -r '.^' --working-dir
780 780
781 781 $ hg parents --template '{rev}\n'
782 782 4
783 783 $ hg cat -r '.^^' file.changed
784 784 first
785 785 second
786 786 third
787 787 fourth
788 788 fifth
789 789 $ hg cat -r '.^' file.changed
790 790 FIRST (CHANGED)
791 791 second
792 792 third
793 793 fourth
794 794 fifth
795 795 $ hg cat -r . file.changed
796 796 FIRST (CHANGED)
797 797 second
798 798 THIRD (CHANGED)
799 799 fourth
800 800 fifth
801 801 $ cat file.changed
802 802 FIRST (CHANGED)
803 803 second
804 804 THIRD (CHANGED)
805 805 fourth
806 806 FIFTH (CHANGED)
807 807
808 808 $ cd ..
809 809
810 810 If we incrementally fix a merge commit, we should fix any lines that changed
811 811 versus either parent. You could imagine only fixing the intersection or some
812 812 other subset, but this is necessary if either parent is being fixed. It
813 813 prevents us from forgetting fixes made in either parent.
814 814
815 815 $ hg init incrementallyfixmergecommit
816 816 $ cd incrementallyfixmergecommit
817 817
818 818 $ printf "a\nb\nc\n" > file.changed
819 819 $ hg commit -Aqm "ancestor"
820 820
821 821 $ printf "aa\nb\nc\n" > file.changed
822 822 $ hg commit -m "change a"
823 823
824 824 $ hg checkout '.^'
825 825 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
826 826 $ printf "a\nb\ncc\n" > file.changed
827 827 $ hg commit -m "change c"
828 828 created new head
829 829
830 830 $ hg merge
831 831 merging file.changed
832 832 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
833 833 (branch merge, don't forget to commit)
834 834 $ hg commit -m "merge"
835 835 $ hg cat -r . file.changed
836 836 aa
837 837 b
838 838 cc
839 839
840 840 $ hg fix -r . --working-dir
841 841 $ hg cat -r . file.changed
842 842 AA
843 843 b
844 844 CC
845 845
846 846 $ cd ..
847 847
848 848 Abort fixing revisions if there is an unfinished operation. We don't want to
849 849 make things worse by editing files or stripping/obsoleting things. Also abort
850 850 fixing the working directory if there are unresolved merge conflicts.
851 851
852 852 $ hg init abortunresolved
853 853 $ cd abortunresolved
854 854
855 855 $ echo "foo1" > foo.whole
856 856 $ hg commit -Aqm "foo 1"
857 857
858 858 $ hg update null
859 859 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
860 860 $ echo "foo2" > foo.whole
861 861 $ hg commit -Aqm "foo 2"
862 862
863 863 $ hg --config extensions.rebase= rebase -r 1 -d 0
864 864 rebasing 1:c3b6dc0e177a "foo 2" (tip)
865 865 merging foo.whole
866 866 warning: conflicts while merging foo.whole! (edit, then use 'hg resolve --mark')
867 867 unresolved conflicts (see hg resolve, then hg rebase --continue)
868 868 [1]
869 869
870 870 $ hg --config extensions.rebase= fix --working-dir
871 871 abort: unresolved conflicts
872 872 (use 'hg resolve')
873 873 [255]
874 874
875 875 $ hg --config extensions.rebase= fix -r .
876 876 abort: rebase in progress
877 877 (use 'hg rebase --continue' or 'hg rebase --abort')
878 878 [255]
879 879
880 880 $ cd ..
881 881
882 882 When fixing a file that was renamed, we should diff against the source of the
883 883 rename for incremental fixing and we should correctly reproduce the rename in
884 884 the replacement revision.
885 885
886 886 $ hg init fixrenamecommit
887 887 $ cd fixrenamecommit
888 888
889 889 $ printf "a\nb\nc\n" > source.changed
890 890 $ hg commit -Aqm "source revision"
891 891 $ hg move source.changed dest.changed
892 892 $ printf "a\nb\ncc\n" > dest.changed
893 893 $ hg commit -m "dest revision"
894 894
895 895 $ hg fix -r .
896 896 $ hg log -r tip --copies --template "{file_copies}\n"
897 897 dest.changed (source.changed)
898 898 $ hg cat -r tip dest.changed
899 899 a
900 900 b
901 901 CC
902 902
903 903 $ cd ..
904 904
905 905 When fixing revisions that remove files we must ensure that the replacement
906 906 actually removes the file, whereas it could accidentally leave it unchanged or
907 907 write an empty string to it.
908 908
909 909 $ hg init fixremovedfile
910 910 $ cd fixremovedfile
911 911
912 912 $ printf "foo\n" > foo.whole
913 913 $ printf "bar\n" > bar.whole
914 914 $ hg commit -Aqm "add files"
915 915 $ hg remove bar.whole
916 916 $ hg commit -m "remove file"
917 917 $ hg status --change .
918 918 R bar.whole
919 919 $ hg fix -r . foo.whole
920 920 $ hg status --change tip
921 921 M foo.whole
922 922 R bar.whole
923 923
924 924 $ cd ..
925 925
926 926 If fixing a revision finds no fixes to make, no replacement revision should be
927 927 created.
928 928
929 929 $ hg init nofixesneeded
930 930 $ cd nofixesneeded
931 931
932 932 $ printf "FOO\n" > foo.whole
933 933 $ hg commit -Aqm "add file"
934 934 $ hg log --template '{rev}\n'
935 935 0
936 936 $ hg fix -r .
937 937 $ hg log --template '{rev}\n'
938 938 0
939 939
940 940 $ cd ..
941 941
942 942 If fixing a commit reverts all the changes in the commit, we replace it with a
943 943 commit that changes no files.
944 944
945 945 $ hg init nochangesleft
946 946 $ cd nochangesleft
947 947
948 948 $ printf "FOO\n" > foo.whole
949 949 $ hg commit -Aqm "add file"
950 950 $ printf "foo\n" > foo.whole
951 951 $ hg commit -m "edit file"
952 952 $ hg status --change .
953 953 M foo.whole
954 954 $ hg fix -r .
955 955 $ hg status --change tip
956 956
957 957 $ cd ..
958 958
959 959 If we fix a parent and child revision together, the child revision must be
960 960 replaced if the parent is replaced, even if the diffs of the child needed no
961 961 fixes. However, we're free to not replace revisions that need no fixes and have
962 962 no ancestors that are replaced.
963 963
964 964 $ hg init mustreplacechild
965 965 $ cd mustreplacechild
966 966
967 967 $ printf "FOO\n" > foo.whole
968 968 $ hg commit -Aqm "add foo"
969 969 $ printf "foo\n" > foo.whole
970 970 $ hg commit -m "edit foo"
971 971 $ printf "BAR\n" > bar.whole
972 972 $ hg commit -Aqm "add bar"
973 973
974 974 $ hg log --graph --template '{rev} {files}'
975 975 @ 2 bar.whole
976 976 |
977 977 o 1 foo.whole
978 978 |
979 979 o 0 foo.whole
980 980
981 981 $ hg fix -r 0:2
982 982 $ hg log --graph --template '{rev} {files}'
983 983 o 4 bar.whole
984 984 |
985 985 o 3
986 986 |
987 987 | @ 2 bar.whole
988 988 | |
989 989 | x 1 foo.whole
990 990 |/
991 991 o 0 foo.whole
992 992
993 993
994 994 $ cd ..
995 995
996 996 It's also possible that the child needs absolutely no changes, but we still
997 997 need to replace it to update its parent. If we skipped replacing the child
998 998 because it had no file content changes, it would become an orphan for no good
999 999 reason.
1000 1000
1001 1001 $ hg init mustreplacechildevenifnop
1002 1002 $ cd mustreplacechildevenifnop
1003 1003
1004 1004 $ printf "Foo\n" > foo.whole
1005 1005 $ hg commit -Aqm "add a bad foo"
1006 1006 $ printf "FOO\n" > foo.whole
1007 1007 $ hg commit -m "add a good foo"
1008 1008 $ hg fix -r . -r '.^'
1009 1009 $ hg log --graph --template '{rev} {desc}'
1010 1010 o 3 add a good foo
1011 1011 |
1012 1012 o 2 add a bad foo
1013 1013
1014 1014 @ 1 add a good foo
1015 1015 |
1016 1016 x 0 add a bad foo
1017 1017
1018 1018
1019 1019 $ cd ..
1020 1020
1021 1021 Similar to the case above, the child revision may become empty as a result of
1022 1022 fixing its parent. We should still create an empty replacement child.
1023 1023 TODO: determine how this should interact with ui.allowemptycommit given that
1024 1024 the empty replacement could have children.
1025 1025
1026 1026 $ hg init mustreplacechildevenifempty
1027 1027 $ cd mustreplacechildevenifempty
1028 1028
1029 1029 $ printf "foo\n" > foo.whole
1030 1030 $ hg commit -Aqm "add foo"
1031 1031 $ printf "Foo\n" > foo.whole
1032 1032 $ hg commit -m "edit foo"
1033 1033 $ hg fix -r . -r '.^'
1034 1034 $ hg log --graph --template '{rev} {desc}\n' --stat
1035 1035 o 3 edit foo
1036 1036 |
1037 1037 o 2 add foo
1038 1038 foo.whole | 1 +
1039 1039 1 files changed, 1 insertions(+), 0 deletions(-)
1040 1040
1041 1041 @ 1 edit foo
1042 1042 | foo.whole | 2 +-
1043 1043 | 1 files changed, 1 insertions(+), 1 deletions(-)
1044 1044 |
1045 1045 x 0 add foo
1046 1046 foo.whole | 1 +
1047 1047 1 files changed, 1 insertions(+), 0 deletions(-)
1048 1048
1049 1049
1050 1050 $ cd ..
1051 1051
1052 1052 Fixing a secret commit should replace it with another secret commit.
1053 1053
1054 1054 $ hg init fixsecretcommit
1055 1055 $ cd fixsecretcommit
1056 1056
1057 1057 $ printf "foo\n" > foo.whole
1058 1058 $ hg commit -Aqm "add foo" --secret
1059 1059 $ hg fix -r .
1060 1060 $ hg log --template '{rev} {phase}\n'
1061 1061 1 secret
1062 1062 0 secret
1063 1063
1064 1064 $ cd ..
1065 1065
1066 1066 We should also preserve phase when fixing a draft commit while the user has
1067 1067 their default set to secret.
1068 1068
1069 1069 $ hg init respectphasesnewcommit
1070 1070 $ cd respectphasesnewcommit
1071 1071
1072 1072 $ printf "foo\n" > foo.whole
1073 1073 $ hg commit -Aqm "add foo"
1074 1074 $ hg --config phases.newcommit=secret fix -r .
1075 1075 $ hg log --template '{rev} {phase}\n'
1076 1076 1 draft
1077 1077 0 draft
1078 1078
1079 1079 $ cd ..
1080 1080
1081 1081 Debug output should show what fixer commands are being subprocessed, which is
1082 1082 useful for anyone trying to set up a new config.
1083 1083
1084 1084 $ hg init debugoutput
1085 1085 $ cd debugoutput
1086 1086
1087 1087 $ printf "foo\nbar\nbaz\n" > foo.changed
1088 1088 $ hg commit -Aqm "foo"
1089 1089 $ printf "Foo\nbar\nBaz\n" > foo.changed
1090 1090 $ hg --debug fix --working-dir
1091 1091 subprocess: * $TESTTMP/uppercase.py 1-1 3-3 (glob)
1092 1092
1093 1093 $ cd ..
1094 1094
1095 1095 Fixing an obsolete revision can cause divergence, so we abort unless the user
1096 1096 configures to allow it. This is not yet smart enough to know whether there is a
1097 1097 successor, but even then it is not likely intentional or idiomatic to fix an
1098 1098 obsolete revision.
1099 1099
1100 1100 $ hg init abortobsoleterev
1101 1101 $ cd abortobsoleterev
1102 1102
1103 1103 $ printf "foo\n" > foo.changed
1104 1104 $ hg commit -Aqm "foo"
1105 1105 $ hg debugobsolete `hg parents --template '{node}'`
1106 1106 1 new obsolescence markers
1107 1107 obsoleted 1 changesets
1108 1108 $ hg --hidden fix -r 0
1109 1109 abort: fixing obsolete revision could cause divergence
1110 1110 [255]
1111 1111
1112 1112 $ hg --hidden fix -r 0 --config experimental.evolution.allowdivergence=true
1113 1113 $ hg cat -r tip foo.changed
1114 1114 FOO
1115 1115
1116 1116 $ cd ..
1117 1117
1118 1118 Test all of the available substitution values for fixer commands.
1119 1119
1120 1120 $ hg init substitution
1121 1121 $ cd substitution
1122 1122
1123 1123 $ mkdir foo
1124 1124 $ printf "hello\ngoodbye\n" > foo/bar
1125 1125 $ hg add
1126 1126 adding foo/bar
1127 1127 $ hg --config "fix.fail:command=printf '%s\n' '{rootpath}' '{basename}'" \
1128 1128 > --config "fix.fail:linerange='{first}' '{last}'" \
1129 1129 > --config "fix.fail:pattern=foo/bar" \
1130 1130 > fix --working-dir
1131 1131 $ cat foo/bar
1132 1132 foo/bar
1133 1133 bar
1134 1134 1
1135 1135 2
1136 1136
1137 1137 $ cd ..
1138 1138
1139 1139 The --base flag should allow picking the revisions to diff against for changed
1140 1140 files and incremental line formatting.
1141 1141
1142 1142 $ hg init baseflag
1143 1143 $ cd baseflag
1144 1144
1145 1145 $ printf "one\ntwo\n" > foo.changed
1146 1146 $ printf "bar\n" > bar.changed
1147 1147 $ hg commit -Aqm "first"
1148 1148 $ printf "one\nTwo\n" > foo.changed
1149 1149 $ hg commit -m "second"
1150 1150 $ hg fix -w --base .
1151 1151 $ hg status
1152 1152 $ hg fix -w --base null
1153 1153 $ cat foo.changed
1154 1154 ONE
1155 1155 TWO
1156 1156 $ cat bar.changed
1157 1157 BAR
1158 1158
1159 1159 $ cd ..
1160 1160
1161 1161 If the user asks to fix the parent of another commit, they are asking to create
1162 1162 an orphan. We must respect experimental.evolution.allowunstable.
1163 1163
1164 1164 $ hg init allowunstable
1165 1165 $ cd allowunstable
1166 1166
1167 1167 $ printf "one\n" > foo.whole
1168 1168 $ hg commit -Aqm "first"
1169 1169 $ printf "two\n" > foo.whole
1170 1170 $ hg commit -m "second"
1171 1171 $ hg --config experimental.evolution.allowunstable=False fix -r '.^'
1172 1172 abort: can only fix a changeset together with all its descendants
1173 1173 [255]
1174 1174 $ hg fix -r '.^'
1175 1175 1 new orphan changesets
1176 1176 $ hg cat -r 2 foo.whole
1177 1177 ONE
1178 1178
1179 1179 $ cd ..
1180 1180
1181 1181 The --base flag affects the set of files being fixed. So while the --whole flag
1182 1182 makes the base irrelevant for changed line ranges, it still changes the
1183 1183 meaning and effect of the command. In this example, no files or lines are fixed
1184 1184 until we specify the base, but then we do fix unchanged lines.
1185 1185
1186 1186 $ hg init basewhole
1187 1187 $ cd basewhole
1188 1188 $ printf "foo1\n" > foo.changed
1189 1189 $ hg commit -Aqm "first"
1190 1190 $ printf "foo2\n" >> foo.changed
1191 1191 $ printf "bar\n" > bar.changed
1192 1192 $ hg commit -Aqm "second"
1193 1193
1194 1194 $ hg fix --working-dir --whole
1195 1195 $ cat *.changed
1196 1196 bar
1197 1197 foo1
1198 1198 foo2
1199 1199
1200 1200 $ hg fix --working-dir --base 0 --whole
1201 1201 $ cat *.changed
1202 1202 BAR
1203 1203 FOO1
1204 1204 FOO2
1205 1205
1206 1206 $ cd ..
1207 1207
1208 1208 The execution order of tools can be controlled. This example doesn't work if
1209 1209 you sort after truncating, but the config defines the correct order while the
1210 1210 definitions are out of order (which might imply the incorrect order given the
1211 1211 implementation of fix). The goal is to use multiple tools to select the lowest
1212 1212 5 numbers in the file.
1213 1213
1214 1214 $ hg init priorityexample
1215 1215 $ cd priorityexample
1216 1216
1217 1217 $ cat >> .hg/hgrc <<EOF
1218 1218 > [fix]
1219 1219 > head:command = head -n 5
1220 1220 > head:pattern = numbers.txt
1221 1221 > head:priority = 1
1222 1222 > sort:command = sort -n
1223 1223 > sort:pattern = numbers.txt
1224 1224 > sort:priority = 2
1225 1225 > EOF
1226 1226
1227 1227 $ printf "8\n2\n3\n6\n7\n4\n9\n5\n1\n0\n" > numbers.txt
1228 1228 $ hg add -q
1229 1229 $ hg fix -w
1230 1230 $ cat numbers.txt
1231 1231 0
1232 1232 1
1233 1233 2
1234 1234 3
1235 1235 4
1236 1236
1237 1237 And of course we should be able to break this by reversing the execution order.
1238 1238 Test negative priorities while we're at it.
1239 1239
1240 1240 $ cat >> .hg/hgrc <<EOF
1241 1241 > [fix]
1242 1242 > head:priority = -1
1243 1243 > sort:priority = -2
1244 1244 > EOF
1245 1245 $ printf "8\n2\n3\n6\n7\n4\n9\n5\n1\n0\n" > numbers.txt
1246 1246 $ hg fix -w
1247 1247 $ cat numbers.txt
1248 1248 2
1249 1249 3
1250 1250 6
1251 1251 7
1252 1252 8
1253 1253
1254 1254 $ cd ..
1255 1255
1256 1256 It's possible for repeated applications of a fixer tool to create cycles in the
1257 1257 generated content of a file. For example, two users with different versions of
1258 1258 a code formatter might fight over the formatting when they run hg fix. In the
1259 1259 absence of other changes, this means we could produce commits with the same
1260 1260 hash in subsequent runs of hg fix. This is a problem unless we support
1261 1261 obsolescence cycles well. We avoid this by adding an extra field to the
1262 1262 successor which forces it to have a new hash. That's why this test creates
1263 1263 three revisions instead of two.
1264 1264
1265 1265 $ hg init cyclictool
1266 1266 $ cd cyclictool
1267 1267
1268 1268 $ cat >> .hg/hgrc <<EOF
1269 1269 > [fix]
1270 1270 > swapletters:command = tr ab ba
1271 1271 > swapletters:pattern = foo
1272 1272 > EOF
1273 1273
1274 1274 $ echo ab > foo
1275 1275 $ hg commit -Aqm foo
1276 1276
1277 1277 $ hg fix -r 0
1278 1278 $ hg fix -r 1
1279 1279
1280 1280 $ hg cat -r 0 foo --hidden
1281 1281 ab
1282 1282 $ hg cat -r 1 foo --hidden
1283 1283 ba
1284 1284 $ hg cat -r 2 foo
1285 1285 ab
1286 1286
1287 1287 $ cd ..
1288 1288
1289 1289 We run fixer tools in the repo root so they can look for config files or other
1290 1290 important things in the working directory. This does NOT mean we are
1291 1291 reconstructing a working copy of every revision being fixed; we're just giving
1292 1292 the tool knowledge of the repo's location in case it can do something
1293 1293 reasonable with that.
1294 1294
1295 1295 $ hg init subprocesscwd
1296 1296 $ cd subprocesscwd
1297 1297
1298 1298 $ cat >> .hg/hgrc <<EOF
1299 1299 > [fix]
1300 > printcwd:command = pwd
1300 > printcwd:command = "$PYTHON" -c "import os; print(os.getcwd())"
1301 1301 > printcwd:pattern = path:foo/bar
1302 1302 > EOF
1303 1303
1304 1304 $ mkdir foo
1305 1305 $ printf "bar\n" > foo/bar
1306 1306 $ hg commit -Aqm blah
1307 1307
1308 1308 $ hg fix -w -r . foo/bar
1309 1309 $ hg cat -r tip foo/bar
1310 1310 $TESTTMP/subprocesscwd
1311 1311 $ cat foo/bar
1312 1312 $TESTTMP/subprocesscwd
1313 1313
1314 1314 $ cd foo
1315 1315
1316 1316 $ hg fix -w -r . bar
1317 1317 $ hg cat -r tip bar
1318 1318 $TESTTMP/subprocesscwd
1319 1319 $ cat bar
1320 1320 $TESTTMP/subprocesscwd
1321 1321
1322 1322 $ cd ../..
1323 1323
1324 1324 Tools configured without a pattern are ignored. It would be too dangerous to
1325 1325 run them on all files, because this might happen while testing a configuration
1326 1326 that also deletes all of the file content. There is no reasonable subset of the
1327 1327 files to use as a default. Users should be explicit about what files are
1328 1328 affected by a tool. This test also confirms that we don't crash when the
1329 1329 pattern config is missing, and that we only warn about it once.
1330 1330
1331 1331 $ hg init nopatternconfigured
1332 1332 $ cd nopatternconfigured
1333 1333
1334 1334 $ printf "foo" > foo
1335 1335 $ printf "bar" > bar
1336 1336 $ hg add -q
1337 1337 $ hg fix --debug --working-dir --config "fix.nopattern:command=echo fixed"
1338 1338 fixer tool has no pattern configuration: nopattern
1339 1339 $ cat foo bar
1340 1340 foobar (no-eol)
1341 1341
1342 1342 $ cd ..
1343 1343
1344 1344 Test that we can configure a fixer to affect all files regardless of the cwd.
1345 1345 The way we invoke matching must not prohibit this.
1346 1346
1347 1347 $ hg init affectallfiles
1348 1348 $ cd affectallfiles
1349 1349
1350 1350 $ mkdir foo bar
1351 1351 $ printf "foo" > foo/file
1352 1352 $ printf "bar" > bar/file
1353 1353 $ printf "baz" > baz_file
1354 1354 $ hg add -q
1355 1355
1356 1356 $ cd bar
1357 1357 $ hg fix --working-dir --config "fix.cooltool:command=echo fixed" \
1358 1358 > --config "fix.cooltool:pattern=rootglob:**"
1359 1359 $ cd ..
1360 1360
1361 1361 $ cat foo/file
1362 1362 fixed
1363 1363 $ cat bar/file
1364 1364 fixed
1365 1365 $ cat baz_file
1366 1366 fixed
1367 1367
1368 1368 $ cd ..
1369 1369
1370 1370 Tools should be able to run on unchanged files, even if they set :linerange.
1371 1371 This includes a corner case where deleted chunks of a file are not considered
1372 1372 changes.
1373 1373
1374 1374 $ hg init skipclean
1375 1375 $ cd skipclean
1376 1376
1377 1377 $ printf "a\nb\nc\n" > foo
1378 1378 $ printf "a\nb\nc\n" > bar
1379 1379 $ printf "a\nb\nc\n" > baz
1380 1380 $ hg commit -Aqm "base"
1381 1381
1382 1382 $ printf "a\nc\n" > foo
1383 1383 $ printf "a\nx\nc\n" > baz
1384 1384
1385 $ cat >> print.py <<EOF
1386 > import sys
1387 > for a in sys.argv[1:]:
1388 > print(a)
1389 > EOF
1390
1385 1391 $ hg fix --working-dir foo bar baz \
1386 > --config 'fix.changedlines:command=printf "Line ranges:\n"; ' \
1387 > --config 'fix.changedlines:linerange=printf "{first} through {last}\n"; ' \
1392 > --config "fix.changedlines:command=\"$PYTHON\" print.py \"Line ranges:\"" \
1393 > --config 'fix.changedlines:linerange="{first} through {last}"' \
1388 1394 > --config 'fix.changedlines:pattern=rootglob:**' \
1389 1395 > --config 'fix.changedlines:skipclean=false'
1390 1396
1391 1397 $ cat foo
1392 1398 Line ranges:
1393 1399 $ cat bar
1394 1400 Line ranges:
1395 1401 $ cat baz
1396 1402 Line ranges:
1397 1403 2 through 2
1398 1404
1399 1405 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now