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