##// END OF EJS Templates
tests: change the fixer commands to use the buffer attribute on stdio objects...
Matt Harbison -
r47862:ea563187 stable
parent child Browse files
Show More
@@ -1,553 +1,555 b''
1 A script that implements uppercasing all letters in a file.
1 A script that implements uppercasing all letters in a file.
2
2
3 $ UPPERCASEPY="$TESTTMP/uppercase.py"
3 $ UPPERCASEPY="$TESTTMP/uppercase.py"
4 $ cat > $UPPERCASEPY <<EOF
4 $ cat > $UPPERCASEPY <<EOF
5 > import sys
5 > import sys
6 > from mercurial.utils.procutil import setbinary
6 > from mercurial.utils.procutil import setbinary
7 > setbinary(sys.stdin)
7 > setbinary(sys.stdin)
8 > setbinary(sys.stdout)
8 > setbinary(sys.stdout)
9 > sys.stdout.write(sys.stdin.read().upper())
9 > stdin = getattr(sys.stdin, 'buffer', sys.stdin)
10 > stdout = getattr(sys.stdout, 'buffer', sys.stdout)
11 > stdout.write(stdin.read().upper())
10 > EOF
12 > EOF
11 $ TESTLINES="foo\nbar\nbaz\n"
13 $ TESTLINES="foo\nbar\nbaz\n"
12 $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY
14 $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY
13 FOO
15 FOO
14 BAR
16 BAR
15 BAZ
17 BAZ
16
18
17 Tests for the fix extension's behavior around non-trivial history topologies.
19 Tests for the fix extension's behavior around non-trivial history topologies.
18 Looks for correct incremental fixing and reproduction of parent/child
20 Looks for correct incremental fixing and reproduction of parent/child
19 relationships. We indicate fixed file content by uppercasing it.
21 relationships. We indicate fixed file content by uppercasing it.
20
22
21 $ cat >> $HGRCPATH <<EOF
23 $ cat >> $HGRCPATH <<EOF
22 > [extensions]
24 > [extensions]
23 > fix =
25 > fix =
24 > strip =
26 > strip =
25 > debugdrawdag=$TESTDIR/drawdag.py
27 > debugdrawdag=$TESTDIR/drawdag.py
26 > [fix]
28 > [fix]
27 > uppercase-whole-file:command="$PYTHON" $UPPERCASEPY
29 > uppercase-whole-file:command="$PYTHON" $UPPERCASEPY
28 > uppercase-whole-file:pattern=set:**
30 > uppercase-whole-file:pattern=set:**
29 > EOF
31 > EOF
30
32
31 This tests the only behavior that should really be affected by obsolescence, so
33 This tests the only behavior that should really be affected by obsolescence, so
32 we'll test it with evolution off and on. This only changes the revision
34 we'll test it with evolution off and on. This only changes the revision
33 numbers, if all is well.
35 numbers, if all is well.
34
36
35 #testcases obsstore-off obsstore-on
37 #testcases obsstore-off obsstore-on
36 #if obsstore-on
38 #if obsstore-on
37 $ cat >> $HGRCPATH <<EOF
39 $ cat >> $HGRCPATH <<EOF
38 > [experimental]
40 > [experimental]
39 > evolution.createmarkers=True
41 > evolution.createmarkers=True
40 > evolution.allowunstable=True
42 > evolution.allowunstable=True
41 > EOF
43 > EOF
42 #endif
44 #endif
43
45
44 Setting up the test topology. Scroll down to see the graph produced. We make it
46 Setting up the test topology. Scroll down to see the graph produced. We make it
45 clear which files were modified in each revision. It's enough to test at the
47 clear which files were modified in each revision. It's enough to test at the
46 file granularity, because that demonstrates which baserevs were diffed against.
48 file granularity, because that demonstrates which baserevs were diffed against.
47 The computation of changed lines is orthogonal and tested separately.
49 The computation of changed lines is orthogonal and tested separately.
48
50
49 $ hg init repo
51 $ hg init repo
50 $ cd repo
52 $ cd repo
51
53
52 $ printf "aaaa\n" > a
54 $ printf "aaaa\n" > a
53 $ hg commit -Am "change A"
55 $ hg commit -Am "change A"
54 adding a
56 adding a
55 $ printf "bbbb\n" > b
57 $ printf "bbbb\n" > b
56 $ hg commit -Am "change B"
58 $ hg commit -Am "change B"
57 adding b
59 adding b
58 $ printf "cccc\n" > c
60 $ printf "cccc\n" > c
59 $ hg commit -Am "change C"
61 $ hg commit -Am "change C"
60 adding c
62 adding c
61 $ hg checkout 0
63 $ hg checkout 0
62 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
64 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
63 $ printf "dddd\n" > d
65 $ printf "dddd\n" > d
64 $ hg commit -Am "change D"
66 $ hg commit -Am "change D"
65 adding d
67 adding d
66 created new head
68 created new head
67 $ hg merge -r 2
69 $ hg merge -r 2
68 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
70 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
69 (branch merge, don't forget to commit)
71 (branch merge, don't forget to commit)
70 $ printf "eeee\n" > e
72 $ printf "eeee\n" > e
71 $ hg commit -Am "change E"
73 $ hg commit -Am "change E"
72 adding e
74 adding e
73 $ hg checkout 0
75 $ hg checkout 0
74 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
76 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
75 $ printf "ffff\n" > f
77 $ printf "ffff\n" > f
76 $ hg commit -Am "change F"
78 $ hg commit -Am "change F"
77 adding f
79 adding f
78 created new head
80 created new head
79 $ hg checkout 0
81 $ hg checkout 0
80 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
82 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
81 $ printf "gggg\n" > g
83 $ printf "gggg\n" > g
82 $ hg commit -Am "change G"
84 $ hg commit -Am "change G"
83 adding g
85 adding g
84 created new head
86 created new head
85 $ hg merge -r 5
87 $ hg merge -r 5
86 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
88 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
87 (branch merge, don't forget to commit)
89 (branch merge, don't forget to commit)
88 $ printf "hhhh\n" > h
90 $ printf "hhhh\n" > h
89 $ hg commit -Am "change H (child of b53d63e816fb and 0e49f92ee6e9)"
91 $ hg commit -Am "change H (child of b53d63e816fb and 0e49f92ee6e9)"
90 adding h
92 adding h
91 $ hg merge -r 4
93 $ hg merge -r 4
92 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
94 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
93 (branch merge, don't forget to commit)
95 (branch merge, don't forget to commit)
94 $ printf "iiii\n" > i
96 $ printf "iiii\n" > i
95 $ hg commit -Am "change I"
97 $ hg commit -Am "change I"
96 adding i
98 adding i
97 $ hg checkout 2
99 $ hg checkout 2
98 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
100 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
99 $ printf "jjjj\n" > j
101 $ printf "jjjj\n" > j
100 $ hg commit -Am "change J (child of 7f371349286e)"
102 $ hg commit -Am "change J (child of 7f371349286e)"
101 adding j
103 adding j
102 created new head
104 created new head
103 $ hg checkout 7
105 $ hg checkout 7
104 3 files updated, 0 files merged, 3 files removed, 0 files unresolved
106 3 files updated, 0 files merged, 3 files removed, 0 files unresolved
105 $ printf "kkkk\n" > k
107 $ printf "kkkk\n" > k
106 $ hg add
108 $ hg add
107 adding k
109 adding k
108
110
109 $ hg log --graph --template '{rev}:{node|short} {desc}\n'
111 $ hg log --graph --template '{rev}:{node|short} {desc}\n'
110 o 9:884041ccc490 change J (child of 7f371349286e)
112 o 9:884041ccc490 change J (child of 7f371349286e)
111 |
113 |
112 | o 8:b7c772105fd2 change I
114 | o 8:b7c772105fd2 change I
113 | |\
115 | |\
114 | | @ 7:4e7b9312dad2 change H (child of b53d63e816fb and 0e49f92ee6e9)
116 | | @ 7:4e7b9312dad2 change H (child of b53d63e816fb and 0e49f92ee6e9)
115 | | |\
117 | | |\
116 | | | o 6:0e49f92ee6e9 change G
118 | | | o 6:0e49f92ee6e9 change G
117 | | | |
119 | | | |
118 | | o | 5:b53d63e816fb change F
120 | | o | 5:b53d63e816fb change F
119 | | |/
121 | | |/
120 | o | 4:ddad58af5e51 change E
122 | o | 4:ddad58af5e51 change E
121 |/| |
123 |/| |
122 | o | 3:c015ebfd2bfe change D
124 | o | 3:c015ebfd2bfe change D
123 | |/
125 | |/
124 o | 2:7f371349286e change C
126 o | 2:7f371349286e change C
125 | |
127 | |
126 o | 1:388fdd33fea0 change B
128 o | 1:388fdd33fea0 change B
127 |/
129 |/
128 o 0:a55a84d97a24 change A
130 o 0:a55a84d97a24 change A
129
131
130
132
131 Fix all but the root revision and its four children.
133 Fix all but the root revision and its four children.
132
134
133 $ hg fix -r '2|4|7|8|9' --working-dir
135 $ hg fix -r '2|4|7|8|9' --working-dir
134 saved backup bundle to * (glob) (obsstore-off !)
136 saved backup bundle to * (glob) (obsstore-off !)
135
137
136 The five revisions remain, but the other revisions were fixed and replaced. All
138 The five revisions remain, but the other revisions were fixed and replaced. All
137 parent pointers have been accurately set to reproduce the previous topology
139 parent pointers have been accurately set to reproduce the previous topology
138 (though it is rendered in a slightly different order now).
140 (though it is rendered in a slightly different order now).
139
141
140 #if obsstore-on
142 #if obsstore-on
141 $ hg log --graph --template '{rev}:{node|short} {desc}\n'
143 $ hg log --graph --template '{rev}:{node|short} {desc}\n'
142 o 14:d8d0e7974598 change J (child of 89de0da1d5da)
144 o 14:d8d0e7974598 change J (child of 89de0da1d5da)
143 |
145 |
144 | o 13:4fc0b354461e change I
146 | o 13:4fc0b354461e change I
145 | |\
147 | |\
146 | | @ 12:1c45f3923443 change H (child of b53d63e816fb and 0e49f92ee6e9)
148 | | @ 12:1c45f3923443 change H (child of b53d63e816fb and 0e49f92ee6e9)
147 | | |\
149 | | |\
148 | o | | 11:d75754455722 change E
150 | o | | 11:d75754455722 change E
149 |/| | |
151 |/| | |
150 o | | | 10:89de0da1d5da change C
152 o | | | 10:89de0da1d5da change C
151 | | | |
153 | | | |
152 | | | o 6:0e49f92ee6e9 change G
154 | | | o 6:0e49f92ee6e9 change G
153 | | | |
155 | | | |
154 | | o | 5:b53d63e816fb change F
156 | | o | 5:b53d63e816fb change F
155 | | |/
157 | | |/
156 | o / 3:c015ebfd2bfe change D
158 | o / 3:c015ebfd2bfe change D
157 | |/
159 | |/
158 o / 1:388fdd33fea0 change B
160 o / 1:388fdd33fea0 change B
159 |/
161 |/
160 o 0:a55a84d97a24 change A
162 o 0:a55a84d97a24 change A
161
163
162 $ C=10
164 $ C=10
163 $ E=11
165 $ E=11
164 $ H=12
166 $ H=12
165 $ I=13
167 $ I=13
166 $ J=14
168 $ J=14
167 #else
169 #else
168 $ hg log --graph --template '{rev}:{node|short} {desc}\n'
170 $ hg log --graph --template '{rev}:{node|short} {desc}\n'
169 o 9:d8d0e7974598 change J (child of 89de0da1d5da)
171 o 9:d8d0e7974598 change J (child of 89de0da1d5da)
170 |
172 |
171 | o 8:4fc0b354461e change I
173 | o 8:4fc0b354461e change I
172 | |\
174 | |\
173 | | @ 7:1c45f3923443 change H (child of b53d63e816fb and 0e49f92ee6e9)
175 | | @ 7:1c45f3923443 change H (child of b53d63e816fb and 0e49f92ee6e9)
174 | | |\
176 | | |\
175 | o | | 6:d75754455722 change E
177 | o | | 6:d75754455722 change E
176 |/| | |
178 |/| | |
177 o | | | 5:89de0da1d5da change C
179 o | | | 5:89de0da1d5da change C
178 | | | |
180 | | | |
179 | | | o 4:0e49f92ee6e9 change G
181 | | | o 4:0e49f92ee6e9 change G
180 | | | |
182 | | | |
181 | | o | 3:b53d63e816fb change F
183 | | o | 3:b53d63e816fb change F
182 | | |/
184 | | |/
183 | o / 2:c015ebfd2bfe change D
185 | o / 2:c015ebfd2bfe change D
184 | |/
186 | |/
185 o / 1:388fdd33fea0 change B
187 o / 1:388fdd33fea0 change B
186 |/
188 |/
187 o 0:a55a84d97a24 change A
189 o 0:a55a84d97a24 change A
188
190
189 $ C=5
191 $ C=5
190 $ E=6
192 $ E=6
191 $ H=7
193 $ H=7
192 $ I=8
194 $ I=8
193 $ J=9
195 $ J=9
194 #endif
196 #endif
195
197
196 Change C is a root of the set being fixed, so all we fix is what has changed
198 Change C is a root of the set being fixed, so all we fix is what has changed
197 since its parent. That parent, change B, is its baserev.
199 since its parent. That parent, change B, is its baserev.
198
200
199 $ hg cat -r $C 'set:**'
201 $ hg cat -r $C 'set:**'
200 aaaa
202 aaaa
201 bbbb
203 bbbb
202 CCCC
204 CCCC
203
205
204 Change E is a merge with only one parent being fixed. Its baserevs are the
206 Change E is a merge with only one parent being fixed. Its baserevs are the
205 unfixed parent plus the baserevs of the other parent. This evaluates to changes
207 unfixed parent plus the baserevs of the other parent. This evaluates to changes
206 B and D. We now have to decide what it means to incrementally fix a merge
208 B and D. We now have to decide what it means to incrementally fix a merge
207 commit. We choose to fix anything that has changed versus any baserev. Only the
209 commit. We choose to fix anything that has changed versus any baserev. Only the
208 undisturbed content of the common ancestor, change A, is unfixed.
210 undisturbed content of the common ancestor, change A, is unfixed.
209
211
210 $ hg cat -r $E 'set:**'
212 $ hg cat -r $E 'set:**'
211 aaaa
213 aaaa
212 BBBB
214 BBBB
213 CCCC
215 CCCC
214 DDDD
216 DDDD
215 EEEE
217 EEEE
216
218
217 Change H is a merge with neither parent being fixed. This is essentially
219 Change H is a merge with neither parent being fixed. This is essentially
218 equivalent to the previous case because there is still only one baserev for
220 equivalent to the previous case because there is still only one baserev for
219 each parent of the merge.
221 each parent of the merge.
220
222
221 $ hg cat -r $H 'set:**'
223 $ hg cat -r $H 'set:**'
222 aaaa
224 aaaa
223 FFFF
225 FFFF
224 GGGG
226 GGGG
225 HHHH
227 HHHH
226
228
227 Change I is a merge that has four baserevs; two from each parent. We handle
229 Change I is a merge that has four baserevs; two from each parent. We handle
228 multiple baserevs in the same way regardless of how many came from each parent.
230 multiple baserevs in the same way regardless of how many came from each parent.
229 So, fixing change H will fix any files that were not exactly the same in each
231 So, fixing change H will fix any files that were not exactly the same in each
230 baserev.
232 baserev.
231
233
232 $ hg cat -r $I 'set:**'
234 $ hg cat -r $I 'set:**'
233 aaaa
235 aaaa
234 BBBB
236 BBBB
235 CCCC
237 CCCC
236 DDDD
238 DDDD
237 EEEE
239 EEEE
238 FFFF
240 FFFF
239 GGGG
241 GGGG
240 HHHH
242 HHHH
241 IIII
243 IIII
242
244
243 Change J is a simple case with one baserev, but its baserev is not its parent,
245 Change J is a simple case with one baserev, but its baserev is not its parent,
244 change C. Its baserev is its grandparent, change B.
246 change C. Its baserev is its grandparent, change B.
245
247
246 $ hg cat -r $J 'set:**'
248 $ hg cat -r $J 'set:**'
247 aaaa
249 aaaa
248 bbbb
250 bbbb
249 CCCC
251 CCCC
250 JJJJ
252 JJJJ
251
253
252 The working copy was dirty, so it is treated much like a revision. The baserevs
254 The working copy was dirty, so it is treated much like a revision. The baserevs
253 for the working copy are inherited from its parent, change H, because it is
255 for the working copy are inherited from its parent, change H, because it is
254 also being fixed.
256 also being fixed.
255
257
256 $ cat *
258 $ cat *
257 aaaa
259 aaaa
258 FFFF
260 FFFF
259 GGGG
261 GGGG
260 HHHH
262 HHHH
261 KKKK
263 KKKK
262
264
263 Change A was never a baserev because none of its children were to be fixed.
265 Change A was never a baserev because none of its children were to be fixed.
264
266
265 $ cd ..
267 $ cd ..
266
268
267
269
268 Test the --source option. We only do this with obsstore on to avoid duplicating
270 Test the --source option. We only do this with obsstore on to avoid duplicating
269 test code. We rely on the other tests to prove that obsolescence is not an
271 test code. We rely on the other tests to prove that obsolescence is not an
270 important factor here.
272 important factor here.
271
273
272 #if obsstore-on
274 #if obsstore-on
273 $ hg init source-arg
275 $ hg init source-arg
274 $ cd source-arg
276 $ cd source-arg
275 $ printf "aaaa\n" > a
277 $ printf "aaaa\n" > a
276 $ hg commit -Am "change A"
278 $ hg commit -Am "change A"
277 adding a
279 adding a
278 $ printf "bbbb\n" > b
280 $ printf "bbbb\n" > b
279 $ hg commit -Am "change B"
281 $ hg commit -Am "change B"
280 adding b
282 adding b
281 $ printf "cccc\n" > c
283 $ printf "cccc\n" > c
282 $ hg commit -Am "change C"
284 $ hg commit -Am "change C"
283 adding c
285 adding c
284 $ hg checkout 0
286 $ hg checkout 0
285 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
287 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
286 $ printf "dddd\n" > d
288 $ printf "dddd\n" > d
287 $ hg commit -Am "change D"
289 $ hg commit -Am "change D"
288 adding d
290 adding d
289 created new head
291 created new head
290 $ hg log --graph --template '{rev} {desc}\n'
292 $ hg log --graph --template '{rev} {desc}\n'
291 @ 3 change D
293 @ 3 change D
292 |
294 |
293 | o 2 change C
295 | o 2 change C
294 | |
296 | |
295 | o 1 change B
297 | o 1 change B
296 |/
298 |/
297 o 0 change A
299 o 0 change A
298
300
299
301
300 Test passing 'wdir()' to --source
302 Test passing 'wdir()' to --source
301 $ printf "xxxx\n" > x
303 $ printf "xxxx\n" > x
302 $ hg add x
304 $ hg add x
303 $ hg fix -s 'wdir()'
305 $ hg fix -s 'wdir()'
304 $ cat *
306 $ cat *
305 aaaa
307 aaaa
306 dddd
308 dddd
307 XXXX
309 XXXX
308
310
309 Test passing '.' to --source
311 Test passing '.' to --source
310 $ printf "xxxx\n" > x
312 $ printf "xxxx\n" > x
311 $ hg fix -s .
313 $ hg fix -s .
312 $ hg log --graph --template '{rev} {desc}\n'
314 $ hg log --graph --template '{rev} {desc}\n'
313 @ 4 change D
315 @ 4 change D
314 |
316 |
315 | o 2 change C
317 | o 2 change C
316 | |
318 | |
317 | o 1 change B
319 | o 1 change B
318 |/
320 |/
319 o 0 change A
321 o 0 change A
320
322
321 $ cat *
323 $ cat *
322 aaaa
324 aaaa
323 DDDD
325 DDDD
324 XXXX
326 XXXX
325 $ hg strip -qf 4
327 $ hg strip -qf 4
326 $ hg co -q 3
328 $ hg co -q 3
327
329
328 Test passing other branch to --source
330 Test passing other branch to --source
329 $ printf "xxxx\n" > x
331 $ printf "xxxx\n" > x
330 $ hg add x
332 $ hg add x
331 $ hg fix -s 2
333 $ hg fix -s 2
332 $ hg log --graph --template '{rev} {desc}\n'
334 $ hg log --graph --template '{rev} {desc}\n'
333 o 4 change C
335 o 4 change C
334 |
336 |
335 | @ 3 change D
337 | @ 3 change D
336 | |
338 | |
337 o | 1 change B
339 o | 1 change B
338 |/
340 |/
339 o 0 change A
341 o 0 change A
340
342
341 $ hg cat -r 4 b c
343 $ hg cat -r 4 b c
342 bbbb
344 bbbb
343 CCCC
345 CCCC
344 $ cat *
346 $ cat *
345 aaaa
347 aaaa
346 dddd
348 dddd
347 xxxx
349 xxxx
348 $ hg strip -qf 4
350 $ hg strip -qf 4
349
351
350 Test passing multiple revisions to --source
352 Test passing multiple revisions to --source
351 $ hg fix -s '2 + .'
353 $ hg fix -s '2 + .'
352 $ hg log --graph --template '{rev} {desc}\n'
354 $ hg log --graph --template '{rev} {desc}\n'
353 @ 5 change D
355 @ 5 change D
354 |
356 |
355 | o 4 change C
357 | o 4 change C
356 | |
358 | |
357 | o 1 change B
359 | o 1 change B
358 |/
360 |/
359 o 0 change A
361 o 0 change A
360
362
361 $ hg cat -r 4 b c
363 $ hg cat -r 4 b c
362 bbbb
364 bbbb
363 CCCC
365 CCCC
364 $ cat *
366 $ cat *
365 aaaa
367 aaaa
366 DDDD
368 DDDD
367 XXXX
369 XXXX
368
370
369 $ cd ..
371 $ cd ..
370
372
371 $ hg init exclude-obsolete
373 $ hg init exclude-obsolete
372 $ cd exclude-obsolete
374 $ cd exclude-obsolete
373 $ hg debugdrawdag <<'EOS'
375 $ hg debugdrawdag <<'EOS'
374 > E C # prune: C
376 > E C # prune: C
375 > | |
377 > | |
376 > D B # prune: B, D
378 > D B # prune: B, D
377 > |/
379 > |/
378 > A
380 > A
379 > EOS
381 > EOS
380 1 new orphan changesets
382 1 new orphan changesets
381 $ hg log --graph --template '{rev} {desc}\n'
383 $ hg log --graph --template '{rev} {desc}\n'
382 * 4 E
384 * 4 E
383 |
385 |
384 | x 3 C
386 | x 3 C
385 | |
387 | |
386 x | 2 D
388 x | 2 D
387 | |
389 | |
388 | x 1 B
390 | x 1 B
389 |/
391 |/
390 o 0 A
392 o 0 A
391
393
392 $ hg fix -s A
394 $ hg fix -s A
393 $ hg fix -s B
395 $ hg fix -s B
394 abort: no changesets specified
396 abort: no changesets specified
395 (use --source or --working-dir)
397 (use --source or --working-dir)
396 [255]
398 [255]
397 $ hg fix -s D
399 $ hg fix -s D
398 $ hg fix -s E
400 $ hg fix -s E
399 $ cd ..
401 $ cd ..
400
402
401 #endif
403 #endif
402
404
403 The --all flag should fix anything that wouldn't cause a problem if you fixed
405 The --all flag should fix anything that wouldn't cause a problem if you fixed
404 it, including the working copy. Obsolete revisions are not fixed because that
406 it, including the working copy. Obsolete revisions are not fixed because that
405 could cause divergence. Public revisions would cause an abort because they are
407 could cause divergence. Public revisions would cause an abort because they are
406 immutable. We can fix orphans because their successors are still just orphans
408 immutable. We can fix orphans because their successors are still just orphans
407 of the original obsolete parent. When obsolesence is off, we're just fixing and
409 of the original obsolete parent. When obsolesence is off, we're just fixing and
408 replacing anything that isn't public.
410 replacing anything that isn't public.
409
411
410 $ hg init fixall
412 $ hg init fixall
411 $ cd fixall
413 $ cd fixall
412 $ hg fix --all --working-dir
414 $ hg fix --all --working-dir
413 abort: cannot specify both --working-dir and --all
415 abort: cannot specify both --working-dir and --all
414 [10]
416 [10]
415
417
416 #if obsstore-on
418 #if obsstore-on
417 $ printf "one\n" > foo.whole
419 $ printf "one\n" > foo.whole
418 $ hg commit -Aqm "first"
420 $ hg commit -Aqm "first"
419 $ hg phase --public
421 $ hg phase --public
420 $ hg tag --local root
422 $ hg tag --local root
421 $ printf "two\n" > foo.whole
423 $ printf "two\n" > foo.whole
422 $ hg commit -m "second"
424 $ hg commit -m "second"
423 $ printf "three\n" > foo.whole
425 $ printf "three\n" > foo.whole
424 $ hg commit -m "third" --secret
426 $ hg commit -m "third" --secret
425 $ hg tag --local secret
427 $ hg tag --local secret
426 $ hg checkout root
428 $ hg checkout root
427 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
429 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
428 $ printf "four\n" > foo.whole
430 $ printf "four\n" > foo.whole
429 $ hg commit -m "fourth"
431 $ hg commit -m "fourth"
430 created new head
432 created new head
431 $ printf "five\n" > foo.whole
433 $ printf "five\n" > foo.whole
432 $ hg commit -m "fifth"
434 $ hg commit -m "fifth"
433 $ hg tag --local replaced
435 $ hg tag --local replaced
434 $ printf "six\n" > foo.whole
436 $ printf "six\n" > foo.whole
435 $ hg commit -m "sixth"
437 $ hg commit -m "sixth"
436 $ hg checkout replaced
438 $ hg checkout replaced
437 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
439 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
438 $ printf "seven\n" > foo.whole
440 $ printf "seven\n" > foo.whole
439 $ hg commit --amend
441 $ hg commit --amend
440 1 new orphan changesets
442 1 new orphan changesets
441 $ hg checkout secret
443 $ hg checkout secret
442 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
444 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
443 $ printf "uncommitted\n" > foo.whole
445 $ printf "uncommitted\n" > foo.whole
444
446
445 $ hg log --graph --template '{rev} {desc} {phase}\n'
447 $ hg log --graph --template '{rev} {desc} {phase}\n'
446 o 6 fifth draft
448 o 6 fifth draft
447 |
449 |
448 | * 5 sixth draft
450 | * 5 sixth draft
449 | |
451 | |
450 | x 4 fifth draft
452 | x 4 fifth draft
451 |/
453 |/
452 o 3 fourth draft
454 o 3 fourth draft
453 |
455 |
454 | @ 2 third secret
456 | @ 2 third secret
455 | |
457 | |
456 | o 1 second draft
458 | o 1 second draft
457 |/
459 |/
458 o 0 first public
460 o 0 first public
459
461
460
462
461 $ hg fix --all
463 $ hg fix --all
462
464
463 $ hg log --graph --template '{rev} {desc}\n' -r 'sort(all(), topo)' --hidden
465 $ hg log --graph --template '{rev} {desc}\n' -r 'sort(all(), topo)' --hidden
464 o 11 fifth
466 o 11 fifth
465 |
467 |
466 o 9 fourth
468 o 9 fourth
467 |
469 |
468 | @ 8 third
470 | @ 8 third
469 | |
471 | |
470 | o 7 second
472 | o 7 second
471 |/
473 |/
472 | * 10 sixth
474 | * 10 sixth
473 | |
475 | |
474 | | x 5 sixth
476 | | x 5 sixth
475 | |/
477 | |/
476 | x 4 fifth
478 | x 4 fifth
477 | |
479 | |
478 | | x 6 fifth
480 | | x 6 fifth
479 | |/
481 | |/
480 | x 3 fourth
482 | x 3 fourth
481 |/
483 |/
482 | x 2 third
484 | x 2 third
483 | |
485 | |
484 | x 1 second
486 | x 1 second
485 |/
487 |/
486 o 0 first
488 o 0 first
487
489
488
490
489 $ hg cat -r 7 foo.whole
491 $ hg cat -r 7 foo.whole
490 TWO
492 TWO
491 $ hg cat -r 8 foo.whole
493 $ hg cat -r 8 foo.whole
492 THREE
494 THREE
493 $ hg cat -r 9 foo.whole
495 $ hg cat -r 9 foo.whole
494 FOUR
496 FOUR
495 $ hg cat -r 10 foo.whole
497 $ hg cat -r 10 foo.whole
496 SIX
498 SIX
497 $ hg cat -r 11 foo.whole
499 $ hg cat -r 11 foo.whole
498 SEVEN
500 SEVEN
499 $ cat foo.whole
501 $ cat foo.whole
500 UNCOMMITTED
502 UNCOMMITTED
501 #else
503 #else
502 $ printf "one\n" > foo.whole
504 $ printf "one\n" > foo.whole
503 $ hg commit -Aqm "first"
505 $ hg commit -Aqm "first"
504 $ hg phase --public
506 $ hg phase --public
505 $ hg tag --local root
507 $ hg tag --local root
506 $ printf "two\n" > foo.whole
508 $ printf "two\n" > foo.whole
507 $ hg commit -m "second"
509 $ hg commit -m "second"
508 $ printf "three\n" > foo.whole
510 $ printf "three\n" > foo.whole
509 $ hg commit -m "third" --secret
511 $ hg commit -m "third" --secret
510 $ hg tag --local secret
512 $ hg tag --local secret
511 $ hg checkout root
513 $ hg checkout root
512 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
514 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
513 $ printf "four\n" > foo.whole
515 $ printf "four\n" > foo.whole
514 $ hg commit -m "fourth"
516 $ hg commit -m "fourth"
515 created new head
517 created new head
516 $ printf "uncommitted\n" > foo.whole
518 $ printf "uncommitted\n" > foo.whole
517
519
518 $ hg log --graph --template '{rev} {desc} {phase}\n'
520 $ hg log --graph --template '{rev} {desc} {phase}\n'
519 @ 3 fourth draft
521 @ 3 fourth draft
520 |
522 |
521 | o 2 third secret
523 | o 2 third secret
522 | |
524 | |
523 | o 1 second draft
525 | o 1 second draft
524 |/
526 |/
525 o 0 first public
527 o 0 first public
526
528
527
529
528 $ hg fix --all
530 $ hg fix --all
529 saved backup bundle to * (glob)
531 saved backup bundle to * (glob)
530
532
531 $ hg log --graph --template '{rev} {desc} {phase}\n'
533 $ hg log --graph --template '{rev} {desc} {phase}\n'
532 @ 3 fourth draft
534 @ 3 fourth draft
533 |
535 |
534 | o 2 third secret
536 | o 2 third secret
535 | |
537 | |
536 | o 1 second draft
538 | o 1 second draft
537 |/
539 |/
538 o 0 first public
540 o 0 first public
539
541
540 $ hg cat -r 0 foo.whole
542 $ hg cat -r 0 foo.whole
541 one
543 one
542 $ hg cat -r 1 foo.whole
544 $ hg cat -r 1 foo.whole
543 TWO
545 TWO
544 $ hg cat -r 2 foo.whole
546 $ hg cat -r 2 foo.whole
545 THREE
547 THREE
546 $ hg cat -r 3 foo.whole
548 $ hg cat -r 3 foo.whole
547 FOUR
549 FOUR
548 $ cat foo.whole
550 $ cat foo.whole
549 UNCOMMITTED
551 UNCOMMITTED
550 #endif
552 #endif
551
553
552 $ cd ..
554 $ cd ..
553
555
@@ -1,1692 +1,1694 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 > stdin = getattr(sys.stdin, 'buffer', sys.stdin)
11 > stdout = getattr(sys.stdout, 'buffer', sys.stdout)
10 > lines = set()
12 > lines = set()
11 > for arg in sys.argv[1:]:
13 > for arg in sys.argv[1:]:
12 > if arg == 'all':
14 > if arg == 'all':
13 > sys.stdout.write(sys.stdin.read().upper())
15 > stdout.write(stdin.read().upper())
14 > sys.exit(0)
16 > sys.exit(0)
15 > else:
17 > else:
16 > first, last = arg.split('-')
18 > first, last = arg.split('-')
17 > lines.update(range(int(first), int(last) + 1))
19 > lines.update(range(int(first), int(last) + 1))
18 > for i, line in enumerate(sys.stdin.readlines()):
20 > for i, line in enumerate(stdin.readlines()):
19 > if i + 1 in lines:
21 > if i + 1 in lines:
20 > sys.stdout.write(line.upper())
22 > stdout.write(line.upper())
21 > else:
23 > else:
22 > sys.stdout.write(line)
24 > stdout.write(line)
23 > EOF
25 > EOF
24 $ TESTLINES="foo\nbar\nbaz\nqux\n"
26 $ TESTLINES="foo\nbar\nbaz\nqux\n"
25 $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY
27 $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY
26 foo
28 foo
27 bar
29 bar
28 baz
30 baz
29 qux
31 qux
30 $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY all
32 $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY all
31 FOO
33 FOO
32 BAR
34 BAR
33 BAZ
35 BAZ
34 QUX
36 QUX
35 $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY 1-1
37 $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY 1-1
36 FOO
38 FOO
37 bar
39 bar
38 baz
40 baz
39 qux
41 qux
40 $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY 1-2
42 $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY 1-2
41 FOO
43 FOO
42 BAR
44 BAR
43 baz
45 baz
44 qux
46 qux
45 $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY 2-3
47 $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY 2-3
46 foo
48 foo
47 BAR
49 BAR
48 BAZ
50 BAZ
49 qux
51 qux
50 $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY 2-2 4-4
52 $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY 2-2 4-4
51 foo
53 foo
52 BAR
54 BAR
53 baz
55 baz
54 QUX
56 QUX
55
57
56 Set up the config with two simple fixers: one that fixes specific line ranges,
58 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
59 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
60 letters to uppercase. They use different file extensions, so each test case can
59 choose which behavior to use by naming files.
61 choose which behavior to use by naming files.
60
62
61 $ cat >> $HGRCPATH <<EOF
63 $ cat >> $HGRCPATH <<EOF
62 > [extensions]
64 > [extensions]
63 > fix =
65 > fix =
64 > [experimental]
66 > [experimental]
65 > evolution.createmarkers=True
67 > evolution.createmarkers=True
66 > evolution.allowunstable=True
68 > evolution.allowunstable=True
67 > [fix]
69 > [fix]
68 > uppercase-whole-file:command="$PYTHON" $UPPERCASEPY all
70 > uppercase-whole-file:command="$PYTHON" $UPPERCASEPY all
69 > uppercase-whole-file:pattern=set:**.whole
71 > uppercase-whole-file:pattern=set:**.whole
70 > uppercase-changed-lines:command="$PYTHON" $UPPERCASEPY
72 > uppercase-changed-lines:command="$PYTHON" $UPPERCASEPY
71 > uppercase-changed-lines:linerange={first}-{last}
73 > uppercase-changed-lines:linerange={first}-{last}
72 > uppercase-changed-lines:pattern=set:**.changed
74 > uppercase-changed-lines:pattern=set:**.changed
73 > EOF
75 > EOF
74
76
75 Help text for fix.
77 Help text for fix.
76
78
77 $ hg help fix
79 $ hg help fix
78 hg fix [OPTION]... [FILE]...
80 hg fix [OPTION]... [FILE]...
79
81
80 rewrite file content in changesets or working directory
82 rewrite file content in changesets or working directory
81
83
82 Runs any configured tools to fix the content of files. Only affects files
84 Runs any configured tools to fix the content of files. Only affects files
83 with changes, unless file arguments are provided. Only affects changed
85 with changes, unless file arguments are provided. Only affects changed
84 lines of files, unless the --whole flag is used. Some tools may always
86 lines of files, unless the --whole flag is used. Some tools may always
85 affect the whole file regardless of --whole.
87 affect the whole file regardless of --whole.
86
88
87 If --working-dir is used, files with uncommitted changes in the working
89 If --working-dir is used, files with uncommitted changes in the working
88 copy will be fixed. Note that no backup are made.
90 copy will be fixed. Note that no backup are made.
89
91
90 If revisions are specified with --source, those revisions and their
92 If revisions are specified with --source, those revisions and their
91 descendants will be checked, and they may be replaced with new revisions
93 descendants will be checked, and they may be replaced with new revisions
92 that have fixed file content. By automatically including the descendants,
94 that have fixed file content. By automatically including the descendants,
93 no merging, rebasing, or evolution will be required. If an ancestor of the
95 no merging, rebasing, or evolution will be required. If an ancestor of the
94 working copy is included, then the working copy itself will also be fixed,
96 working copy is included, then the working copy itself will also be fixed,
95 and the working copy will be updated to the fixed parent.
97 and the working copy will be updated to the fixed parent.
96
98
97 When determining what lines of each file to fix at each revision, the
99 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
100 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
101 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
102 override this default behavior, though it is not usually desirable to do
101 so.
103 so.
102
104
103 (use 'hg help -e fix' to show help for the fix extension)
105 (use 'hg help -e fix' to show help for the fix extension)
104
106
105 options ([+] can be repeated):
107 options ([+] can be repeated):
106
108
107 --all fix all non-public non-obsolete revisions
109 --all fix all non-public non-obsolete revisions
108 --base REV [+] revisions to diff against (overrides automatic selection,
110 --base REV [+] revisions to diff against (overrides automatic selection,
109 and applies to every revision being fixed)
111 and applies to every revision being fixed)
110 -s --source REV [+] fix the specified revisions and their descendants
112 -s --source REV [+] fix the specified revisions and their descendants
111 -w --working-dir fix the working directory
113 -w --working-dir fix the working directory
112 --whole always fix every line of a file
114 --whole always fix every line of a file
113
115
114 (some details hidden, use --verbose to show complete help)
116 (some details hidden, use --verbose to show complete help)
115
117
116 $ hg help -e fix
118 $ hg help -e fix
117 fix extension - rewrite file content in changesets or working copy
119 fix extension - rewrite file content in changesets or working copy
118 (EXPERIMENTAL)
120 (EXPERIMENTAL)
119
121
120 Provides a command that runs configured tools on the contents of modified
122 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.
123 files, writing back any fixes to the working copy or replacing changesets.
122
124
123 Here is an example configuration that causes 'hg fix' to apply automatic
125 Here is an example configuration that causes 'hg fix' to apply automatic
124 formatting fixes to modified lines in C++ code:
126 formatting fixes to modified lines in C++ code:
125
127
126 [fix]
128 [fix]
127 clang-format:command=clang-format --assume-filename={rootpath}
129 clang-format:command=clang-format --assume-filename={rootpath}
128 clang-format:linerange=--lines={first}:{last}
130 clang-format:linerange=--lines={first}:{last}
129 clang-format:pattern=set:**.cpp or **.hpp
131 clang-format:pattern=set:**.cpp or **.hpp
130
132
131 The :command suboption forms the first part of the shell command that will be
133 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
134 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
135 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
136 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-
137 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
138 zero exit status but no standard error output. Some values may be substituted
137 into the command:
139 into the command:
138
140
139 {rootpath} The path of the file being fixed, relative to the repo root
141 {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
142 {basename} The name of the file being fixed, without the directory path
141
143
142 If the :linerange suboption is set, the tool will only be run if there are
144 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
145 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
146 command once for every range of changed lines in the file. Some values may be
145 substituted into the command:
147 substituted into the command:
146
148
147 {first} The 1-based line number of the first line in the modified range
149 {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
150 {last} The 1-based line number of the last line in the modified range
149
151
150 Deleted sections of a file will be ignored by :linerange, because there is no
152 Deleted sections of a file will be ignored by :linerange, because there is no
151 corresponding line range in the version being fixed.
153 corresponding line range in the version being fixed.
152
154
153 By default, tools that set :linerange will only be executed if there is at
155 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
156 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.
157 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
158 If such a tool needs to operate on unchanged files, it should set the
157 :skipclean suboption to false.
159 :skipclean suboption to false.
158
160
159 The :pattern suboption determines which files will be passed through each
161 The :pattern suboption determines which files will be passed through each
160 configured tool. See 'hg help patterns' for possible values. However, all
162 configured tool. See 'hg help patterns' for possible values. However, all
161 patterns are relative to the repo root, even if that text says they are
163 patterns are relative to the repo root, even if that text says they are
162 relative to the current working directory. If there are file arguments to 'hg
164 relative to the current working directory. If there are file arguments to 'hg
163 fix', the intersection of these patterns is used.
165 fix', the intersection of these patterns is used.
164
166
165 There is also a configurable limit for the maximum size of file that will be
167 There is also a configurable limit for the maximum size of file that will be
166 processed by 'hg fix':
168 processed by 'hg fix':
167
169
168 [fix]
170 [fix]
169 maxfilesize = 2MB
171 maxfilesize = 2MB
170
172
171 Normally, execution of configured tools will continue after a failure
173 Normally, execution of configured tools will continue after a failure
172 (indicated by a non-zero exit status). It can also be configured to abort
174 (indicated by a non-zero exit status). It can also be configured to abort
173 after the first such failure, so that no files will be affected if any tool
175 after the first such failure, so that no files will be affected if any tool
174 fails. This abort will also cause 'hg fix' to exit with a non-zero status:
176 fails. This abort will also cause 'hg fix' to exit with a non-zero status:
175
177
176 [fix]
178 [fix]
177 failure = abort
179 failure = abort
178
180
179 When multiple tools are configured to affect a file, they execute in an order
181 When multiple tools are configured to affect a file, they execute in an order
180 defined by the :priority suboption. The priority suboption has a default value
182 defined by the :priority suboption. The priority suboption has a default value
181 of zero for each tool. Tools are executed in order of descending priority. The
183 of zero for each tool. Tools are executed in order of descending priority. The
182 execution order of tools with equal priority is unspecified. For example, you
184 execution order of tools with equal priority is unspecified. For example, you
183 could use the 'sort' and 'head' utilities to keep only the 10 smallest numbers
185 could use the 'sort' and 'head' utilities to keep only the 10 smallest numbers
184 in a text file by ensuring that 'sort' runs before 'head':
186 in a text file by ensuring that 'sort' runs before 'head':
185
187
186 [fix]
188 [fix]
187 sort:command = sort -n
189 sort:command = sort -n
188 head:command = head -n 10
190 head:command = head -n 10
189 sort:pattern = numbers.txt
191 sort:pattern = numbers.txt
190 head:pattern = numbers.txt
192 head:pattern = numbers.txt
191 sort:priority = 2
193 sort:priority = 2
192 head:priority = 1
194 head:priority = 1
193
195
194 To account for changes made by each tool, the line numbers used for
196 To account for changes made by each tool, the line numbers used for
195 incremental formatting are recomputed before executing the next tool. So, each
197 incremental formatting are recomputed before executing the next tool. So, each
196 tool may see different values for the arguments added by the :linerange
198 tool may see different values for the arguments added by the :linerange
197 suboption.
199 suboption.
198
200
199 Each fixer tool is allowed to return some metadata in addition to the fixed
201 Each fixer tool is allowed to return some metadata in addition to the fixed
200 file content. The metadata must be placed before the file content on stdout,
202 file content. The metadata must be placed before the file content on stdout,
201 separated from the file content by a zero byte. The metadata is parsed as a
203 separated from the file content by a zero byte. The metadata is parsed as a
202 JSON value (so, it should be UTF-8 encoded and contain no zero bytes). A fixer
204 JSON value (so, it should be UTF-8 encoded and contain no zero bytes). A fixer
203 tool is expected to produce this metadata encoding if and only if the
205 tool is expected to produce this metadata encoding if and only if the
204 :metadata suboption is true:
206 :metadata suboption is true:
205
207
206 [fix]
208 [fix]
207 tool:command = tool --prepend-json-metadata
209 tool:command = tool --prepend-json-metadata
208 tool:metadata = true
210 tool:metadata = true
209
211
210 The metadata values are passed to hooks, which can be used to print summaries
212 The metadata values are passed to hooks, which can be used to print summaries
211 or perform other post-fixing work. The supported hooks are:
213 or perform other post-fixing work. The supported hooks are:
212
214
213 "postfixfile"
215 "postfixfile"
214 Run once for each file in each revision where any fixer tools made changes
216 Run once for each file in each revision where any fixer tools made changes
215 to the file content. Provides "$HG_REV" and "$HG_PATH" to identify the file,
217 to the file content. Provides "$HG_REV" and "$HG_PATH" to identify the file,
216 and "$HG_METADATA" with a map of fixer names to metadata values from fixer
218 and "$HG_METADATA" with a map of fixer names to metadata values from fixer
217 tools that affected the file. Fixer tools that didn't affect the file have a
219 tools that affected the file. Fixer tools that didn't affect the file have a
218 value of None. Only fixer tools that executed are present in the metadata.
220 value of None. Only fixer tools that executed are present in the metadata.
219
221
220 "postfix"
222 "postfix"
221 Run once after all files and revisions have been handled. Provides
223 Run once after all files and revisions have been handled. Provides
222 "$HG_REPLACEMENTS" with information about what revisions were created and
224 "$HG_REPLACEMENTS" with information about what revisions were created and
223 made obsolete. Provides a boolean "$HG_WDIRWRITTEN" to indicate whether any
225 made obsolete. Provides a boolean "$HG_WDIRWRITTEN" to indicate whether any
224 files in the working copy were updated. Provides a list "$HG_METADATA"
226 files in the working copy were updated. Provides a list "$HG_METADATA"
225 mapping fixer tool names to lists of metadata values returned from
227 mapping fixer tool names to lists of metadata values returned from
226 executions that modified a file. This aggregates the same metadata
228 executions that modified a file. This aggregates the same metadata
227 previously passed to the "postfixfile" hook.
229 previously passed to the "postfixfile" hook.
228
230
229 Fixer tools are run in the repository's root directory. This allows them to
231 Fixer tools are run in the repository's root directory. This allows them to
230 read configuration files from the working copy, or even write to the working
232 read configuration files from the working copy, or even write to the working
231 copy. The working copy is not updated to match the revision being fixed. In
233 copy. The working copy is not updated to match the revision being fixed. In
232 fact, several revisions may be fixed in parallel. Writes to the working copy
234 fact, several revisions may be fixed in parallel. Writes to the working copy
233 are not amended into the revision being fixed; fixer tools should always write
235 are not amended into the revision being fixed; fixer tools should always write
234 fixed file content back to stdout as documented above.
236 fixed file content back to stdout as documented above.
235
237
236 list of commands:
238 list of commands:
237
239
238 fix rewrite file content in changesets or working directory
240 fix rewrite file content in changesets or working directory
239
241
240 (use 'hg help -v -e fix' to show built-in aliases and global options)
242 (use 'hg help -v -e fix' to show built-in aliases and global options)
241
243
242 There is no default behavior in the absence of --rev and --working-dir.
244 There is no default behavior in the absence of --rev and --working-dir.
243
245
244 $ hg init badusage
246 $ hg init badusage
245 $ cd badusage
247 $ cd badusage
246
248
247 $ hg fix
249 $ hg fix
248 abort: no changesets specified
250 abort: no changesets specified
249 (use --source or --working-dir)
251 (use --source or --working-dir)
250 [255]
252 [255]
251 $ hg fix --whole
253 $ hg fix --whole
252 abort: no changesets specified
254 abort: no changesets specified
253 (use --source or --working-dir)
255 (use --source or --working-dir)
254 [255]
256 [255]
255 $ hg fix --base 0
257 $ hg fix --base 0
256 abort: no changesets specified
258 abort: no changesets specified
257 (use --source or --working-dir)
259 (use --source or --working-dir)
258 [255]
260 [255]
259
261
260 Fixing a public revision isn't allowed. It should abort early enough that
262 Fixing a public revision isn't allowed. It should abort early enough that
261 nothing happens, even to the working directory.
263 nothing happens, even to the working directory.
262
264
263 $ printf "hello\n" > hello.whole
265 $ printf "hello\n" > hello.whole
264 $ hg commit -Aqm "hello"
266 $ hg commit -Aqm "hello"
265 $ hg phase -r 0 --public
267 $ hg phase -r 0 --public
266 $ hg fix -r 0
268 $ hg fix -r 0
267 abort: cannot fix public changesets
269 abort: cannot fix public changesets
268 (see 'hg help phases' for details)
270 (see 'hg help phases' for details)
269 [10]
271 [10]
270 $ hg fix -r 0 --working-dir
272 $ hg fix -r 0 --working-dir
271 abort: cannot fix public changesets
273 abort: cannot fix public changesets
272 (see 'hg help phases' for details)
274 (see 'hg help phases' for details)
273 [10]
275 [10]
274 $ hg cat -r tip hello.whole
276 $ hg cat -r tip hello.whole
275 hello
277 hello
276 $ cat hello.whole
278 $ cat hello.whole
277 hello
279 hello
278
280
279 $ cd ..
281 $ cd ..
280
282
281 Fixing a clean working directory should do nothing. Even the --whole flag
283 Fixing a clean working directory should do nothing. Even the --whole flag
282 shouldn't cause any clean files to be fixed. Specifying a clean file explicitly
284 shouldn't cause any clean files to be fixed. Specifying a clean file explicitly
283 should only fix it if the fixer always fixes the whole file. The combination of
285 should only fix it if the fixer always fixes the whole file. The combination of
284 an explicit filename and --whole should format the entire file regardless.
286 an explicit filename and --whole should format the entire file regardless.
285
287
286 $ hg init fixcleanwdir
288 $ hg init fixcleanwdir
287 $ cd fixcleanwdir
289 $ cd fixcleanwdir
288
290
289 $ printf "hello\n" > hello.changed
291 $ printf "hello\n" > hello.changed
290 $ printf "world\n" > hello.whole
292 $ printf "world\n" > hello.whole
291 $ hg commit -Aqm "foo"
293 $ hg commit -Aqm "foo"
292 $ hg fix --working-dir
294 $ hg fix --working-dir
293 $ hg diff
295 $ hg diff
294 $ hg fix --working-dir --whole
296 $ hg fix --working-dir --whole
295 $ hg diff
297 $ hg diff
296 $ hg fix --working-dir *
298 $ hg fix --working-dir *
297 $ cat *
299 $ cat *
298 hello
300 hello
299 WORLD
301 WORLD
300 $ hg revert --all --no-backup
302 $ hg revert --all --no-backup
301 reverting hello.whole
303 reverting hello.whole
302 $ hg fix --working-dir * --whole
304 $ hg fix --working-dir * --whole
303 $ cat *
305 $ cat *
304 HELLO
306 HELLO
305 WORLD
307 WORLD
306
308
307 The same ideas apply to fixing a revision, so we create a revision that doesn't
309 The same ideas apply to fixing a revision, so we create a revision that doesn't
308 modify either of the files in question and try fixing it. This also tests that
310 modify either of the files in question and try fixing it. This also tests that
309 we ignore a file that doesn't match any configured fixer.
311 we ignore a file that doesn't match any configured fixer.
310
312
311 $ hg revert --all --no-backup
313 $ hg revert --all --no-backup
312 reverting hello.changed
314 reverting hello.changed
313 reverting hello.whole
315 reverting hello.whole
314 $ printf "unimportant\n" > some.file
316 $ printf "unimportant\n" > some.file
315 $ hg commit -Aqm "some other file"
317 $ hg commit -Aqm "some other file"
316
318
317 $ hg fix -r .
319 $ hg fix -r .
318 $ hg cat -r tip *
320 $ hg cat -r tip *
319 hello
321 hello
320 world
322 world
321 unimportant
323 unimportant
322 $ hg fix -r . --whole
324 $ hg fix -r . --whole
323 $ hg cat -r tip *
325 $ hg cat -r tip *
324 hello
326 hello
325 world
327 world
326 unimportant
328 unimportant
327 $ hg fix -r . *
329 $ hg fix -r . *
328 $ hg cat -r tip *
330 $ hg cat -r tip *
329 hello
331 hello
330 WORLD
332 WORLD
331 unimportant
333 unimportant
332 $ hg fix -r . * --whole --config experimental.evolution.allowdivergence=true
334 $ hg fix -r . * --whole --config experimental.evolution.allowdivergence=true
333 2 new content-divergent changesets
335 2 new content-divergent changesets
334 $ hg cat -r tip *
336 $ hg cat -r tip *
335 HELLO
337 HELLO
336 WORLD
338 WORLD
337 unimportant
339 unimportant
338
340
339 $ cd ..
341 $ cd ..
340
342
341 Fixing the working directory should still work if there are no revisions.
343 Fixing the working directory should still work if there are no revisions.
342
344
343 $ hg init norevisions
345 $ hg init norevisions
344 $ cd norevisions
346 $ cd norevisions
345
347
346 $ printf "something\n" > something.whole
348 $ printf "something\n" > something.whole
347 $ hg add
349 $ hg add
348 adding something.whole
350 adding something.whole
349 $ hg fix --working-dir
351 $ hg fix --working-dir
350 $ cat something.whole
352 $ cat something.whole
351 SOMETHING
353 SOMETHING
352
354
353 $ cd ..
355 $ cd ..
354
356
355 Test the effect of fixing the working directory for each possible status, with
357 Test the effect of fixing the working directory for each possible status, with
356 and without providing explicit file arguments.
358 and without providing explicit file arguments.
357
359
358 $ hg init implicitlyfixstatus
360 $ hg init implicitlyfixstatus
359 $ cd implicitlyfixstatus
361 $ cd implicitlyfixstatus
360
362
361 $ printf "modified\n" > modified.whole
363 $ printf "modified\n" > modified.whole
362 $ printf "removed\n" > removed.whole
364 $ printf "removed\n" > removed.whole
363 $ printf "deleted\n" > deleted.whole
365 $ printf "deleted\n" > deleted.whole
364 $ printf "clean\n" > clean.whole
366 $ printf "clean\n" > clean.whole
365 $ printf "ignored.whole" > .hgignore
367 $ printf "ignored.whole" > .hgignore
366 $ hg commit -Aqm "stuff"
368 $ hg commit -Aqm "stuff"
367
369
368 $ printf "modified!!!\n" > modified.whole
370 $ printf "modified!!!\n" > modified.whole
369 $ printf "unknown\n" > unknown.whole
371 $ printf "unknown\n" > unknown.whole
370 $ printf "ignored\n" > ignored.whole
372 $ printf "ignored\n" > ignored.whole
371 $ printf "added\n" > added.whole
373 $ printf "added\n" > added.whole
372 $ hg add added.whole
374 $ hg add added.whole
373 $ hg remove removed.whole
375 $ hg remove removed.whole
374 $ rm deleted.whole
376 $ rm deleted.whole
375
377
376 $ hg status --all
378 $ hg status --all
377 M modified.whole
379 M modified.whole
378 A added.whole
380 A added.whole
379 R removed.whole
381 R removed.whole
380 ! deleted.whole
382 ! deleted.whole
381 ? unknown.whole
383 ? unknown.whole
382 I ignored.whole
384 I ignored.whole
383 C .hgignore
385 C .hgignore
384 C clean.whole
386 C clean.whole
385
387
386 $ hg fix --working-dir
388 $ hg fix --working-dir
387
389
388 $ hg status --all
390 $ hg status --all
389 M modified.whole
391 M modified.whole
390 A added.whole
392 A added.whole
391 R removed.whole
393 R removed.whole
392 ! deleted.whole
394 ! deleted.whole
393 ? unknown.whole
395 ? unknown.whole
394 I ignored.whole
396 I ignored.whole
395 C .hgignore
397 C .hgignore
396 C clean.whole
398 C clean.whole
397
399
398 $ cat *.whole
400 $ cat *.whole
399 ADDED
401 ADDED
400 clean
402 clean
401 ignored
403 ignored
402 MODIFIED!!!
404 MODIFIED!!!
403 unknown
405 unknown
404
406
405 $ printf "modified!!!\n" > modified.whole
407 $ printf "modified!!!\n" > modified.whole
406 $ printf "added\n" > added.whole
408 $ printf "added\n" > added.whole
407
409
408 Listing the files explicitly causes untracked files to also be fixed, but
410 Listing the files explicitly causes untracked files to also be fixed, but
409 ignored files are still unaffected.
411 ignored files are still unaffected.
410
412
411 $ hg fix --working-dir *.whole
413 $ hg fix --working-dir *.whole
412
414
413 $ hg status --all
415 $ hg status --all
414 M clean.whole
416 M clean.whole
415 M modified.whole
417 M modified.whole
416 A added.whole
418 A added.whole
417 R removed.whole
419 R removed.whole
418 ! deleted.whole
420 ! deleted.whole
419 ? unknown.whole
421 ? unknown.whole
420 I ignored.whole
422 I ignored.whole
421 C .hgignore
423 C .hgignore
422
424
423 $ cat *.whole
425 $ cat *.whole
424 ADDED
426 ADDED
425 CLEAN
427 CLEAN
426 ignored
428 ignored
427 MODIFIED!!!
429 MODIFIED!!!
428 UNKNOWN
430 UNKNOWN
429
431
430 $ cd ..
432 $ cd ..
431
433
432 Test that incremental fixing works on files with additions, deletions, and
434 Test that incremental fixing works on files with additions, deletions, and
433 changes in multiple line ranges. Note that deletions do not generally cause
435 changes in multiple line ranges. Note that deletions do not generally cause
434 neighboring lines to be fixed, so we don't return a line range for purely
436 neighboring lines to be fixed, so we don't return a line range for purely
435 deleted sections. In the future we should support a :deletion config that
437 deleted sections. In the future we should support a :deletion config that
436 allows fixers to know where deletions are located.
438 allows fixers to know where deletions are located.
437
439
438 $ hg init incrementalfixedlines
440 $ hg init incrementalfixedlines
439 $ cd incrementalfixedlines
441 $ cd incrementalfixedlines
440
442
441 $ printf "a\nb\nc\nd\ne\nf\ng\n" > foo.txt
443 $ printf "a\nb\nc\nd\ne\nf\ng\n" > foo.txt
442 $ hg commit -Aqm "foo"
444 $ hg commit -Aqm "foo"
443 $ printf "zz\na\nc\ndd\nee\nff\nf\ngg\n" > foo.txt
445 $ printf "zz\na\nc\ndd\nee\nff\nf\ngg\n" > foo.txt
444
446
445 $ hg --config "fix.fail:command=echo" \
447 $ hg --config "fix.fail:command=echo" \
446 > --config "fix.fail:linerange={first}:{last}" \
448 > --config "fix.fail:linerange={first}:{last}" \
447 > --config "fix.fail:pattern=foo.txt" \
449 > --config "fix.fail:pattern=foo.txt" \
448 > fix --working-dir
450 > fix --working-dir
449 $ cat foo.txt
451 $ cat foo.txt
450 1:1 4:6 8:8
452 1:1 4:6 8:8
451
453
452 $ cd ..
454 $ cd ..
453
455
454 Test that --whole fixes all lines regardless of the diffs present.
456 Test that --whole fixes all lines regardless of the diffs present.
455
457
456 $ hg init wholeignoresdiffs
458 $ hg init wholeignoresdiffs
457 $ cd wholeignoresdiffs
459 $ cd wholeignoresdiffs
458
460
459 $ printf "a\nb\nc\nd\ne\nf\ng\n" > foo.changed
461 $ printf "a\nb\nc\nd\ne\nf\ng\n" > foo.changed
460 $ hg commit -Aqm "foo"
462 $ hg commit -Aqm "foo"
461 $ printf "zz\na\nc\ndd\nee\nff\nf\ngg\n" > foo.changed
463 $ printf "zz\na\nc\ndd\nee\nff\nf\ngg\n" > foo.changed
462
464
463 $ hg fix --working-dir
465 $ hg fix --working-dir
464 $ cat foo.changed
466 $ cat foo.changed
465 ZZ
467 ZZ
466 a
468 a
467 c
469 c
468 DD
470 DD
469 EE
471 EE
470 FF
472 FF
471 f
473 f
472 GG
474 GG
473
475
474 $ hg fix --working-dir --whole
476 $ hg fix --working-dir --whole
475 $ cat foo.changed
477 $ cat foo.changed
476 ZZ
478 ZZ
477 A
479 A
478 C
480 C
479 DD
481 DD
480 EE
482 EE
481 FF
483 FF
482 F
484 F
483 GG
485 GG
484
486
485 $ cd ..
487 $ cd ..
486
488
487 We should do nothing with symlinks, and their targets should be unaffected. Any
489 We should do nothing with symlinks, and their targets should be unaffected. Any
488 other behavior would be more complicated to implement and harder to document.
490 other behavior would be more complicated to implement and harder to document.
489
491
490 #if symlink
492 #if symlink
491 $ hg init dontmesswithsymlinks
493 $ hg init dontmesswithsymlinks
492 $ cd dontmesswithsymlinks
494 $ cd dontmesswithsymlinks
493
495
494 $ printf "hello\n" > hello.whole
496 $ printf "hello\n" > hello.whole
495 $ ln -s hello.whole hellolink
497 $ ln -s hello.whole hellolink
496 $ hg add
498 $ hg add
497 adding hello.whole
499 adding hello.whole
498 adding hellolink
500 adding hellolink
499 $ hg fix --working-dir hellolink
501 $ hg fix --working-dir hellolink
500 $ hg status
502 $ hg status
501 A hello.whole
503 A hello.whole
502 A hellolink
504 A hellolink
503
505
504 $ cd ..
506 $ cd ..
505 #endif
507 #endif
506
508
507 We should allow fixers to run on binary files, even though this doesn't sound
509 We should allow fixers to run on binary files, even though this doesn't sound
508 like a common use case. There's not much benefit to disallowing it, and users
510 like a common use case. There's not much benefit to disallowing it, and users
509 can add "and not binary()" to their filesets if needed. The Mercurial
511 can add "and not binary()" to their filesets if needed. The Mercurial
510 philosophy is generally to not handle binary files specially anyway.
512 philosophy is generally to not handle binary files specially anyway.
511
513
512 $ hg init cantouchbinaryfiles
514 $ hg init cantouchbinaryfiles
513 $ cd cantouchbinaryfiles
515 $ cd cantouchbinaryfiles
514
516
515 $ printf "hello\0\n" > hello.whole
517 $ printf "hello\0\n" > hello.whole
516 $ hg add
518 $ hg add
517 adding hello.whole
519 adding hello.whole
518 $ hg fix --working-dir 'set:binary()'
520 $ hg fix --working-dir 'set:binary()'
519 $ cat hello.whole
521 $ cat hello.whole
520 HELLO\x00 (esc)
522 HELLO\x00 (esc)
521
523
522 $ cd ..
524 $ cd ..
523
525
524 We have a config for the maximum size of file we will attempt to fix. This can
526 We have a config for the maximum size of file we will attempt to fix. This can
525 be helpful to avoid running unsuspecting fixer tools on huge inputs, which
527 be helpful to avoid running unsuspecting fixer tools on huge inputs, which
526 could happen by accident without a well considered configuration. A more
528 could happen by accident without a well considered configuration. A more
527 precise configuration could use the size() fileset function if one global limit
529 precise configuration could use the size() fileset function if one global limit
528 is undesired.
530 is undesired.
529
531
530 $ hg init maxfilesize
532 $ hg init maxfilesize
531 $ cd maxfilesize
533 $ cd maxfilesize
532
534
533 $ printf "this file is huge\n" > hello.whole
535 $ printf "this file is huge\n" > hello.whole
534 $ hg add
536 $ hg add
535 adding hello.whole
537 adding hello.whole
536 $ hg --config fix.maxfilesize=10 fix --working-dir
538 $ hg --config fix.maxfilesize=10 fix --working-dir
537 ignoring file larger than 10 bytes: hello.whole
539 ignoring file larger than 10 bytes: hello.whole
538 $ cat hello.whole
540 $ cat hello.whole
539 this file is huge
541 this file is huge
540
542
541 $ cd ..
543 $ cd ..
542
544
543 If we specify a file to fix, other files should be left alone, even if they
545 If we specify a file to fix, other files should be left alone, even if they
544 have changes.
546 have changes.
545
547
546 $ hg init fixonlywhatitellyouto
548 $ hg init fixonlywhatitellyouto
547 $ cd fixonlywhatitellyouto
549 $ cd fixonlywhatitellyouto
548
550
549 $ printf "fix me!\n" > fixme.whole
551 $ printf "fix me!\n" > fixme.whole
550 $ printf "not me.\n" > notme.whole
552 $ printf "not me.\n" > notme.whole
551 $ hg add
553 $ hg add
552 adding fixme.whole
554 adding fixme.whole
553 adding notme.whole
555 adding notme.whole
554 $ hg fix --working-dir fixme.whole
556 $ hg fix --working-dir fixme.whole
555 $ cat *.whole
557 $ cat *.whole
556 FIX ME!
558 FIX ME!
557 not me.
559 not me.
558
560
559 $ cd ..
561 $ cd ..
560
562
561 If we try to fix a missing file, we still fix other files.
563 If we try to fix a missing file, we still fix other files.
562
564
563 $ hg init fixmissingfile
565 $ hg init fixmissingfile
564 $ cd fixmissingfile
566 $ cd fixmissingfile
565
567
566 $ printf "fix me!\n" > foo.whole
568 $ printf "fix me!\n" > foo.whole
567 $ hg add
569 $ hg add
568 adding foo.whole
570 adding foo.whole
569 $ hg fix --working-dir foo.whole bar.whole
571 $ hg fix --working-dir foo.whole bar.whole
570 bar.whole: $ENOENT$
572 bar.whole: $ENOENT$
571 $ cat *.whole
573 $ cat *.whole
572 FIX ME!
574 FIX ME!
573
575
574 $ cd ..
576 $ cd ..
575
577
576 Specifying a directory name should fix all its files and subdirectories.
578 Specifying a directory name should fix all its files and subdirectories.
577
579
578 $ hg init fixdirectory
580 $ hg init fixdirectory
579 $ cd fixdirectory
581 $ cd fixdirectory
580
582
581 $ mkdir -p dir1/dir2
583 $ mkdir -p dir1/dir2
582 $ printf "foo\n" > foo.whole
584 $ printf "foo\n" > foo.whole
583 $ printf "bar\n" > dir1/bar.whole
585 $ printf "bar\n" > dir1/bar.whole
584 $ printf "baz\n" > dir1/dir2/baz.whole
586 $ printf "baz\n" > dir1/dir2/baz.whole
585 $ hg add
587 $ hg add
586 adding dir1/bar.whole
588 adding dir1/bar.whole
587 adding dir1/dir2/baz.whole
589 adding dir1/dir2/baz.whole
588 adding foo.whole
590 adding foo.whole
589 $ hg fix --working-dir dir1
591 $ hg fix --working-dir dir1
590 $ cat foo.whole dir1/bar.whole dir1/dir2/baz.whole
592 $ cat foo.whole dir1/bar.whole dir1/dir2/baz.whole
591 foo
593 foo
592 BAR
594 BAR
593 BAZ
595 BAZ
594
596
595 $ cd ..
597 $ cd ..
596
598
597 Fixing a file in the working directory that needs no fixes should not actually
599 Fixing a file in the working directory that needs no fixes should not actually
598 write back to the file, so for example the mtime shouldn't change.
600 write back to the file, so for example the mtime shouldn't change.
599
601
600 $ hg init donttouchunfixedfiles
602 $ hg init donttouchunfixedfiles
601 $ cd donttouchunfixedfiles
603 $ cd donttouchunfixedfiles
602
604
603 $ printf "NO FIX NEEDED\n" > foo.whole
605 $ printf "NO FIX NEEDED\n" > foo.whole
604 $ hg add
606 $ hg add
605 adding foo.whole
607 adding foo.whole
606 $ cp -p foo.whole foo.whole.orig
608 $ cp -p foo.whole foo.whole.orig
607 $ cp -p foo.whole.orig foo.whole
609 $ cp -p foo.whole.orig foo.whole
608 $ sleep 2 # mtime has a resolution of one or two seconds.
610 $ sleep 2 # mtime has a resolution of one or two seconds.
609 $ hg fix --working-dir
611 $ hg fix --working-dir
610 $ f foo.whole.orig --newer foo.whole
612 $ f foo.whole.orig --newer foo.whole
611 foo.whole.orig: newer than foo.whole
613 foo.whole.orig: newer than foo.whole
612
614
613 $ cd ..
615 $ cd ..
614
616
615 When a fixer prints to stderr, we don't assume that it has failed. We show the
617 When a fixer prints to stderr, we don't assume that it has failed. We show the
616 error messages to the user, and we still let the fixer affect the file it was
618 error messages to the user, and we still let the fixer affect the file it was
617 fixing if its exit code is zero. Some code formatters might emit error messages
619 fixing if its exit code is zero. Some code formatters might emit error messages
618 on stderr and nothing on stdout, which would cause us the clear the file,
620 on stderr and nothing on stdout, which would cause us the clear the file,
619 except that they also exit with a non-zero code. We show the user which fixer
621 except that they also exit with a non-zero code. We show the user which fixer
620 emitted the stderr, and which revision, but we assume that the fixer will print
622 emitted the stderr, and which revision, but we assume that the fixer will print
621 the filename if it is relevant (since the issue may be non-specific). There is
623 the filename if it is relevant (since the issue may be non-specific). There is
622 also a config to abort (without affecting any files whatsoever) if we see any
624 also a config to abort (without affecting any files whatsoever) if we see any
623 tool with a non-zero exit status.
625 tool with a non-zero exit status.
624
626
625 $ hg init showstderr
627 $ hg init showstderr
626 $ cd showstderr
628 $ cd showstderr
627
629
628 $ printf "hello\n" > hello.txt
630 $ printf "hello\n" > hello.txt
629 $ hg add
631 $ hg add
630 adding hello.txt
632 adding hello.txt
631 $ cat > $TESTTMP/work.sh <<'EOF'
633 $ cat > $TESTTMP/work.sh <<'EOF'
632 > printf 'HELLO\n'
634 > printf 'HELLO\n'
633 > printf "$@: some\nerror that didn't stop the tool" >&2
635 > printf "$@: some\nerror that didn't stop the tool" >&2
634 > exit 0 # success despite the stderr output
636 > exit 0 # success despite the stderr output
635 > EOF
637 > EOF
636 $ hg --config "fix.work:command=sh $TESTTMP/work.sh {rootpath}" \
638 $ hg --config "fix.work:command=sh $TESTTMP/work.sh {rootpath}" \
637 > --config "fix.work:pattern=hello.txt" \
639 > --config "fix.work:pattern=hello.txt" \
638 > fix --working-dir
640 > fix --working-dir
639 [wdir] work: hello.txt: some
641 [wdir] work: hello.txt: some
640 [wdir] work: error that didn't stop the tool
642 [wdir] work: error that didn't stop the tool
641 $ cat hello.txt
643 $ cat hello.txt
642 HELLO
644 HELLO
643
645
644 $ printf "goodbye\n" > hello.txt
646 $ printf "goodbye\n" > hello.txt
645 $ printf "foo\n" > foo.whole
647 $ printf "foo\n" > foo.whole
646 $ hg add
648 $ hg add
647 adding foo.whole
649 adding foo.whole
648 $ cat > $TESTTMP/fail.sh <<'EOF'
650 $ cat > $TESTTMP/fail.sh <<'EOF'
649 > printf 'GOODBYE\n'
651 > printf 'GOODBYE\n'
650 > printf "$@: some\nerror that did stop the tool\n" >&2
652 > printf "$@: some\nerror that did stop the tool\n" >&2
651 > exit 42 # success despite the stdout output
653 > exit 42 # success despite the stdout output
652 > EOF
654 > EOF
653 $ hg --config "fix.fail:command=sh $TESTTMP/fail.sh {rootpath}" \
655 $ hg --config "fix.fail:command=sh $TESTTMP/fail.sh {rootpath}" \
654 > --config "fix.fail:pattern=hello.txt" \
656 > --config "fix.fail:pattern=hello.txt" \
655 > --config "fix.failure=abort" \
657 > --config "fix.failure=abort" \
656 > fix --working-dir
658 > fix --working-dir
657 [wdir] fail: hello.txt: some
659 [wdir] fail: hello.txt: some
658 [wdir] fail: error that did stop the tool
660 [wdir] fail: error that did stop the tool
659 abort: no fixes will be applied
661 abort: no fixes will be applied
660 (use --config fix.failure=continue to apply any successful fixes anyway)
662 (use --config fix.failure=continue to apply any successful fixes anyway)
661 [255]
663 [255]
662 $ cat hello.txt
664 $ cat hello.txt
663 goodbye
665 goodbye
664 $ cat foo.whole
666 $ cat foo.whole
665 foo
667 foo
666
668
667 $ hg --config "fix.fail:command=sh $TESTTMP/fail.sh {rootpath}" \
669 $ hg --config "fix.fail:command=sh $TESTTMP/fail.sh {rootpath}" \
668 > --config "fix.fail:pattern=hello.txt" \
670 > --config "fix.fail:pattern=hello.txt" \
669 > fix --working-dir
671 > fix --working-dir
670 [wdir] fail: hello.txt: some
672 [wdir] fail: hello.txt: some
671 [wdir] fail: error that did stop the tool
673 [wdir] fail: error that did stop the tool
672 $ cat hello.txt
674 $ cat hello.txt
673 goodbye
675 goodbye
674 $ cat foo.whole
676 $ cat foo.whole
675 FOO
677 FOO
676
678
677 $ hg --config "fix.fail:command=exit 42" \
679 $ hg --config "fix.fail:command=exit 42" \
678 > --config "fix.fail:pattern=hello.txt" \
680 > --config "fix.fail:pattern=hello.txt" \
679 > fix --working-dir
681 > fix --working-dir
680 [wdir] fail: exited with status 42
682 [wdir] fail: exited with status 42
681
683
682 $ cd ..
684 $ cd ..
683
685
684 Fixing the working directory and its parent revision at the same time should
686 Fixing the working directory and its parent revision at the same time should
685 check out the replacement revision for the parent. This prevents any new
687 check out the replacement revision for the parent. This prevents any new
686 uncommitted changes from appearing. We test this for a clean working directory
688 uncommitted changes from appearing. We test this for a clean working directory
687 and a dirty one. In both cases, all lines/files changed since the grandparent
689 and a dirty one. In both cases, all lines/files changed since the grandparent
688 will be fixed. The grandparent is the "baserev" for both the parent and the
690 will be fixed. The grandparent is the "baserev" for both the parent and the
689 working copy.
691 working copy.
690
692
691 $ hg init fixdotandcleanwdir
693 $ hg init fixdotandcleanwdir
692 $ cd fixdotandcleanwdir
694 $ cd fixdotandcleanwdir
693
695
694 $ printf "hello\n" > hello.whole
696 $ printf "hello\n" > hello.whole
695 $ printf "world\n" > world.whole
697 $ printf "world\n" > world.whole
696 $ hg commit -Aqm "the parent commit"
698 $ hg commit -Aqm "the parent commit"
697
699
698 $ hg parents --template '{rev} {desc}\n'
700 $ hg parents --template '{rev} {desc}\n'
699 0 the parent commit
701 0 the parent commit
700 $ hg fix --working-dir -r .
702 $ hg fix --working-dir -r .
701 $ hg parents --template '{rev} {desc}\n'
703 $ hg parents --template '{rev} {desc}\n'
702 1 the parent commit
704 1 the parent commit
703 $ hg cat -r . *.whole
705 $ hg cat -r . *.whole
704 HELLO
706 HELLO
705 WORLD
707 WORLD
706 $ cat *.whole
708 $ cat *.whole
707 HELLO
709 HELLO
708 WORLD
710 WORLD
709 $ hg status
711 $ hg status
710
712
711 $ cd ..
713 $ cd ..
712
714
713 Same test with a dirty working copy.
715 Same test with a dirty working copy.
714
716
715 $ hg init fixdotanddirtywdir
717 $ hg init fixdotanddirtywdir
716 $ cd fixdotanddirtywdir
718 $ cd fixdotanddirtywdir
717
719
718 $ printf "hello\n" > hello.whole
720 $ printf "hello\n" > hello.whole
719 $ printf "world\n" > world.whole
721 $ printf "world\n" > world.whole
720 $ hg commit -Aqm "the parent commit"
722 $ hg commit -Aqm "the parent commit"
721
723
722 $ printf "hello,\n" > hello.whole
724 $ printf "hello,\n" > hello.whole
723 $ printf "world!\n" > world.whole
725 $ printf "world!\n" > world.whole
724
726
725 $ hg parents --template '{rev} {desc}\n'
727 $ hg parents --template '{rev} {desc}\n'
726 0 the parent commit
728 0 the parent commit
727 $ hg fix --working-dir -r .
729 $ hg fix --working-dir -r .
728 $ hg parents --template '{rev} {desc}\n'
730 $ hg parents --template '{rev} {desc}\n'
729 1 the parent commit
731 1 the parent commit
730 $ hg cat -r . *.whole
732 $ hg cat -r . *.whole
731 HELLO
733 HELLO
732 WORLD
734 WORLD
733 $ cat *.whole
735 $ cat *.whole
734 HELLO,
736 HELLO,
735 WORLD!
737 WORLD!
736 $ hg status
738 $ hg status
737 M hello.whole
739 M hello.whole
738 M world.whole
740 M world.whole
739
741
740 $ cd ..
742 $ cd ..
741
743
742 When we have a chain of commits that change mutually exclusive lines of code,
744 When we have a chain of commits that change mutually exclusive lines of code,
743 we should be able to do incremental fixing that causes each commit in the chain
745 we should be able to do incremental fixing that causes each commit in the chain
744 to include fixes made to the previous commits. This prevents children from
746 to include fixes made to the previous commits. This prevents children from
745 backing out the fixes made in their parents. A dirty working directory is
747 backing out the fixes made in their parents. A dirty working directory is
746 conceptually similar to another commit in the chain.
748 conceptually similar to another commit in the chain.
747
749
748 $ hg init incrementallyfixchain
750 $ hg init incrementallyfixchain
749 $ cd incrementallyfixchain
751 $ cd incrementallyfixchain
750
752
751 $ cat > file.changed <<EOF
753 $ cat > file.changed <<EOF
752 > first
754 > first
753 > second
755 > second
754 > third
756 > third
755 > fourth
757 > fourth
756 > fifth
758 > fifth
757 > EOF
759 > EOF
758 $ hg commit -Aqm "the common ancestor (the baserev)"
760 $ hg commit -Aqm "the common ancestor (the baserev)"
759 $ cat > file.changed <<EOF
761 $ cat > file.changed <<EOF
760 > first (changed)
762 > first (changed)
761 > second
763 > second
762 > third
764 > third
763 > fourth
765 > fourth
764 > fifth
766 > fifth
765 > EOF
767 > EOF
766 $ hg commit -Aqm "the first commit to fix"
768 $ hg commit -Aqm "the first commit to fix"
767 $ cat > file.changed <<EOF
769 $ cat > file.changed <<EOF
768 > first (changed)
770 > first (changed)
769 > second
771 > second
770 > third (changed)
772 > third (changed)
771 > fourth
773 > fourth
772 > fifth
774 > fifth
773 > EOF
775 > EOF
774 $ hg commit -Aqm "the second commit to fix"
776 $ hg commit -Aqm "the second commit to fix"
775 $ cat > file.changed <<EOF
777 $ cat > file.changed <<EOF
776 > first (changed)
778 > first (changed)
777 > second
779 > second
778 > third (changed)
780 > third (changed)
779 > fourth
781 > fourth
780 > fifth (changed)
782 > fifth (changed)
781 > EOF
783 > EOF
782
784
783 $ hg fix -r . -r '.^' --working-dir
785 $ hg fix -r . -r '.^' --working-dir
784
786
785 $ hg parents --template '{rev}\n'
787 $ hg parents --template '{rev}\n'
786 4
788 4
787 $ hg cat -r '.^^' file.changed
789 $ hg cat -r '.^^' file.changed
788 first
790 first
789 second
791 second
790 third
792 third
791 fourth
793 fourth
792 fifth
794 fifth
793 $ hg cat -r '.^' file.changed
795 $ hg cat -r '.^' file.changed
794 FIRST (CHANGED)
796 FIRST (CHANGED)
795 second
797 second
796 third
798 third
797 fourth
799 fourth
798 fifth
800 fifth
799 $ hg cat -r . file.changed
801 $ hg cat -r . file.changed
800 FIRST (CHANGED)
802 FIRST (CHANGED)
801 second
803 second
802 THIRD (CHANGED)
804 THIRD (CHANGED)
803 fourth
805 fourth
804 fifth
806 fifth
805 $ cat file.changed
807 $ cat file.changed
806 FIRST (CHANGED)
808 FIRST (CHANGED)
807 second
809 second
808 THIRD (CHANGED)
810 THIRD (CHANGED)
809 fourth
811 fourth
810 FIFTH (CHANGED)
812 FIFTH (CHANGED)
811
813
812 $ cd ..
814 $ cd ..
813
815
814 If we incrementally fix a merge commit, we should fix any lines that changed
816 If we incrementally fix a merge commit, we should fix any lines that changed
815 versus either parent. You could imagine only fixing the intersection or some
817 versus either parent. You could imagine only fixing the intersection or some
816 other subset, but this is necessary if either parent is being fixed. It
818 other subset, but this is necessary if either parent is being fixed. It
817 prevents us from forgetting fixes made in either parent.
819 prevents us from forgetting fixes made in either parent.
818
820
819 $ hg init incrementallyfixmergecommit
821 $ hg init incrementallyfixmergecommit
820 $ cd incrementallyfixmergecommit
822 $ cd incrementallyfixmergecommit
821
823
822 $ printf "a\nb\nc\n" > file.changed
824 $ printf "a\nb\nc\n" > file.changed
823 $ hg commit -Aqm "ancestor"
825 $ hg commit -Aqm "ancestor"
824
826
825 $ printf "aa\nb\nc\n" > file.changed
827 $ printf "aa\nb\nc\n" > file.changed
826 $ hg commit -m "change a"
828 $ hg commit -m "change a"
827
829
828 $ hg checkout '.^'
830 $ hg checkout '.^'
829 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
831 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
830 $ printf "a\nb\ncc\n" > file.changed
832 $ printf "a\nb\ncc\n" > file.changed
831 $ hg commit -m "change c"
833 $ hg commit -m "change c"
832 created new head
834 created new head
833
835
834 $ hg merge
836 $ hg merge
835 merging file.changed
837 merging file.changed
836 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
838 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
837 (branch merge, don't forget to commit)
839 (branch merge, don't forget to commit)
838 $ hg commit -m "merge"
840 $ hg commit -m "merge"
839 $ hg cat -r . file.changed
841 $ hg cat -r . file.changed
840 aa
842 aa
841 b
843 b
842 cc
844 cc
843
845
844 $ hg fix -r . --working-dir
846 $ hg fix -r . --working-dir
845 $ hg cat -r . file.changed
847 $ hg cat -r . file.changed
846 AA
848 AA
847 b
849 b
848 CC
850 CC
849
851
850 $ cd ..
852 $ cd ..
851
853
852 Abort fixing revisions if there is an unfinished operation. We don't want to
854 Abort fixing revisions if there is an unfinished operation. We don't want to
853 make things worse by editing files or stripping/obsoleting things. Also abort
855 make things worse by editing files or stripping/obsoleting things. Also abort
854 fixing the working directory if there are unresolved merge conflicts.
856 fixing the working directory if there are unresolved merge conflicts.
855
857
856 $ hg init abortunresolved
858 $ hg init abortunresolved
857 $ cd abortunresolved
859 $ cd abortunresolved
858
860
859 $ echo "foo1" > foo.whole
861 $ echo "foo1" > foo.whole
860 $ hg commit -Aqm "foo 1"
862 $ hg commit -Aqm "foo 1"
861
863
862 $ hg update null
864 $ hg update null
863 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
865 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
864 $ echo "foo2" > foo.whole
866 $ echo "foo2" > foo.whole
865 $ hg commit -Aqm "foo 2"
867 $ hg commit -Aqm "foo 2"
866
868
867 $ hg --config extensions.rebase= rebase -r 1 -d 0
869 $ hg --config extensions.rebase= rebase -r 1 -d 0
868 rebasing 1:c3b6dc0e177a tip "foo 2"
870 rebasing 1:c3b6dc0e177a tip "foo 2"
869 merging foo.whole
871 merging foo.whole
870 warning: conflicts while merging foo.whole! (edit, then use 'hg resolve --mark')
872 warning: conflicts while merging foo.whole! (edit, then use 'hg resolve --mark')
871 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
873 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue')
872 [240]
874 [240]
873
875
874 $ hg --config extensions.rebase= fix --working-dir
876 $ hg --config extensions.rebase= fix --working-dir
875 abort: unresolved conflicts
877 abort: unresolved conflicts
876 (use 'hg resolve')
878 (use 'hg resolve')
877 [255]
879 [255]
878
880
879 $ hg --config extensions.rebase= fix -r .
881 $ hg --config extensions.rebase= fix -r .
880 abort: rebase in progress
882 abort: rebase in progress
881 (use 'hg rebase --continue', 'hg rebase --abort', or 'hg rebase --stop')
883 (use 'hg rebase --continue', 'hg rebase --abort', or 'hg rebase --stop')
882 [20]
884 [20]
883
885
884 $ cd ..
886 $ cd ..
885
887
886 When fixing a file that was renamed, we should diff against the source of the
888 When fixing a file that was renamed, we should diff against the source of the
887 rename for incremental fixing and we should correctly reproduce the rename in
889 rename for incremental fixing and we should correctly reproduce the rename in
888 the replacement revision.
890 the replacement revision.
889
891
890 $ hg init fixrenamecommit
892 $ hg init fixrenamecommit
891 $ cd fixrenamecommit
893 $ cd fixrenamecommit
892
894
893 $ printf "a\nb\nc\n" > source.changed
895 $ printf "a\nb\nc\n" > source.changed
894 $ hg commit -Aqm "source revision"
896 $ hg commit -Aqm "source revision"
895 $ hg move source.changed dest.changed
897 $ hg move source.changed dest.changed
896 $ printf "a\nb\ncc\n" > dest.changed
898 $ printf "a\nb\ncc\n" > dest.changed
897 $ hg commit -m "dest revision"
899 $ hg commit -m "dest revision"
898
900
899 $ hg fix -r .
901 $ hg fix -r .
900 $ hg log -r tip --copies --template "{file_copies}\n"
902 $ hg log -r tip --copies --template "{file_copies}\n"
901 dest.changed (source.changed)
903 dest.changed (source.changed)
902 $ hg cat -r tip dest.changed
904 $ hg cat -r tip dest.changed
903 a
905 a
904 b
906 b
905 CC
907 CC
906
908
907 $ cd ..
909 $ cd ..
908
910
909 When fixing revisions that remove files we must ensure that the replacement
911 When fixing revisions that remove files we must ensure that the replacement
910 actually removes the file, whereas it could accidentally leave it unchanged or
912 actually removes the file, whereas it could accidentally leave it unchanged or
911 write an empty string to it.
913 write an empty string to it.
912
914
913 $ hg init fixremovedfile
915 $ hg init fixremovedfile
914 $ cd fixremovedfile
916 $ cd fixremovedfile
915
917
916 $ printf "foo\n" > foo.whole
918 $ printf "foo\n" > foo.whole
917 $ printf "bar\n" > bar.whole
919 $ printf "bar\n" > bar.whole
918 $ hg commit -Aqm "add files"
920 $ hg commit -Aqm "add files"
919 $ hg remove bar.whole
921 $ hg remove bar.whole
920 $ hg commit -m "remove file"
922 $ hg commit -m "remove file"
921 $ hg status --change .
923 $ hg status --change .
922 R bar.whole
924 R bar.whole
923 $ hg fix -r . foo.whole
925 $ hg fix -r . foo.whole
924 $ hg status --change tip
926 $ hg status --change tip
925 M foo.whole
927 M foo.whole
926 R bar.whole
928 R bar.whole
927
929
928 $ cd ..
930 $ cd ..
929
931
930 If fixing a revision finds no fixes to make, no replacement revision should be
932 If fixing a revision finds no fixes to make, no replacement revision should be
931 created.
933 created.
932
934
933 $ hg init nofixesneeded
935 $ hg init nofixesneeded
934 $ cd nofixesneeded
936 $ cd nofixesneeded
935
937
936 $ printf "FOO\n" > foo.whole
938 $ printf "FOO\n" > foo.whole
937 $ hg commit -Aqm "add file"
939 $ hg commit -Aqm "add file"
938 $ hg log --template '{rev}\n'
940 $ hg log --template '{rev}\n'
939 0
941 0
940 $ hg fix -r .
942 $ hg fix -r .
941 $ hg log --template '{rev}\n'
943 $ hg log --template '{rev}\n'
942 0
944 0
943
945
944 $ cd ..
946 $ cd ..
945
947
946 If fixing a commit reverts all the changes in the commit, we replace it with a
948 If fixing a commit reverts all the changes in the commit, we replace it with a
947 commit that changes no files.
949 commit that changes no files.
948
950
949 $ hg init nochangesleft
951 $ hg init nochangesleft
950 $ cd nochangesleft
952 $ cd nochangesleft
951
953
952 $ printf "FOO\n" > foo.whole
954 $ printf "FOO\n" > foo.whole
953 $ hg commit -Aqm "add file"
955 $ hg commit -Aqm "add file"
954 $ printf "foo\n" > foo.whole
956 $ printf "foo\n" > foo.whole
955 $ hg commit -m "edit file"
957 $ hg commit -m "edit file"
956 $ hg status --change .
958 $ hg status --change .
957 M foo.whole
959 M foo.whole
958 $ hg fix -r .
960 $ hg fix -r .
959 $ hg status --change tip
961 $ hg status --change tip
960
962
961 $ cd ..
963 $ cd ..
962
964
963 If we fix a parent and child revision together, the child revision must be
965 If we fix a parent and child revision together, the child revision must be
964 replaced if the parent is replaced, even if the diffs of the child needed no
966 replaced if the parent is replaced, even if the diffs of the child needed no
965 fixes. However, we're free to not replace revisions that need no fixes and have
967 fixes. However, we're free to not replace revisions that need no fixes and have
966 no ancestors that are replaced.
968 no ancestors that are replaced.
967
969
968 $ hg init mustreplacechild
970 $ hg init mustreplacechild
969 $ cd mustreplacechild
971 $ cd mustreplacechild
970
972
971 $ printf "FOO\n" > foo.whole
973 $ printf "FOO\n" > foo.whole
972 $ hg commit -Aqm "add foo"
974 $ hg commit -Aqm "add foo"
973 $ printf "foo\n" > foo.whole
975 $ printf "foo\n" > foo.whole
974 $ hg commit -m "edit foo"
976 $ hg commit -m "edit foo"
975 $ printf "BAR\n" > bar.whole
977 $ printf "BAR\n" > bar.whole
976 $ hg commit -Aqm "add bar"
978 $ hg commit -Aqm "add bar"
977
979
978 $ hg log --graph --template '{rev} {files}'
980 $ hg log --graph --template '{rev} {files}'
979 @ 2 bar.whole
981 @ 2 bar.whole
980 |
982 |
981 o 1 foo.whole
983 o 1 foo.whole
982 |
984 |
983 o 0 foo.whole
985 o 0 foo.whole
984
986
985 $ hg fix -r 0:2
987 $ hg fix -r 0:2
986 $ hg log --graph --template '{rev} {files}'
988 $ hg log --graph --template '{rev} {files}'
987 o 4 bar.whole
989 o 4 bar.whole
988 |
990 |
989 o 3
991 o 3
990 |
992 |
991 | @ 2 bar.whole
993 | @ 2 bar.whole
992 | |
994 | |
993 | x 1 foo.whole
995 | x 1 foo.whole
994 |/
996 |/
995 o 0 foo.whole
997 o 0 foo.whole
996
998
997
999
998 $ cd ..
1000 $ cd ..
999
1001
1000 It's also possible that the child needs absolutely no changes, but we still
1002 It's also possible that the child needs absolutely no changes, but we still
1001 need to replace it to update its parent. If we skipped replacing the child
1003 need to replace it to update its parent. If we skipped replacing the child
1002 because it had no file content changes, it would become an orphan for no good
1004 because it had no file content changes, it would become an orphan for no good
1003 reason.
1005 reason.
1004
1006
1005 $ hg init mustreplacechildevenifnop
1007 $ hg init mustreplacechildevenifnop
1006 $ cd mustreplacechildevenifnop
1008 $ cd mustreplacechildevenifnop
1007
1009
1008 $ printf "Foo\n" > foo.whole
1010 $ printf "Foo\n" > foo.whole
1009 $ hg commit -Aqm "add a bad foo"
1011 $ hg commit -Aqm "add a bad foo"
1010 $ printf "FOO\n" > foo.whole
1012 $ printf "FOO\n" > foo.whole
1011 $ hg commit -m "add a good foo"
1013 $ hg commit -m "add a good foo"
1012 $ hg fix -r . -r '.^'
1014 $ hg fix -r . -r '.^'
1013 $ hg log --graph --template '{rev} {desc}'
1015 $ hg log --graph --template '{rev} {desc}'
1014 o 3 add a good foo
1016 o 3 add a good foo
1015 |
1017 |
1016 o 2 add a bad foo
1018 o 2 add a bad foo
1017
1019
1018 @ 1 add a good foo
1020 @ 1 add a good foo
1019 |
1021 |
1020 x 0 add a bad foo
1022 x 0 add a bad foo
1021
1023
1022
1024
1023 $ cd ..
1025 $ cd ..
1024
1026
1025 Similar to the case above, the child revision may become empty as a result of
1027 Similar to the case above, the child revision may become empty as a result of
1026 fixing its parent. We should still create an empty replacement child.
1028 fixing its parent. We should still create an empty replacement child.
1027 TODO: determine how this should interact with ui.allowemptycommit given that
1029 TODO: determine how this should interact with ui.allowemptycommit given that
1028 the empty replacement could have children.
1030 the empty replacement could have children.
1029
1031
1030 $ hg init mustreplacechildevenifempty
1032 $ hg init mustreplacechildevenifempty
1031 $ cd mustreplacechildevenifempty
1033 $ cd mustreplacechildevenifempty
1032
1034
1033 $ printf "foo\n" > foo.whole
1035 $ printf "foo\n" > foo.whole
1034 $ hg commit -Aqm "add foo"
1036 $ hg commit -Aqm "add foo"
1035 $ printf "Foo\n" > foo.whole
1037 $ printf "Foo\n" > foo.whole
1036 $ hg commit -m "edit foo"
1038 $ hg commit -m "edit foo"
1037 $ hg fix -r . -r '.^'
1039 $ hg fix -r . -r '.^'
1038 $ hg log --graph --template '{rev} {desc}\n' --stat
1040 $ hg log --graph --template '{rev} {desc}\n' --stat
1039 o 3 edit foo
1041 o 3 edit foo
1040 |
1042 |
1041 o 2 add foo
1043 o 2 add foo
1042 foo.whole | 1 +
1044 foo.whole | 1 +
1043 1 files changed, 1 insertions(+), 0 deletions(-)
1045 1 files changed, 1 insertions(+), 0 deletions(-)
1044
1046
1045 @ 1 edit foo
1047 @ 1 edit foo
1046 | foo.whole | 2 +-
1048 | foo.whole | 2 +-
1047 | 1 files changed, 1 insertions(+), 1 deletions(-)
1049 | 1 files changed, 1 insertions(+), 1 deletions(-)
1048 |
1050 |
1049 x 0 add foo
1051 x 0 add foo
1050 foo.whole | 1 +
1052 foo.whole | 1 +
1051 1 files changed, 1 insertions(+), 0 deletions(-)
1053 1 files changed, 1 insertions(+), 0 deletions(-)
1052
1054
1053
1055
1054 $ cd ..
1056 $ cd ..
1055
1057
1056 Fixing a secret commit should replace it with another secret commit.
1058 Fixing a secret commit should replace it with another secret commit.
1057
1059
1058 $ hg init fixsecretcommit
1060 $ hg init fixsecretcommit
1059 $ cd fixsecretcommit
1061 $ cd fixsecretcommit
1060
1062
1061 $ printf "foo\n" > foo.whole
1063 $ printf "foo\n" > foo.whole
1062 $ hg commit -Aqm "add foo" --secret
1064 $ hg commit -Aqm "add foo" --secret
1063 $ hg fix -r .
1065 $ hg fix -r .
1064 $ hg log --template '{rev} {phase}\n'
1066 $ hg log --template '{rev} {phase}\n'
1065 1 secret
1067 1 secret
1066 0 secret
1068 0 secret
1067
1069
1068 $ cd ..
1070 $ cd ..
1069
1071
1070 We should also preserve phase when fixing a draft commit while the user has
1072 We should also preserve phase when fixing a draft commit while the user has
1071 their default set to secret.
1073 their default set to secret.
1072
1074
1073 $ hg init respectphasesnewcommit
1075 $ hg init respectphasesnewcommit
1074 $ cd respectphasesnewcommit
1076 $ cd respectphasesnewcommit
1075
1077
1076 $ printf "foo\n" > foo.whole
1078 $ printf "foo\n" > foo.whole
1077 $ hg commit -Aqm "add foo"
1079 $ hg commit -Aqm "add foo"
1078 $ hg --config phases.newcommit=secret fix -r .
1080 $ hg --config phases.newcommit=secret fix -r .
1079 $ hg log --template '{rev} {phase}\n'
1081 $ hg log --template '{rev} {phase}\n'
1080 1 draft
1082 1 draft
1081 0 draft
1083 0 draft
1082
1084
1083 $ cd ..
1085 $ cd ..
1084
1086
1085 Debug output should show what fixer commands are being subprocessed, which is
1087 Debug output should show what fixer commands are being subprocessed, which is
1086 useful for anyone trying to set up a new config.
1088 useful for anyone trying to set up a new config.
1087
1089
1088 $ hg init debugoutput
1090 $ hg init debugoutput
1089 $ cd debugoutput
1091 $ cd debugoutput
1090
1092
1091 $ printf "foo\nbar\nbaz\n" > foo.changed
1093 $ printf "foo\nbar\nbaz\n" > foo.changed
1092 $ hg commit -Aqm "foo"
1094 $ hg commit -Aqm "foo"
1093 $ printf "Foo\nbar\nBaz\n" > foo.changed
1095 $ printf "Foo\nbar\nBaz\n" > foo.changed
1094 $ hg --debug fix --working-dir
1096 $ hg --debug fix --working-dir
1095 subprocess: * $TESTTMP/uppercase.py 1-1 3-3 (glob)
1097 subprocess: * $TESTTMP/uppercase.py 1-1 3-3 (glob)
1096
1098
1097 $ cd ..
1099 $ cd ..
1098
1100
1099 Fixing an obsolete revision can cause divergence, so we abort unless the user
1101 Fixing an obsolete revision can cause divergence, so we abort unless the user
1100 configures to allow it. This is not yet smart enough to know whether there is a
1102 configures to allow it. This is not yet smart enough to know whether there is a
1101 successor, but even then it is not likely intentional or idiomatic to fix an
1103 successor, but even then it is not likely intentional or idiomatic to fix an
1102 obsolete revision.
1104 obsolete revision.
1103
1105
1104 $ hg init abortobsoleterev
1106 $ hg init abortobsoleterev
1105 $ cd abortobsoleterev
1107 $ cd abortobsoleterev
1106
1108
1107 $ printf "foo\n" > foo.changed
1109 $ printf "foo\n" > foo.changed
1108 $ hg commit -Aqm "foo"
1110 $ hg commit -Aqm "foo"
1109 $ hg ci --amend -m rewritten
1111 $ hg ci --amend -m rewritten
1110 $ hg --hidden fix -r 0
1112 $ hg --hidden fix -r 0
1111 abort: fixing obsolete revision could cause divergence
1113 abort: fixing obsolete revision could cause divergence
1112 [255]
1114 [255]
1113
1115
1114 $ hg --hidden fix -r 0 --config experimental.evolution.allowdivergence=true
1116 $ hg --hidden fix -r 0 --config experimental.evolution.allowdivergence=true
1115 2 new content-divergent changesets
1117 2 new content-divergent changesets
1116 $ hg cat -r tip foo.changed
1118 $ hg cat -r tip foo.changed
1117 FOO
1119 FOO
1118
1120
1119 $ cd ..
1121 $ cd ..
1120
1122
1121 Test all of the available substitution values for fixer commands.
1123 Test all of the available substitution values for fixer commands.
1122
1124
1123 $ hg init substitution
1125 $ hg init substitution
1124 $ cd substitution
1126 $ cd substitution
1125
1127
1126 $ mkdir foo
1128 $ mkdir foo
1127 $ printf "hello\ngoodbye\n" > foo/bar
1129 $ printf "hello\ngoodbye\n" > foo/bar
1128 $ hg add
1130 $ hg add
1129 adding foo/bar
1131 adding foo/bar
1130 $ hg --config "fix.fail:command=printf '%s\n' '{rootpath}' '{basename}'" \
1132 $ hg --config "fix.fail:command=printf '%s\n' '{rootpath}' '{basename}'" \
1131 > --config "fix.fail:linerange='{first}' '{last}'" \
1133 > --config "fix.fail:linerange='{first}' '{last}'" \
1132 > --config "fix.fail:pattern=foo/bar" \
1134 > --config "fix.fail:pattern=foo/bar" \
1133 > fix --working-dir
1135 > fix --working-dir
1134 $ cat foo/bar
1136 $ cat foo/bar
1135 foo/bar
1137 foo/bar
1136 bar
1138 bar
1137 1
1139 1
1138 2
1140 2
1139
1141
1140 $ cd ..
1142 $ cd ..
1141
1143
1142 The --base flag should allow picking the revisions to diff against for changed
1144 The --base flag should allow picking the revisions to diff against for changed
1143 files and incremental line formatting.
1145 files and incremental line formatting.
1144
1146
1145 $ hg init baseflag
1147 $ hg init baseflag
1146 $ cd baseflag
1148 $ cd baseflag
1147
1149
1148 $ printf "one\ntwo\n" > foo.changed
1150 $ printf "one\ntwo\n" > foo.changed
1149 $ printf "bar\n" > bar.changed
1151 $ printf "bar\n" > bar.changed
1150 $ hg commit -Aqm "first"
1152 $ hg commit -Aqm "first"
1151 $ printf "one\nTwo\n" > foo.changed
1153 $ printf "one\nTwo\n" > foo.changed
1152 $ hg commit -m "second"
1154 $ hg commit -m "second"
1153 $ hg fix -w --base .
1155 $ hg fix -w --base .
1154 $ hg status
1156 $ hg status
1155 $ hg fix -w --base null
1157 $ hg fix -w --base null
1156 $ cat foo.changed
1158 $ cat foo.changed
1157 ONE
1159 ONE
1158 TWO
1160 TWO
1159 $ cat bar.changed
1161 $ cat bar.changed
1160 BAR
1162 BAR
1161
1163
1162 $ cd ..
1164 $ cd ..
1163
1165
1164 If the user asks to fix the parent of another commit, they are asking to create
1166 If the user asks to fix the parent of another commit, they are asking to create
1165 an orphan. We must respect experimental.evolution.allowunstable.
1167 an orphan. We must respect experimental.evolution.allowunstable.
1166
1168
1167 $ hg init allowunstable
1169 $ hg init allowunstable
1168 $ cd allowunstable
1170 $ cd allowunstable
1169
1171
1170 $ printf "one\n" > foo.whole
1172 $ printf "one\n" > foo.whole
1171 $ hg commit -Aqm "first"
1173 $ hg commit -Aqm "first"
1172 $ printf "two\n" > foo.whole
1174 $ printf "two\n" > foo.whole
1173 $ hg commit -m "second"
1175 $ hg commit -m "second"
1174 $ hg --config experimental.evolution.allowunstable=False fix -r '.^'
1176 $ hg --config experimental.evolution.allowunstable=False fix -r '.^'
1175 abort: cannot fix changeset with children
1177 abort: cannot fix changeset with children
1176 [10]
1178 [10]
1177 $ hg fix -r '.^'
1179 $ hg fix -r '.^'
1178 1 new orphan changesets
1180 1 new orphan changesets
1179 $ hg cat -r 2 foo.whole
1181 $ hg cat -r 2 foo.whole
1180 ONE
1182 ONE
1181
1183
1182 $ cd ..
1184 $ cd ..
1183
1185
1184 The --base flag affects the set of files being fixed. So while the --whole flag
1186 The --base flag affects the set of files being fixed. So while the --whole flag
1185 makes the base irrelevant for changed line ranges, it still changes the
1187 makes the base irrelevant for changed line ranges, it still changes the
1186 meaning and effect of the command. In this example, no files or lines are fixed
1188 meaning and effect of the command. In this example, no files or lines are fixed
1187 until we specify the base, but then we do fix unchanged lines.
1189 until we specify the base, but then we do fix unchanged lines.
1188
1190
1189 $ hg init basewhole
1191 $ hg init basewhole
1190 $ cd basewhole
1192 $ cd basewhole
1191 $ printf "foo1\n" > foo.changed
1193 $ printf "foo1\n" > foo.changed
1192 $ hg commit -Aqm "first"
1194 $ hg commit -Aqm "first"
1193 $ printf "foo2\n" >> foo.changed
1195 $ printf "foo2\n" >> foo.changed
1194 $ printf "bar\n" > bar.changed
1196 $ printf "bar\n" > bar.changed
1195 $ hg commit -Aqm "second"
1197 $ hg commit -Aqm "second"
1196
1198
1197 $ hg fix --working-dir --whole
1199 $ hg fix --working-dir --whole
1198 $ cat *.changed
1200 $ cat *.changed
1199 bar
1201 bar
1200 foo1
1202 foo1
1201 foo2
1203 foo2
1202
1204
1203 $ hg fix --working-dir --base 0 --whole
1205 $ hg fix --working-dir --base 0 --whole
1204 $ cat *.changed
1206 $ cat *.changed
1205 BAR
1207 BAR
1206 FOO1
1208 FOO1
1207 FOO2
1209 FOO2
1208
1210
1209 $ cd ..
1211 $ cd ..
1210
1212
1211 The execution order of tools can be controlled. This example doesn't work if
1213 The execution order of tools can be controlled. This example doesn't work if
1212 you sort after truncating, but the config defines the correct order while the
1214 you sort after truncating, but the config defines the correct order while the
1213 definitions are out of order (which might imply the incorrect order given the
1215 definitions are out of order (which might imply the incorrect order given the
1214 implementation of fix). The goal is to use multiple tools to select the lowest
1216 implementation of fix). The goal is to use multiple tools to select the lowest
1215 5 numbers in the file.
1217 5 numbers in the file.
1216
1218
1217 $ hg init priorityexample
1219 $ hg init priorityexample
1218 $ cd priorityexample
1220 $ cd priorityexample
1219
1221
1220 $ cat >> .hg/hgrc <<EOF
1222 $ cat >> .hg/hgrc <<EOF
1221 > [fix]
1223 > [fix]
1222 > head:command = head -n 5
1224 > head:command = head -n 5
1223 > head:pattern = numbers.txt
1225 > head:pattern = numbers.txt
1224 > head:priority = 1
1226 > head:priority = 1
1225 > sort:command = sort -n
1227 > sort:command = sort -n
1226 > sort:pattern = numbers.txt
1228 > sort:pattern = numbers.txt
1227 > sort:priority = 2
1229 > sort:priority = 2
1228 > EOF
1230 > EOF
1229
1231
1230 $ printf "8\n2\n3\n6\n7\n4\n9\n5\n1\n0\n" > numbers.txt
1232 $ printf "8\n2\n3\n6\n7\n4\n9\n5\n1\n0\n" > numbers.txt
1231 $ hg add -q
1233 $ hg add -q
1232 $ hg fix -w
1234 $ hg fix -w
1233 $ cat numbers.txt
1235 $ cat numbers.txt
1234 0
1236 0
1235 1
1237 1
1236 2
1238 2
1237 3
1239 3
1238 4
1240 4
1239
1241
1240 And of course we should be able to break this by reversing the execution order.
1242 And of course we should be able to break this by reversing the execution order.
1241 Test negative priorities while we're at it.
1243 Test negative priorities while we're at it.
1242
1244
1243 $ cat >> .hg/hgrc <<EOF
1245 $ cat >> .hg/hgrc <<EOF
1244 > [fix]
1246 > [fix]
1245 > head:priority = -1
1247 > head:priority = -1
1246 > sort:priority = -2
1248 > sort:priority = -2
1247 > EOF
1249 > EOF
1248 $ printf "8\n2\n3\n6\n7\n4\n9\n5\n1\n0\n" > numbers.txt
1250 $ printf "8\n2\n3\n6\n7\n4\n9\n5\n1\n0\n" > numbers.txt
1249 $ hg fix -w
1251 $ hg fix -w
1250 $ cat numbers.txt
1252 $ cat numbers.txt
1251 2
1253 2
1252 3
1254 3
1253 6
1255 6
1254 7
1256 7
1255 8
1257 8
1256
1258
1257 $ cd ..
1259 $ cd ..
1258
1260
1259 It's possible for repeated applications of a fixer tool to create cycles in the
1261 It's possible for repeated applications of a fixer tool to create cycles in the
1260 generated content of a file. For example, two users with different versions of
1262 generated content of a file. For example, two users with different versions of
1261 a code formatter might fight over the formatting when they run hg fix. In the
1263 a code formatter might fight over the formatting when they run hg fix. In the
1262 absence of other changes, this means we could produce commits with the same
1264 absence of other changes, this means we could produce commits with the same
1263 hash in subsequent runs of hg fix. This is a problem unless we support
1265 hash in subsequent runs of hg fix. This is a problem unless we support
1264 obsolescence cycles well. We avoid this by adding an extra field to the
1266 obsolescence cycles well. We avoid this by adding an extra field to the
1265 successor which forces it to have a new hash. That's why this test creates
1267 successor which forces it to have a new hash. That's why this test creates
1266 three revisions instead of two.
1268 three revisions instead of two.
1267
1269
1268 $ hg init cyclictool
1270 $ hg init cyclictool
1269 $ cd cyclictool
1271 $ cd cyclictool
1270
1272
1271 $ cat >> .hg/hgrc <<EOF
1273 $ cat >> .hg/hgrc <<EOF
1272 > [fix]
1274 > [fix]
1273 > swapletters:command = tr ab ba
1275 > swapletters:command = tr ab ba
1274 > swapletters:pattern = foo
1276 > swapletters:pattern = foo
1275 > EOF
1277 > EOF
1276
1278
1277 $ echo ab > foo
1279 $ echo ab > foo
1278 $ hg commit -Aqm foo
1280 $ hg commit -Aqm foo
1279
1281
1280 $ hg fix -r 0
1282 $ hg fix -r 0
1281 $ hg fix -r 1
1283 $ hg fix -r 1
1282
1284
1283 $ hg cat -r 0 foo --hidden
1285 $ hg cat -r 0 foo --hidden
1284 ab
1286 ab
1285 $ hg cat -r 1 foo --hidden
1287 $ hg cat -r 1 foo --hidden
1286 ba
1288 ba
1287 $ hg cat -r 2 foo
1289 $ hg cat -r 2 foo
1288 ab
1290 ab
1289
1291
1290 $ cd ..
1292 $ cd ..
1291
1293
1292 We run fixer tools in the repo root so they can look for config files or other
1294 We run fixer tools in the repo root so they can look for config files or other
1293 important things in the working directory. This does NOT mean we are
1295 important things in the working directory. This does NOT mean we are
1294 reconstructing a working copy of every revision being fixed; we're just giving
1296 reconstructing a working copy of every revision being fixed; we're just giving
1295 the tool knowledge of the repo's location in case it can do something
1297 the tool knowledge of the repo's location in case it can do something
1296 reasonable with that.
1298 reasonable with that.
1297
1299
1298 $ hg init subprocesscwd
1300 $ hg init subprocesscwd
1299 $ cd subprocesscwd
1301 $ cd subprocesscwd
1300
1302
1301 $ cat >> .hg/hgrc <<EOF
1303 $ cat >> .hg/hgrc <<EOF
1302 > [fix]
1304 > [fix]
1303 > printcwd:command = "$PYTHON" -c "import os; print(os.getcwd())"
1305 > printcwd:command = "$PYTHON" -c "import os; print(os.getcwd())"
1304 > printcwd:pattern = relpath:foo/bar
1306 > printcwd:pattern = relpath:foo/bar
1305 > filesetpwd:command = "$PYTHON" -c "import os; print('fs: ' + os.getcwd())"
1307 > filesetpwd:command = "$PYTHON" -c "import os; print('fs: ' + os.getcwd())"
1306 > filesetpwd:pattern = set:**quux
1308 > filesetpwd:pattern = set:**quux
1307 > EOF
1309 > EOF
1308
1310
1309 $ mkdir foo
1311 $ mkdir foo
1310 $ printf "bar\n" > foo/bar
1312 $ printf "bar\n" > foo/bar
1311 $ printf "quux\n" > quux
1313 $ printf "quux\n" > quux
1312 $ hg commit -Aqm blah
1314 $ hg commit -Aqm blah
1313
1315
1314 $ hg fix -w -r . foo/bar
1316 $ hg fix -w -r . foo/bar
1315 $ hg cat -r tip foo/bar
1317 $ hg cat -r tip foo/bar
1316 $TESTTMP/subprocesscwd
1318 $TESTTMP/subprocesscwd
1317 $ cat foo/bar
1319 $ cat foo/bar
1318 $TESTTMP/subprocesscwd
1320 $TESTTMP/subprocesscwd
1319
1321
1320 $ cd foo
1322 $ cd foo
1321
1323
1322 $ hg fix -w -r . bar
1324 $ hg fix -w -r . bar
1323 $ hg cat -r tip bar ../quux
1325 $ hg cat -r tip bar ../quux
1324 $TESTTMP/subprocesscwd
1326 $TESTTMP/subprocesscwd
1325 quux
1327 quux
1326 $ cat bar ../quux
1328 $ cat bar ../quux
1327 $TESTTMP/subprocesscwd
1329 $TESTTMP/subprocesscwd
1328 quux
1330 quux
1329 $ echo modified > bar
1331 $ echo modified > bar
1330 $ hg fix -w bar
1332 $ hg fix -w bar
1331 $ cat bar
1333 $ cat bar
1332 $TESTTMP/subprocesscwd
1334 $TESTTMP/subprocesscwd
1333
1335
1334 Apparently fixing p1() and its descendants doesn't include wdir() unless
1336 Apparently fixing p1() and its descendants doesn't include wdir() unless
1335 explicitly stated.
1337 explicitly stated.
1336
1338
1337 $ hg fix -r '.::'
1339 $ hg fix -r '.::'
1338 $ hg cat -r . ../quux
1340 $ hg cat -r . ../quux
1339 quux
1341 quux
1340 $ hg cat -r tip ../quux
1342 $ hg cat -r tip ../quux
1341 fs: $TESTTMP/subprocesscwd
1343 fs: $TESTTMP/subprocesscwd
1342 $ cat ../quux
1344 $ cat ../quux
1343 quux
1345 quux
1344
1346
1345 Clean files are not fixed unless explicitly named
1347 Clean files are not fixed unless explicitly named
1346 $ echo 'dirty' > ../quux
1348 $ echo 'dirty' > ../quux
1347
1349
1348 $ hg fix --working-dir
1350 $ hg fix --working-dir
1349 $ cat ../quux
1351 $ cat ../quux
1350 fs: $TESTTMP/subprocesscwd
1352 fs: $TESTTMP/subprocesscwd
1351
1353
1352 $ cd ../..
1354 $ cd ../..
1353
1355
1354 Tools configured without a pattern are ignored. It would be too dangerous to
1356 Tools configured without a pattern are ignored. It would be too dangerous to
1355 run them on all files, because this might happen while testing a configuration
1357 run them on all files, because this might happen while testing a configuration
1356 that also deletes all of the file content. There is no reasonable subset of the
1358 that also deletes all of the file content. There is no reasonable subset of the
1357 files to use as a default. Users should be explicit about what files are
1359 files to use as a default. Users should be explicit about what files are
1358 affected by a tool. This test also confirms that we don't crash when the
1360 affected by a tool. This test also confirms that we don't crash when the
1359 pattern config is missing, and that we only warn about it once.
1361 pattern config is missing, and that we only warn about it once.
1360
1362
1361 $ hg init nopatternconfigured
1363 $ hg init nopatternconfigured
1362 $ cd nopatternconfigured
1364 $ cd nopatternconfigured
1363
1365
1364 $ printf "foo" > foo
1366 $ printf "foo" > foo
1365 $ printf "bar" > bar
1367 $ printf "bar" > bar
1366 $ hg add -q
1368 $ hg add -q
1367 $ hg fix --debug --working-dir --config "fix.nopattern:command=echo fixed"
1369 $ hg fix --debug --working-dir --config "fix.nopattern:command=echo fixed"
1368 fixer tool has no pattern configuration: nopattern
1370 fixer tool has no pattern configuration: nopattern
1369 $ cat foo bar
1371 $ cat foo bar
1370 foobar (no-eol)
1372 foobar (no-eol)
1371 $ hg fix --debug --working-dir --config "fix.nocommand:pattern=foo.bar"
1373 $ hg fix --debug --working-dir --config "fix.nocommand:pattern=foo.bar"
1372 fixer tool has no command configuration: nocommand
1374 fixer tool has no command configuration: nocommand
1373
1375
1374 $ cd ..
1376 $ cd ..
1375
1377
1376 Tools can be disabled. Disabled tools do nothing but print a debug message.
1378 Tools can be disabled. Disabled tools do nothing but print a debug message.
1377
1379
1378 $ hg init disabled
1380 $ hg init disabled
1379 $ cd disabled
1381 $ cd disabled
1380
1382
1381 $ printf "foo\n" > foo
1383 $ printf "foo\n" > foo
1382 $ hg add -q
1384 $ hg add -q
1383 $ hg fix --debug --working-dir --config "fix.disabled:command=echo fixed" \
1385 $ hg fix --debug --working-dir --config "fix.disabled:command=echo fixed" \
1384 > --config "fix.disabled:pattern=foo" \
1386 > --config "fix.disabled:pattern=foo" \
1385 > --config "fix.disabled:enabled=false"
1387 > --config "fix.disabled:enabled=false"
1386 ignoring disabled fixer tool: disabled
1388 ignoring disabled fixer tool: disabled
1387 $ cat foo
1389 $ cat foo
1388 foo
1390 foo
1389
1391
1390 $ cd ..
1392 $ cd ..
1391
1393
1392 Test that we can configure a fixer to affect all files regardless of the cwd.
1394 Test that we can configure a fixer to affect all files regardless of the cwd.
1393 The way we invoke matching must not prohibit this.
1395 The way we invoke matching must not prohibit this.
1394
1396
1395 $ hg init affectallfiles
1397 $ hg init affectallfiles
1396 $ cd affectallfiles
1398 $ cd affectallfiles
1397
1399
1398 $ mkdir foo bar
1400 $ mkdir foo bar
1399 $ printf "foo" > foo/file
1401 $ printf "foo" > foo/file
1400 $ printf "bar" > bar/file
1402 $ printf "bar" > bar/file
1401 $ printf "baz" > baz_file
1403 $ printf "baz" > baz_file
1402 $ hg add -q
1404 $ hg add -q
1403
1405
1404 $ cd bar
1406 $ cd bar
1405 $ hg fix --working-dir --config "fix.cooltool:command=echo fixed" \
1407 $ hg fix --working-dir --config "fix.cooltool:command=echo fixed" \
1406 > --config "fix.cooltool:pattern=glob:**"
1408 > --config "fix.cooltool:pattern=glob:**"
1407 $ cd ..
1409 $ cd ..
1408
1410
1409 $ cat foo/file
1411 $ cat foo/file
1410 fixed
1412 fixed
1411 $ cat bar/file
1413 $ cat bar/file
1412 fixed
1414 fixed
1413 $ cat baz_file
1415 $ cat baz_file
1414 fixed
1416 fixed
1415
1417
1416 $ cd ..
1418 $ cd ..
1417
1419
1418 Tools should be able to run on unchanged files, even if they set :linerange.
1420 Tools should be able to run on unchanged files, even if they set :linerange.
1419 This includes a corner case where deleted chunks of a file are not considered
1421 This includes a corner case where deleted chunks of a file are not considered
1420 changes.
1422 changes.
1421
1423
1422 $ hg init skipclean
1424 $ hg init skipclean
1423 $ cd skipclean
1425 $ cd skipclean
1424
1426
1425 $ printf "a\nb\nc\n" > foo
1427 $ printf "a\nb\nc\n" > foo
1426 $ printf "a\nb\nc\n" > bar
1428 $ printf "a\nb\nc\n" > bar
1427 $ printf "a\nb\nc\n" > baz
1429 $ printf "a\nb\nc\n" > baz
1428 $ hg commit -Aqm "base"
1430 $ hg commit -Aqm "base"
1429
1431
1430 $ printf "a\nc\n" > foo
1432 $ printf "a\nc\n" > foo
1431 $ printf "a\nx\nc\n" > baz
1433 $ printf "a\nx\nc\n" > baz
1432
1434
1433 $ cat >> print.py <<EOF
1435 $ cat >> print.py <<EOF
1434 > import sys
1436 > import sys
1435 > for a in sys.argv[1:]:
1437 > for a in sys.argv[1:]:
1436 > print(a)
1438 > print(a)
1437 > EOF
1439 > EOF
1438
1440
1439 $ hg fix --working-dir foo bar baz \
1441 $ hg fix --working-dir foo bar baz \
1440 > --config "fix.changedlines:command=\"$PYTHON\" print.py \"Line ranges:\"" \
1442 > --config "fix.changedlines:command=\"$PYTHON\" print.py \"Line ranges:\"" \
1441 > --config 'fix.changedlines:linerange="{first} through {last}"' \
1443 > --config 'fix.changedlines:linerange="{first} through {last}"' \
1442 > --config 'fix.changedlines:pattern=glob:**' \
1444 > --config 'fix.changedlines:pattern=glob:**' \
1443 > --config 'fix.changedlines:skipclean=false'
1445 > --config 'fix.changedlines:skipclean=false'
1444
1446
1445 $ cat foo
1447 $ cat foo
1446 Line ranges:
1448 Line ranges:
1447 $ cat bar
1449 $ cat bar
1448 Line ranges:
1450 Line ranges:
1449 $ cat baz
1451 $ cat baz
1450 Line ranges:
1452 Line ranges:
1451 2 through 2
1453 2 through 2
1452
1454
1453 $ cd ..
1455 $ cd ..
1454
1456
1455 Test various cases around merges. We were previously dropping files if they were
1457 Test various cases around merges. We were previously dropping files if they were
1456 created on only the p2 side of the merge, so let's test permutations of:
1458 created on only the p2 side of the merge, so let's test permutations of:
1457 * added, was fixed
1459 * added, was fixed
1458 * added, considered for fixing but was already good
1460 * added, considered for fixing but was already good
1459 * added, not considered for fixing
1461 * added, not considered for fixing
1460 * modified, was fixed
1462 * modified, was fixed
1461 * modified, considered for fixing but was already good
1463 * modified, considered for fixing but was already good
1462 * modified, not considered for fixing
1464 * modified, not considered for fixing
1463
1465
1464 Before the bug was fixed where we would drop files, this test demonstrated the
1466 Before the bug was fixed where we would drop files, this test demonstrated the
1465 following issues:
1467 following issues:
1466 * new_in_r1.ignored, new_in_r1_already_good.changed, and
1468 * new_in_r1.ignored, new_in_r1_already_good.changed, and
1467 > mod_in_r1_already_good.changed were NOT in the manifest for the merge commit
1469 > mod_in_r1_already_good.changed were NOT in the manifest for the merge commit
1468 * mod_in_r1.ignored had its contents from r0, NOT r1.
1470 * mod_in_r1.ignored had its contents from r0, NOT r1.
1469
1471
1470 We're also setting a named branch for every commit to demonstrate that the
1472 We're also setting a named branch for every commit to demonstrate that the
1471 branch is kept intact and there aren't issues updating to another branch in the
1473 branch is kept intact and there aren't issues updating to another branch in the
1472 middle of fix.
1474 middle of fix.
1473
1475
1474 $ hg init merge_keeps_files
1476 $ hg init merge_keeps_files
1475 $ cd merge_keeps_files
1477 $ cd merge_keeps_files
1476 $ for f in r0 mod_in_r1 mod_in_r2 mod_in_merge mod_in_child; do
1478 $ for f in r0 mod_in_r1 mod_in_r2 mod_in_merge mod_in_child; do
1477 > for c in changed whole ignored; do
1479 > for c in changed whole ignored; do
1478 > printf "hello\n" > $f.$c
1480 > printf "hello\n" > $f.$c
1479 > done
1481 > done
1480 > printf "HELLO\n" > "mod_in_${f}_already_good.changed"
1482 > printf "HELLO\n" > "mod_in_${f}_already_good.changed"
1481 > done
1483 > done
1482 $ hg branch -q r0
1484 $ hg branch -q r0
1483 $ hg ci -Aqm 'r0'
1485 $ hg ci -Aqm 'r0'
1484 $ hg phase -p
1486 $ hg phase -p
1485 $ make_test_files() {
1487 $ make_test_files() {
1486 > printf "world\n" >> "mod_in_$1.changed"
1488 > printf "world\n" >> "mod_in_$1.changed"
1487 > printf "world\n" >> "mod_in_$1.whole"
1489 > printf "world\n" >> "mod_in_$1.whole"
1488 > printf "world\n" >> "mod_in_$1.ignored"
1490 > printf "world\n" >> "mod_in_$1.ignored"
1489 > printf "WORLD\n" >> "mod_in_$1_already_good.changed"
1491 > printf "WORLD\n" >> "mod_in_$1_already_good.changed"
1490 > printf "new in $1\n" > "new_in_$1.changed"
1492 > printf "new in $1\n" > "new_in_$1.changed"
1491 > printf "new in $1\n" > "new_in_$1.whole"
1493 > printf "new in $1\n" > "new_in_$1.whole"
1492 > printf "new in $1\n" > "new_in_$1.ignored"
1494 > printf "new in $1\n" > "new_in_$1.ignored"
1493 > printf "ALREADY GOOD, NEW IN THIS REV\n" > "new_in_$1_already_good.changed"
1495 > printf "ALREADY GOOD, NEW IN THIS REV\n" > "new_in_$1_already_good.changed"
1494 > }
1496 > }
1495 $ make_test_commit() {
1497 $ make_test_commit() {
1496 > make_test_files "$1"
1498 > make_test_files "$1"
1497 > hg branch -q "$1"
1499 > hg branch -q "$1"
1498 > hg ci -Aqm "$2"
1500 > hg ci -Aqm "$2"
1499 > }
1501 > }
1500 $ make_test_commit r1 "merge me, pt1"
1502 $ make_test_commit r1 "merge me, pt1"
1501 $ hg co -q ".^"
1503 $ hg co -q ".^"
1502 $ make_test_commit r2 "merge me, pt2"
1504 $ make_test_commit r2 "merge me, pt2"
1503 $ hg merge -qr 1
1505 $ hg merge -qr 1
1504 $ make_test_commit merge "evil merge"
1506 $ make_test_commit merge "evil merge"
1505 $ make_test_commit child "child of merge"
1507 $ make_test_commit child "child of merge"
1506 $ make_test_files wdir
1508 $ make_test_files wdir
1507 $ hg fix -r 'not public()' -w
1509 $ hg fix -r 'not public()' -w
1508 $ hg log -G -T'{rev}:{shortest(node,8)}: branch:{branch} desc:{desc}'
1510 $ hg log -G -T'{rev}:{shortest(node,8)}: branch:{branch} desc:{desc}'
1509 @ 8:c22ce900: branch:child desc:child of merge
1511 @ 8:c22ce900: branch:child desc:child of merge
1510 |
1512 |
1511 o 7:5a30615a: branch:merge desc:evil merge
1513 o 7:5a30615a: branch:merge desc:evil merge
1512 |\
1514 |\
1513 | o 6:4e5acdc4: branch:r2 desc:merge me, pt2
1515 | o 6:4e5acdc4: branch:r2 desc:merge me, pt2
1514 | |
1516 | |
1515 o | 5:eea01878: branch:r1 desc:merge me, pt1
1517 o | 5:eea01878: branch:r1 desc:merge me, pt1
1516 |/
1518 |/
1517 o 0:0c548d87: branch:r0 desc:r0
1519 o 0:0c548d87: branch:r0 desc:r0
1518
1520
1519 $ hg files -r tip
1521 $ hg files -r tip
1520 mod_in_child.changed
1522 mod_in_child.changed
1521 mod_in_child.ignored
1523 mod_in_child.ignored
1522 mod_in_child.whole
1524 mod_in_child.whole
1523 mod_in_child_already_good.changed
1525 mod_in_child_already_good.changed
1524 mod_in_merge.changed
1526 mod_in_merge.changed
1525 mod_in_merge.ignored
1527 mod_in_merge.ignored
1526 mod_in_merge.whole
1528 mod_in_merge.whole
1527 mod_in_merge_already_good.changed
1529 mod_in_merge_already_good.changed
1528 mod_in_mod_in_child_already_good.changed
1530 mod_in_mod_in_child_already_good.changed
1529 mod_in_mod_in_merge_already_good.changed
1531 mod_in_mod_in_merge_already_good.changed
1530 mod_in_mod_in_r1_already_good.changed
1532 mod_in_mod_in_r1_already_good.changed
1531 mod_in_mod_in_r2_already_good.changed
1533 mod_in_mod_in_r2_already_good.changed
1532 mod_in_r0_already_good.changed
1534 mod_in_r0_already_good.changed
1533 mod_in_r1.changed
1535 mod_in_r1.changed
1534 mod_in_r1.ignored
1536 mod_in_r1.ignored
1535 mod_in_r1.whole
1537 mod_in_r1.whole
1536 mod_in_r1_already_good.changed
1538 mod_in_r1_already_good.changed
1537 mod_in_r2.changed
1539 mod_in_r2.changed
1538 mod_in_r2.ignored
1540 mod_in_r2.ignored
1539 mod_in_r2.whole
1541 mod_in_r2.whole
1540 mod_in_r2_already_good.changed
1542 mod_in_r2_already_good.changed
1541 new_in_child.changed
1543 new_in_child.changed
1542 new_in_child.ignored
1544 new_in_child.ignored
1543 new_in_child.whole
1545 new_in_child.whole
1544 new_in_child_already_good.changed
1546 new_in_child_already_good.changed
1545 new_in_merge.changed
1547 new_in_merge.changed
1546 new_in_merge.ignored
1548 new_in_merge.ignored
1547 new_in_merge.whole
1549 new_in_merge.whole
1548 new_in_merge_already_good.changed
1550 new_in_merge_already_good.changed
1549 new_in_r1.changed
1551 new_in_r1.changed
1550 new_in_r1.ignored
1552 new_in_r1.ignored
1551 new_in_r1.whole
1553 new_in_r1.whole
1552 new_in_r1_already_good.changed
1554 new_in_r1_already_good.changed
1553 new_in_r2.changed
1555 new_in_r2.changed
1554 new_in_r2.ignored
1556 new_in_r2.ignored
1555 new_in_r2.whole
1557 new_in_r2.whole
1556 new_in_r2_already_good.changed
1558 new_in_r2_already_good.changed
1557 r0.changed
1559 r0.changed
1558 r0.ignored
1560 r0.ignored
1559 r0.whole
1561 r0.whole
1560 $ for f in "$(hg files -r tip)"; do hg cat -r tip $f -T'{path}:\n{data}\n'; done
1562 $ for f in "$(hg files -r tip)"; do hg cat -r tip $f -T'{path}:\n{data}\n'; done
1561 mod_in_child.changed:
1563 mod_in_child.changed:
1562 hello
1564 hello
1563 WORLD
1565 WORLD
1564
1566
1565 mod_in_child.ignored:
1567 mod_in_child.ignored:
1566 hello
1568 hello
1567 world
1569 world
1568
1570
1569 mod_in_child.whole:
1571 mod_in_child.whole:
1570 HELLO
1572 HELLO
1571 WORLD
1573 WORLD
1572
1574
1573 mod_in_child_already_good.changed:
1575 mod_in_child_already_good.changed:
1574 WORLD
1576 WORLD
1575
1577
1576 mod_in_merge.changed:
1578 mod_in_merge.changed:
1577 hello
1579 hello
1578 WORLD
1580 WORLD
1579
1581
1580 mod_in_merge.ignored:
1582 mod_in_merge.ignored:
1581 hello
1583 hello
1582 world
1584 world
1583
1585
1584 mod_in_merge.whole:
1586 mod_in_merge.whole:
1585 HELLO
1587 HELLO
1586 WORLD
1588 WORLD
1587
1589
1588 mod_in_merge_already_good.changed:
1590 mod_in_merge_already_good.changed:
1589 WORLD
1591 WORLD
1590
1592
1591 mod_in_mod_in_child_already_good.changed:
1593 mod_in_mod_in_child_already_good.changed:
1592 HELLO
1594 HELLO
1593
1595
1594 mod_in_mod_in_merge_already_good.changed:
1596 mod_in_mod_in_merge_already_good.changed:
1595 HELLO
1597 HELLO
1596
1598
1597 mod_in_mod_in_r1_already_good.changed:
1599 mod_in_mod_in_r1_already_good.changed:
1598 HELLO
1600 HELLO
1599
1601
1600 mod_in_mod_in_r2_already_good.changed:
1602 mod_in_mod_in_r2_already_good.changed:
1601 HELLO
1603 HELLO
1602
1604
1603 mod_in_r0_already_good.changed:
1605 mod_in_r0_already_good.changed:
1604 HELLO
1606 HELLO
1605
1607
1606 mod_in_r1.changed:
1608 mod_in_r1.changed:
1607 hello
1609 hello
1608 WORLD
1610 WORLD
1609
1611
1610 mod_in_r1.ignored:
1612 mod_in_r1.ignored:
1611 hello
1613 hello
1612 world
1614 world
1613
1615
1614 mod_in_r1.whole:
1616 mod_in_r1.whole:
1615 HELLO
1617 HELLO
1616 WORLD
1618 WORLD
1617
1619
1618 mod_in_r1_already_good.changed:
1620 mod_in_r1_already_good.changed:
1619 WORLD
1621 WORLD
1620
1622
1621 mod_in_r2.changed:
1623 mod_in_r2.changed:
1622 hello
1624 hello
1623 WORLD
1625 WORLD
1624
1626
1625 mod_in_r2.ignored:
1627 mod_in_r2.ignored:
1626 hello
1628 hello
1627 world
1629 world
1628
1630
1629 mod_in_r2.whole:
1631 mod_in_r2.whole:
1630 HELLO
1632 HELLO
1631 WORLD
1633 WORLD
1632
1634
1633 mod_in_r2_already_good.changed:
1635 mod_in_r2_already_good.changed:
1634 WORLD
1636 WORLD
1635
1637
1636 new_in_child.changed:
1638 new_in_child.changed:
1637 NEW IN CHILD
1639 NEW IN CHILD
1638
1640
1639 new_in_child.ignored:
1641 new_in_child.ignored:
1640 new in child
1642 new in child
1641
1643
1642 new_in_child.whole:
1644 new_in_child.whole:
1643 NEW IN CHILD
1645 NEW IN CHILD
1644
1646
1645 new_in_child_already_good.changed:
1647 new_in_child_already_good.changed:
1646 ALREADY GOOD, NEW IN THIS REV
1648 ALREADY GOOD, NEW IN THIS REV
1647
1649
1648 new_in_merge.changed:
1650 new_in_merge.changed:
1649 NEW IN MERGE
1651 NEW IN MERGE
1650
1652
1651 new_in_merge.ignored:
1653 new_in_merge.ignored:
1652 new in merge
1654 new in merge
1653
1655
1654 new_in_merge.whole:
1656 new_in_merge.whole:
1655 NEW IN MERGE
1657 NEW IN MERGE
1656
1658
1657 new_in_merge_already_good.changed:
1659 new_in_merge_already_good.changed:
1658 ALREADY GOOD, NEW IN THIS REV
1660 ALREADY GOOD, NEW IN THIS REV
1659
1661
1660 new_in_r1.changed:
1662 new_in_r1.changed:
1661 NEW IN R1
1663 NEW IN R1
1662
1664
1663 new_in_r1.ignored:
1665 new_in_r1.ignored:
1664 new in r1
1666 new in r1
1665
1667
1666 new_in_r1.whole:
1668 new_in_r1.whole:
1667 NEW IN R1
1669 NEW IN R1
1668
1670
1669 new_in_r1_already_good.changed:
1671 new_in_r1_already_good.changed:
1670 ALREADY GOOD, NEW IN THIS REV
1672 ALREADY GOOD, NEW IN THIS REV
1671
1673
1672 new_in_r2.changed:
1674 new_in_r2.changed:
1673 NEW IN R2
1675 NEW IN R2
1674
1676
1675 new_in_r2.ignored:
1677 new_in_r2.ignored:
1676 new in r2
1678 new in r2
1677
1679
1678 new_in_r2.whole:
1680 new_in_r2.whole:
1679 NEW IN R2
1681 NEW IN R2
1680
1682
1681 new_in_r2_already_good.changed:
1683 new_in_r2_already_good.changed:
1682 ALREADY GOOD, NEW IN THIS REV
1684 ALREADY GOOD, NEW IN THIS REV
1683
1685
1684 r0.changed:
1686 r0.changed:
1685 hello
1687 hello
1686
1688
1687 r0.ignored:
1689 r0.ignored:
1688 hello
1690 hello
1689
1691
1690 r0.whole:
1692 r0.whole:
1691 hello
1693 hello
1692
1694
General Comments 0
You need to be logged in to leave comments. Login now