Show More
@@ -80,6 +80,7 b' from mercurial.node import (' | |||||
80 | from mercurial import ( |
|
80 | from mercurial import ( | |
81 | archival, |
|
81 | archival, | |
82 | cmdutil, |
|
82 | cmdutil, | |
|
83 | encoding, | |||
83 | error, |
|
84 | error, | |
84 | filemerge, |
|
85 | filemerge, | |
85 | formatter, |
|
86 | formatter, | |
@@ -175,6 +176,65 b' def formatcmdline(cmdline, repo_root, do' | |||||
175 | cmdline += ' $parent1 $child' |
|
176 | cmdline += ' $parent1 $child' | |
176 | return re.sub(regex, quote, cmdline) |
|
177 | return re.sub(regex, quote, cmdline) | |
177 |
|
178 | |||
|
179 | def _runperfilediff(cmdline, repo_root, ui, do3way, confirm, | |||
|
180 | commonfiles, tmproot, dir1a, dir1b, | |||
|
181 | dir2root, dir2, | |||
|
182 | rev1a, rev1b, rev2): | |||
|
183 | # Note that we need to sort the list of files because it was | |||
|
184 | # built in an "unstable" way and it's annoying to get files in a | |||
|
185 | # random order, especially when "confirm" mode is enabled. | |||
|
186 | totalfiles = len(commonfiles) | |||
|
187 | for idx, commonfile in enumerate(sorted(commonfiles)): | |||
|
188 | path1a = os.path.join(tmproot, dir1a, commonfile) | |||
|
189 | label1a = commonfile + rev1a | |||
|
190 | if not os.path.isfile(path1a): | |||
|
191 | path1a = os.devnull | |||
|
192 | ||||
|
193 | path1b = '' | |||
|
194 | label1b = '' | |||
|
195 | if do3way: | |||
|
196 | path1b = os.path.join(tmproot, dir1b, commonfile) | |||
|
197 | label1b = commonfile + rev1b | |||
|
198 | if not os.path.isfile(path1b): | |||
|
199 | path1b = os.devnull | |||
|
200 | ||||
|
201 | path2 = os.path.join(dir2root, dir2, commonfile) | |||
|
202 | label2 = commonfile + rev2 | |||
|
203 | ||||
|
204 | if confirm: | |||
|
205 | # Prompt before showing this diff | |||
|
206 | difffiles = _('diff %s (%d of %d)') % (commonfile, idx + 1, | |||
|
207 | totalfiles) | |||
|
208 | responses = _('[Yns?]' | |||
|
209 | '$$ &Yes, show diff' | |||
|
210 | '$$ &No, skip this diff' | |||
|
211 | '$$ &Skip remaining diffs' | |||
|
212 | '$$ &? (display help)') | |||
|
213 | r = ui.promptchoice('%s %s' % (difffiles, responses)) | |||
|
214 | if r == 3: # ? | |||
|
215 | while r == 3: | |||
|
216 | for c, t in ui.extractchoices(responses)[1]: | |||
|
217 | ui.write('%s - %s\n' % (c, encoding.lower(t))) | |||
|
218 | r = ui.promptchoice('%s %s' % (difffiles, responses)) | |||
|
219 | if r == 0: # yes | |||
|
220 | pass | |||
|
221 | elif r == 1: # no | |||
|
222 | continue | |||
|
223 | elif r == 2: # skip | |||
|
224 | break | |||
|
225 | ||||
|
226 | curcmdline = formatcmdline( | |||
|
227 | cmdline, repo_root, do3way=do3way, | |||
|
228 | parent1=path1a, plabel1=label1a, | |||
|
229 | parent2=path1b, plabel2=label1b, | |||
|
230 | child=path2, clabel=label2) | |||
|
231 | ui.debug('running %r in %s\n' % (pycompat.bytestr(curcmdline), | |||
|
232 | tmproot)) | |||
|
233 | ||||
|
234 | # Run the comparison program and wait for it to exit | |||
|
235 | # before we show the next file. | |||
|
236 | ui.system(curcmdline, cwd=tmproot, blockedtag='extdiff') | |||
|
237 | ||||
178 | def dodiff(ui, repo, cmdline, pats, opts): |
|
238 | def dodiff(ui, repo, cmdline, pats, opts): | |
179 | '''Do the actual diff: |
|
239 | '''Do the actual diff: | |
180 |
|
240 | |||
@@ -201,6 +261,9 b' def dodiff(ui, repo, cmdline, pats, opts' | |||||
201 | else: |
|
261 | else: | |
202 | ctx1b = repo[nullid] |
|
262 | ctx1b = repo[nullid] | |
203 |
|
263 | |||
|
264 | perfile = opts.get('per_file') | |||
|
265 | confirm = opts.get('confirm') | |||
|
266 | ||||
204 | node1a = ctx1a.node() |
|
267 | node1a = ctx1a.node() | |
205 | node1b = ctx1b.node() |
|
268 | node1b = ctx1b.node() | |
206 | node2 = ctx2.node() |
|
269 | node2 = ctx2.node() | |
@@ -217,6 +280,8 b' def dodiff(ui, repo, cmdline, pats, opts' | |||||
217 | if opts.get('patch'): |
|
280 | if opts.get('patch'): | |
218 | if subrepos: |
|
281 | if subrepos: | |
219 | raise error.Abort(_('--patch cannot be used with --subrepos')) |
|
282 | raise error.Abort(_('--patch cannot be used with --subrepos')) | |
|
283 | if perfile: | |||
|
284 | raise error.Abort(_('--patch cannot be used with --per-file')) | |||
220 | if node2 is None: |
|
285 | if node2 is None: | |
221 | raise error.Abort(_('--patch requires two revisions')) |
|
286 | raise error.Abort(_('--patch requires two revisions')) | |
222 | else: |
|
287 | else: | |
@@ -304,15 +369,23 b' def dodiff(ui, repo, cmdline, pats, opts' | |||||
304 | label1b = None |
|
369 | label1b = None | |
305 | fnsandstat = [] |
|
370 | fnsandstat = [] | |
306 |
|
371 | |||
307 | # Run the external tool on the 2 temp directories or the patches |
|
372 | if not perfile: | |
308 | cmdline = formatcmdline( |
|
373 | # Run the external tool on the 2 temp directories or the patches | |
309 | cmdline, repo.root, do3way=do3way, |
|
374 | cmdline = formatcmdline( | |
310 | parent1=dir1a, plabel1=label1a, |
|
375 | cmdline, repo.root, do3way=do3way, | |
311 |
parent |
|
376 | parent1=dir1a, plabel1=label1a, | |
312 |
|
|
377 | parent2=dir1b, plabel2=label1b, | |
313 | ui.debug('running %r in %s\n' % (pycompat.bytestr(cmdline), |
|
378 | child=dir2, clabel=label2) | |
314 | tmproot)) |
|
379 | ui.debug('running %r in %s\n' % (pycompat.bytestr(cmdline), | |
315 | ui.system(cmdline, cwd=tmproot, blockedtag='extdiff') |
|
380 | tmproot)) | |
|
381 | ui.system(cmdline, cwd=tmproot, blockedtag='extdiff') | |||
|
382 | else: | |||
|
383 | # Run the external tool once for each pair of files | |||
|
384 | _runperfilediff( | |||
|
385 | cmdline, repo.root, ui, do3way=do3way, confirm=confirm, | |||
|
386 | commonfiles=common, tmproot=tmproot, dir1a=dir1a, dir1b=dir1b, | |||
|
387 | dir2root=dir2root, dir2=dir2, | |||
|
388 | rev1a=rev1a, rev1b=rev1b, rev2=rev2) | |||
316 |
|
389 | |||
317 | for copy_fn, working_fn, st in fnsandstat: |
|
390 | for copy_fn, working_fn, st in fnsandstat: | |
318 | cpstat = os.lstat(copy_fn) |
|
391 | cpstat = os.lstat(copy_fn) | |
@@ -340,6 +413,10 b' extdiffopts = [' | |||||
340 | _('pass option to comparison program'), _('OPT')), |
|
413 | _('pass option to comparison program'), _('OPT')), | |
341 | ('r', 'rev', [], _('revision'), _('REV')), |
|
414 | ('r', 'rev', [], _('revision'), _('REV')), | |
342 | ('c', 'change', '', _('change made by revision'), _('REV')), |
|
415 | ('c', 'change', '', _('change made by revision'), _('REV')), | |
|
416 | ('', 'per-file', False, | |||
|
417 | _('compare each file instead of revision snapshots')), | |||
|
418 | ('', 'confirm', False, | |||
|
419 | _('prompt user before each external program invocation')), | |||
343 | ('', 'patch', None, _('compare patches for two revisions')) |
|
420 | ('', 'patch', None, _('compare patches for two revisions')) | |
344 | ] + cmdutil.walkopts + cmdutil.subrepoopts |
|
421 | ] + cmdutil.walkopts + cmdutil.subrepoopts | |
345 |
|
422 | |||
@@ -357,15 +434,23 b' def extdiff(ui, repo, *pats, **opts):' | |||||
357 | default options "-Npru". |
|
434 | default options "-Npru". | |
358 |
|
435 | |||
359 | To select a different program, use the -p/--program option. The |
|
436 | To select a different program, use the -p/--program option. The | |
360 |
program will be passed the names of two directories to compare |
|
437 | program will be passed the names of two directories to compare, | |
361 | pass additional options to the program, use -o/--option. These |
|
438 | unless the --per-file option is specified (see below). To pass | |
362 | will be passed before the names of the directories to compare. |
|
439 | additional options to the program, use -o/--option. These will be | |
|
440 | passed before the names of the directories or files to compare. | |||
363 |
|
441 | |||
364 | When two revision arguments are given, then changes are shown |
|
442 | When two revision arguments are given, then changes are shown | |
365 | between those revisions. If only one revision is specified then |
|
443 | between those revisions. If only one revision is specified then | |
366 | that revision is compared to the working directory, and, when no |
|
444 | that revision is compared to the working directory, and, when no | |
367 | revisions are specified, the working directory files are compared |
|
445 | revisions are specified, the working directory files are compared | |
368 |
to its parent. |
|
446 | to its parent. | |
|
447 | ||||
|
448 | The --per-file option runs the external program repeatedly on each | |||
|
449 | file to diff, instead of once on two directories. | |||
|
450 | ||||
|
451 | The --confirm option will prompt the user before each invocation of | |||
|
452 | the external program. It is ignored if --per-file isn't specified. | |||
|
453 | ''' | |||
369 | opts = pycompat.byteskwargs(opts) |
|
454 | opts = pycompat.byteskwargs(opts) | |
370 | program = opts.get('program') |
|
455 | program = opts.get('program') | |
371 | option = opts.get('option') |
|
456 | option = opts.get('option') |
@@ -48,6 +48,8 b' Should diff cloned directories:' | |||||
48 | -o --option OPT [+] pass option to comparison program |
|
48 | -o --option OPT [+] pass option to comparison program | |
49 | -r --rev REV [+] revision |
|
49 | -r --rev REV [+] revision | |
50 | -c --change REV change made by revision |
|
50 | -c --change REV change made by revision | |
|
51 | --per-file compare each file instead of revision snapshots | |||
|
52 | --confirm prompt user before each external program invocation | |||
51 | --patch compare patches for two revisions |
|
53 | --patch compare patches for two revisions | |
52 | -I --include PATTERN [+] include names matching the given patterns |
|
54 | -I --include PATTERN [+] include names matching the given patterns | |
53 | -X --exclude PATTERN [+] exclude names matching the given patterns |
|
55 | -X --exclude PATTERN [+] exclude names matching the given patterns | |
@@ -128,6 +130,40 b' issue3153: ensure using extdiff with rem' | |||||
128 | diffing a.398e36faf9c6 a.5ab95fb166c4 |
|
130 | diffing a.398e36faf9c6 a.5ab95fb166c4 | |
129 | [1] |
|
131 | [1] | |
130 |
|
132 | |||
|
133 | Test --per-file option: | |||
|
134 | ||||
|
135 | $ hg up -q -C 3 | |||
|
136 | $ echo a2 > a | |||
|
137 | $ echo b2 > b | |||
|
138 | $ hg ci -d '3 0' -mtestmode1 | |||
|
139 | created new head | |||
|
140 | $ hg falabala -c 6 --per-file | |||
|
141 | diffing "*\\extdiff.*\\a.46c0e4daeb72\\a" "a.81906f2b98ac\\a" (glob) (windows !) | |||
|
142 | diffing */extdiff.*/a.46c0e4daeb72/a a.81906f2b98ac/a (glob) (no-windows !) | |||
|
143 | diffing "*\\extdiff.*\\a.46c0e4daeb72\\b" "a.81906f2b98ac\\b" (glob) (windows !) | |||
|
144 | diffing */extdiff.*/a.46c0e4daeb72/b a.81906f2b98ac/b (glob) (no-windows !) | |||
|
145 | [1] | |||
|
146 | ||||
|
147 | Test --per-file and --confirm options: | |||
|
148 | ||||
|
149 | $ hg --config ui.interactive=True falabala -c 6 --per-file --confirm <<EOF | |||
|
150 | > n | |||
|
151 | > y | |||
|
152 | > EOF | |||
|
153 | diff a (1 of 2) [Yns?] n | |||
|
154 | diff b (2 of 2) [Yns?] y | |||
|
155 | diffing "*\\extdiff.*\\a.46c0e4daeb72\\b" "a.81906f2b98ac\\b" (glob) (windows !) | |||
|
156 | diffing */extdiff.*/a.46c0e4daeb72/b a.81906f2b98ac/b (glob) (no-windows !) | |||
|
157 | [1] | |||
|
158 | ||||
|
159 | Test --per-file and --confirm options with skipping: | |||
|
160 | ||||
|
161 | $ hg --config ui.interactive=True falabala -c 6 --per-file --confirm <<EOF | |||
|
162 | > s | |||
|
163 | > EOF | |||
|
164 | diff a (1 of 2) [Yns?] s | |||
|
165 | [1] | |||
|
166 | ||||
131 | issue4463: usage of command line configuration without additional quoting |
|
167 | issue4463: usage of command line configuration without additional quoting | |
132 |
|
168 | |||
133 | $ cat <<EOF >> $HGRCPATH |
|
169 | $ cat <<EOF >> $HGRCPATH |
@@ -805,15 +805,22 b' Extension module help vs command help:' | |||||
805 | "-Npru". |
|
805 | "-Npru". | |
806 |
|
806 | |||
807 | To select a different program, use the -p/--program option. The program |
|
807 | To select a different program, use the -p/--program option. The program | |
808 |
will be passed the names of two directories to compare |
|
808 | will be passed the names of two directories to compare, unless the --per- | |
809 | options to the program, use -o/--option. These will be passed before the |
|
809 | file option is specified (see below). To pass additional options to the | |
810 | names of the directories to compare. |
|
810 | program, use -o/--option. These will be passed before the names of the | |
|
811 | directories or files to compare. | |||
811 |
|
812 | |||
812 | When two revision arguments are given, then changes are shown between |
|
813 | When two revision arguments are given, then changes are shown between | |
813 | those revisions. If only one revision is specified then that revision is |
|
814 | those revisions. If only one revision is specified then that revision is | |
814 | compared to the working directory, and, when no revisions are specified, |
|
815 | compared to the working directory, and, when no revisions are specified, | |
815 | the working directory files are compared to its parent. |
|
816 | the working directory files are compared to its parent. | |
816 |
|
817 | |||
|
818 | The --per-file option runs the external program repeatedly on each file to | |||
|
819 | diff, instead of once on two directories. | |||
|
820 | ||||
|
821 | The --confirm option will prompt the user before each invocation of the | |||
|
822 | external program. It is ignored if --per-file isn't specified. | |||
|
823 | ||||
817 |
(use ' |
|
824 | (use 'hg help -e extdiff' to show help for the extdiff extension) | |
818 |
|
825 | |||
819 | options ([+] can be repeated): |
|
826 | options ([+] can be repeated): | |
@@ -822,6 +829,8 b' Extension module help vs command help:' | |||||
822 | -o --option OPT [+] pass option to comparison program |
|
829 | -o --option OPT [+] pass option to comparison program | |
823 | -r --rev REV [+] revision |
|
830 | -r --rev REV [+] revision | |
824 | -c --change REV change made by revision |
|
831 | -c --change REV change made by revision | |
|
832 | --per-file compare each file instead of revision snapshots | |||
|
833 | --confirm prompt user before each external program invocation | |||
825 | --patch compare patches for two revisions |
|
834 | --patch compare patches for two revisions | |
826 | -I --include PATTERN [+] include names matching the given patterns |
|
835 | -I --include PATTERN [+] include names matching the given patterns | |
827 | -X --exclude PATTERN [+] exclude names matching the given patterns |
|
836 | -X --exclude PATTERN [+] exclude names matching the given patterns |
General Comments 0
You need to be logged in to leave comments.
Login now