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