##// END OF EJS Templates
extdiff: avoid unexpected quoting arguments for external tools (issue4463)...
FUJIWARA Katsunori -
r23680:4075f2f8 default
parent child Browse files
Show More
@@ -1,330 +1,337 b''
1 1 # extdiff.py - external diff program support for mercurial
2 2 #
3 3 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 '''command to allow external programs to compare revisions
9 9
10 10 The extdiff Mercurial extension allows you to use external programs
11 11 to compare revisions, or revision with working directory. The external
12 12 diff programs are called with a configurable set of options and two
13 13 non-option arguments: paths to directories containing snapshots of
14 14 files to compare.
15 15
16 16 The extdiff extension also allows you to configure new diff commands, so
17 17 you do not need to type :hg:`extdiff -p kdiff3` always. ::
18 18
19 19 [extdiff]
20 20 # add new command that runs GNU diff(1) in 'context diff' mode
21 21 cdiff = gdiff -Nprc5
22 22 ## or the old way:
23 23 #cmd.cdiff = gdiff
24 24 #opts.cdiff = -Nprc5
25 25
26 26 # add new command called meld, runs meld (no need to name twice). If
27 27 # the meld executable is not available, the meld tool in [merge-tools]
28 28 # will be used, if available
29 29 meld =
30 30
31 31 # add new command called vimdiff, runs gvimdiff with DirDiff plugin
32 32 # (see http://www.vim.org/scripts/script.php?script_id=102) Non
33 33 # English user, be sure to put "let g:DirDiffDynamicDiffText = 1" in
34 34 # your .vimrc
35 35 vimdiff = gvim -f "+next" \\
36 36 "+execute 'DirDiff' fnameescape(argv(0)) fnameescape(argv(1))"
37 37
38 38 Tool arguments can include variables that are expanded at runtime::
39 39
40 40 $parent1, $plabel1 - filename, descriptive label of first parent
41 41 $child, $clabel - filename, descriptive label of child revision
42 42 $parent2, $plabel2 - filename, descriptive label of second parent
43 43 $root - repository root
44 44 $parent is an alias for $parent1.
45 45
46 46 The extdiff extension will look in your [diff-tools] and [merge-tools]
47 47 sections for diff tool arguments, when none are specified in [extdiff].
48 48
49 49 ::
50 50
51 51 [extdiff]
52 52 kdiff3 =
53 53
54 54 [diff-tools]
55 55 kdiff3.diffargs=--L1 '$plabel1' --L2 '$clabel' $parent $child
56 56
57 57 You can use -I/-X and list of file or directory names like normal
58 58 :hg:`diff` command. The extdiff extension makes snapshots of only
59 59 needed files, so running the external diff program will actually be
60 60 pretty fast (at least faster than having to compare the entire tree).
61 61 '''
62 62
63 63 from mercurial.i18n import _
64 64 from mercurial.node import short, nullid
65 65 from mercurial import cmdutil, scmutil, util, commands, encoding, filemerge
66 66 import os, shlex, shutil, tempfile, re
67 67
68 68 cmdtable = {}
69 69 command = cmdutil.command(cmdtable)
70 70 testedwith = 'internal'
71 71
72 72 def snapshot(ui, repo, files, node, tmproot):
73 73 '''snapshot files as of some revision
74 74 if not using snapshot, -I/-X does not work and recursive diff
75 75 in tools like kdiff3 and meld displays too many files.'''
76 76 dirname = os.path.basename(repo.root)
77 77 if dirname == "":
78 78 dirname = "root"
79 79 if node is not None:
80 80 dirname = '%s.%s' % (dirname, short(node))
81 81 base = os.path.join(tmproot, dirname)
82 82 os.mkdir(base)
83 83 if node is not None:
84 84 ui.note(_('making snapshot of %d files from rev %s\n') %
85 85 (len(files), short(node)))
86 86 else:
87 87 ui.note(_('making snapshot of %d files from working directory\n') %
88 88 (len(files)))
89 89 wopener = scmutil.opener(base)
90 90 fns_and_mtime = []
91 91 ctx = repo[node]
92 92 for fn in sorted(files):
93 93 wfn = util.pconvert(fn)
94 94 if wfn not in ctx:
95 95 # File doesn't exist; could be a bogus modify
96 96 continue
97 97 ui.note(' %s\n' % wfn)
98 98 dest = os.path.join(base, wfn)
99 99 fctx = ctx[wfn]
100 100 data = repo.wwritedata(wfn, fctx.data())
101 101 if 'l' in fctx.flags():
102 102 wopener.symlink(data, wfn)
103 103 else:
104 104 wopener.write(wfn, data)
105 105 if 'x' in fctx.flags():
106 106 util.setflags(dest, False, True)
107 107 if node is None:
108 108 fns_and_mtime.append((dest, repo.wjoin(fn),
109 109 os.lstat(dest).st_mtime))
110 110 return dirname, fns_and_mtime
111 111
112 def dodiff(ui, repo, diffcmd, diffopts, pats, opts):
112 def dodiff(ui, repo, args, pats, opts):
113 113 '''Do the actual diff:
114 114
115 115 - copy to a temp structure if diffing 2 internal revisions
116 116 - copy to a temp structure if diffing working revision with
117 117 another one and more than 1 file is changed
118 118 - just invoke the diff for a single file in the working dir
119 119 '''
120 120
121 121 revs = opts.get('rev')
122 122 change = opts.get('change')
123 args = ' '.join(map(util.shellquote, diffopts))
124 123 do3way = '$parent2' in args
125 124
126 125 if revs and change:
127 126 msg = _('cannot specify --rev and --change at the same time')
128 127 raise util.Abort(msg)
129 128 elif change:
130 129 node2 = scmutil.revsingle(repo, change, None).node()
131 130 node1a, node1b = repo.changelog.parents(node2)
132 131 else:
133 132 node1a, node2 = scmutil.revpair(repo, revs)
134 133 if not revs:
135 134 node1b = repo.dirstate.p2()
136 135 else:
137 136 node1b = nullid
138 137
139 138 # Disable 3-way merge if there is only one parent
140 139 if do3way:
141 140 if node1b == nullid:
142 141 do3way = False
143 142
144 143 matcher = scmutil.match(repo[node2], pats, opts)
145 144 mod_a, add_a, rem_a = map(set, repo.status(node1a, node2, matcher)[:3])
146 145 if do3way:
147 146 mod_b, add_b, rem_b = map(set, repo.status(node1b, node2, matcher)[:3])
148 147 else:
149 148 mod_b, add_b, rem_b = set(), set(), set()
150 149 modadd = mod_a | add_a | mod_b | add_b
151 150 common = modadd | rem_a | rem_b
152 151 if not common:
153 152 return 0
154 153
155 154 tmproot = tempfile.mkdtemp(prefix='extdiff.')
156 155 try:
157 156 # Always make a copy of node1a (and node1b, if applicable)
158 157 dir1a_files = mod_a | rem_a | ((mod_b | add_b) - add_a)
159 158 dir1a = snapshot(ui, repo, dir1a_files, node1a, tmproot)[0]
160 159 rev1a = '@%d' % repo[node1a].rev()
161 160 if do3way:
162 161 dir1b_files = mod_b | rem_b | ((mod_a | add_a) - add_b)
163 162 dir1b = snapshot(ui, repo, dir1b_files, node1b, tmproot)[0]
164 163 rev1b = '@%d' % repo[node1b].rev()
165 164 else:
166 165 dir1b = None
167 166 rev1b = ''
168 167
169 168 fns_and_mtime = []
170 169
171 170 # If node2 in not the wc or there is >1 change, copy it
172 171 dir2root = ''
173 172 rev2 = ''
174 173 if node2:
175 174 dir2 = snapshot(ui, repo, modadd, node2, tmproot)[0]
176 175 rev2 = '@%d' % repo[node2].rev()
177 176 elif len(common) > 1:
178 177 #we only actually need to get the files to copy back to
179 178 #the working dir in this case (because the other cases
180 179 #are: diffing 2 revisions or single file -- in which case
181 180 #the file is already directly passed to the diff tool).
182 181 dir2, fns_and_mtime = snapshot(ui, repo, modadd, None, tmproot)
183 182 else:
184 183 # This lets the diff tool open the changed file directly
185 184 dir2 = ''
186 185 dir2root = repo.root
187 186
188 187 label1a = rev1a
189 188 label1b = rev1b
190 189 label2 = rev2
191 190
192 191 # If only one change, diff the files instead of the directories
193 192 # Handle bogus modifies correctly by checking if the files exist
194 193 if len(common) == 1:
195 194 common_file = util.localpath(common.pop())
196 195 dir1a = os.path.join(tmproot, dir1a, common_file)
197 196 label1a = common_file + rev1a
198 197 if not os.path.isfile(dir1a):
199 198 dir1a = os.devnull
200 199 if do3way:
201 200 dir1b = os.path.join(tmproot, dir1b, common_file)
202 201 label1b = common_file + rev1b
203 202 if not os.path.isfile(dir1b):
204 203 dir1b = os.devnull
205 204 dir2 = os.path.join(dir2root, dir2, common_file)
206 205 label2 = common_file + rev2
207 206
208 207 # Function to quote file/dir names in the argument string.
209 208 # When not operating in 3-way mode, an empty string is
210 209 # returned for parent2
211 210 replace = {'parent': dir1a, 'parent1': dir1a, 'parent2': dir1b,
212 211 'plabel1': label1a, 'plabel2': label1b,
213 212 'clabel': label2, 'child': dir2,
214 213 'root': repo.root}
215 214 def quote(match):
216 215 key = match.group()[1:]
217 216 if not do3way and key == 'parent2':
218 217 return ''
219 218 return util.shellquote(replace[key])
220 219
221 220 # Match parent2 first, so 'parent1?' will match both parent1 and parent
222 221 regex = '\$(parent2|parent1?|child|plabel1|plabel2|clabel|root)'
223 222 if not do3way and not re.search(regex, args):
224 223 args += ' $parent1 $child'
225 args = re.sub(regex, quote, args)
226 cmdline = util.shellquote(diffcmd) + ' ' + args
224 cmdline = re.sub(regex, quote, args)
227 225
228 226 ui.debug('running %r in %s\n' % (cmdline, tmproot))
229 227 ui.system(cmdline, cwd=tmproot)
230 228
231 229 for copy_fn, working_fn, mtime in fns_and_mtime:
232 230 if os.lstat(copy_fn).st_mtime != mtime:
233 231 ui.debug('file changed while diffing. '
234 232 'Overwriting: %s (src: %s)\n' % (working_fn, copy_fn))
235 233 util.copyfile(copy_fn, working_fn)
236 234
237 235 return 1
238 236 finally:
239 237 ui.note(_('cleaning up temp directory\n'))
240 238 shutil.rmtree(tmproot)
241 239
242 240 @command('extdiff',
243 241 [('p', 'program', '',
244 242 _('comparison program to run'), _('CMD')),
245 243 ('o', 'option', [],
246 244 _('pass option to comparison program'), _('OPT')),
247 245 ('r', 'rev', [], _('revision'), _('REV')),
248 246 ('c', 'change', '', _('change made by revision'), _('REV')),
249 247 ] + commands.walkopts,
250 248 _('hg extdiff [OPT]... [FILE]...'),
251 249 inferrepo=True)
252 250 def extdiff(ui, repo, *pats, **opts):
253 251 '''use external program to diff repository (or selected files)
254 252
255 253 Show differences between revisions for the specified files, using
256 254 an external program. The default program used is diff, with
257 255 default options "-Npru".
258 256
259 257 To select a different program, use the -p/--program option. The
260 258 program will be passed the names of two directories to compare. To
261 259 pass additional options to the program, use -o/--option. These
262 260 will be passed before the names of the directories to compare.
263 261
264 262 When two revision arguments are given, then changes are shown
265 263 between those revisions. If only one revision is specified then
266 264 that revision is compared to the working directory, and, when no
267 265 revisions are specified, the working directory files are compared
268 266 to its parent.'''
269 267 program = opts.get('program')
270 268 option = opts.get('option')
271 269 if not program:
272 270 program = 'diff'
273 271 option = option or ['-Npru']
274 return dodiff(ui, repo, program, option, pats, opts)
272 cmdline = ' '.join(map(util.shellquote, [program] + option))
273 return dodiff(ui, repo, cmdline, pats, opts)
275 274
276 275 def uisetup(ui):
277 276 for cmd, path in ui.configitems('extdiff'):
278 277 if cmd.startswith('cmd.'):
279 278 cmd = cmd[4:]
280 279 if not path:
281 280 path = util.findexe(cmd)
282 281 if path is None:
283 282 path = filemerge.findexternaltool(ui, cmd) or cmd
284 diffopts = shlex.split(ui.config('extdiff', 'opts.' + cmd, ''))
283 diffopts = ui.config('extdiff', 'opts.' + cmd, '')
284 cmdline = util.shellquote(path)
285 if diffopts:
286 cmdline += ' ' + diffopts
285 287 elif cmd.startswith('opts.'):
286 288 continue
287 289 else:
288 # command = path opts
289 290 if path:
290 diffopts = shlex.split(path)
291 path = diffopts.pop(0)
291 # case "cmd = path opts"
292 cmdline = path
293 diffopts = len(shlex.split(cmdline)) > 1
292 294 else:
293 path, diffopts = util.findexe(cmd), []
295 # case "cmd ="
296 path = util.findexe(cmd)
294 297 if path is None:
295 298 path = filemerge.findexternaltool(ui, cmd) or cmd
299 cmdline = util.shellquote(path)
300 diffopts = False
296 301 # look for diff arguments in [diff-tools] then [merge-tools]
297 if diffopts == []:
302 if not diffopts:
298 303 args = ui.config('diff-tools', cmd+'.diffargs') or \
299 304 ui.config('merge-tools', cmd+'.diffargs')
300 305 if args:
301 diffopts = shlex.split(args)
302 def save(cmd, path, diffopts):
306 cmdline += ' ' + args
307 def save(cmdline):
303 308 '''use closure to save diff command to use'''
304 309 def mydiff(ui, repo, *pats, **opts):
305 return dodiff(ui, repo, path, diffopts + opts['option'],
306 pats, opts)
310 options = ' '.join(map(util.shellquote, opts['option']))
311 if options:
312 options = ' ' + options
313 return dodiff(ui, repo, cmdline + options, pats, opts)
307 314 doc = _('''\
308 315 use %(path)s to diff repository (or selected files)
309 316
310 317 Show differences between revisions for the specified files, using
311 318 the %(path)s program.
312 319
313 320 When two revision arguments are given, then changes are shown
314 321 between those revisions. If only one revision is specified then
315 322 that revision is compared to the working directory, and, when no
316 323 revisions are specified, the working directory files are compared
317 324 to its parent.\
318 325 ''') % {'path': util.uirepr(path)}
319 326
320 327 # We must translate the docstring right away since it is
321 328 # used as a format string. The string will unfortunately
322 329 # be translated again in commands.helpcmd and this will
323 330 # fail when the docstring contains non-ASCII characters.
324 331 # Decoding the string to a Unicode string here (using the
325 332 # right encoding) prevents that.
326 333 mydiff.__doc__ = doc.decode(encoding.encoding)
327 334 return mydiff
328 cmdtable[cmd] = (save(cmd, path, diffopts),
335 cmdtable[cmd] = (save(cmdline),
329 336 cmdtable['extdiff'][1][1:],
330 337 _('hg %s [OPTION]... [FILE]...') % cmd)
@@ -1,236 +1,302 b''
1 1 $ echo "[extensions]" >> $HGRCPATH
2 2 $ echo "extdiff=" >> $HGRCPATH
3 3
4 4 $ hg init a
5 5 $ cd a
6 6 $ echo a > a
7 7 $ echo b > b
8 8 $ hg add
9 9 adding a
10 10 adding b
11 11
12 12 Should diff cloned directories:
13 13
14 14 $ hg extdiff -o -r $opt
15 15 Only in a: a
16 16 Only in a: b
17 17 [1]
18 18
19 19 $ cat <<EOF >> $HGRCPATH
20 20 > [extdiff]
21 21 > cmd.falabala = echo
22 22 > opts.falabala = diffing
23 23 > cmd.edspace = echo
24 24 > opts.edspace = "name <user@example.com>"
25 25 > EOF
26 26
27 27 $ hg falabala
28 28 diffing a.000000000000 a
29 29 [1]
30 30
31 31 $ hg help falabala
32 32 hg falabala [OPTION]... [FILE]...
33 33
34 34 use 'echo' to diff repository (or selected files)
35 35
36 36 Show differences between revisions for the specified files, using the
37 37 'echo' program.
38 38
39 39 When two revision arguments are given, then changes are shown between
40 40 those revisions. If only one revision is specified then that revision is
41 41 compared to the working directory, and, when no revisions are specified,
42 42 the working directory files are compared to its parent.
43 43
44 44 options ([+] can be repeated):
45 45
46 46 -o --option OPT [+] pass option to comparison program
47 47 -r --rev REV [+] revision
48 48 -c --change REV change made by revision
49 49 -I --include PATTERN [+] include names matching the given patterns
50 50 -X --exclude PATTERN [+] exclude names matching the given patterns
51 51
52 52 (some details hidden, use --verbose to show complete help)
53 53
54 54 $ hg ci -d '0 0' -mtest1
55 55
56 56 $ echo b >> a
57 57 $ hg ci -d '1 0' -mtest2
58 58
59 59 Should diff cloned files directly:
60 60
61 61 $ hg falabala -r 0:1
62 62 diffing */extdiff.*/a.8a5febb7f867/a a.34eed99112ab/a (glob)
63 63 [1]
64 64
65 65 Test diff during merge:
66 66
67 67 $ hg update -C 0
68 68 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
69 69 $ echo c >> c
70 70 $ hg add c
71 71 $ hg ci -m "new branch" -d '1 0'
72 72 created new head
73 73 $ hg merge 1
74 74 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
75 75 (branch merge, don't forget to commit)
76 76
77 77 Should diff cloned file against wc file:
78 78
79 79 $ hg falabala
80 80 diffing */extdiff.*/a.2a13a4d2da36/a */a/a (glob)
81 81 [1]
82 82
83 83
84 84 Test --change option:
85 85
86 86 $ hg ci -d '2 0' -mtest3
87 87 $ hg falabala -c 1
88 88 diffing */extdiff.*/a.8a5febb7f867/a a.34eed99112ab/a (glob)
89 89 [1]
90 90
91 91 Check diff are made from the first parent:
92 92
93 93 $ hg falabala -c 3 || echo "diff-like tools yield a non-zero exit code"
94 94 diffing */extdiff.*/a.2a13a4d2da36/a a.46c0e4daeb72/a (glob)
95 95 diff-like tools yield a non-zero exit code
96 96
97 issue4463: usage of command line configuration without additional quoting
98
99 $ cat <<EOF >> $HGRCPATH
100 > [extdiff]
101 > cmd.4463a = echo
102 > opts.4463a = a-naked 'single quoted' "double quoted"
103 > 4463b = echo b-naked 'single quoted' "double quoted"
104 > echo =
105 > EOF
106 $ hg update -q -C 0
107 $ echo a >> a
108 #if windows
109 $ hg --debug 4463a | grep '^running'
110 running '"echo" a-naked \'single quoted\' "double quoted" "*\\a" "*\\a"' in */extdiff.* (glob)
111 $ hg --debug 4463b | grep '^running'
112 running 'echo b-naked \'single quoted\' "double quoted" "*\\a" "*\\a"' in */extdiff.* (glob)
113 $ hg --debug echo | grep '^running'
114 running '"*echo*" "*\\a" "*\\a"' in */extdiff.* (glob)
115 #else
116 $ hg --debug 4463a | grep '^running'
117 running '\'echo\' a-naked \'single quoted\' "double quoted" \'*/a\' \'$TESTTMP/a/a\'' in */extdiff.* (glob)
118 $ hg --debug 4463b | grep '^running'
119 running 'echo b-naked \'single quoted\' "double quoted" \'*/a\' \'$TESTTMP/a/a\'' in */extdiff.* (glob)
120 $ hg --debug echo | grep '^running'
121 running "'*echo*' '*/a' '$TESTTMP/a/a'" in */extdiff.* (glob)
122 #endif
123
124 (getting options from other than extdiff section)
125
126 $ cat <<EOF >> $HGRCPATH
127 > [extdiff]
128 > # using diff-tools diffargs
129 > 4463b2 = echo
130 > # using merge-tools diffargs
131 > 4463b3 = echo
132 > # no diffargs
133 > 4463b4 = echo
134 > [diff-tools]
135 > 4463b2.diffargs = b2-naked 'single quoted' "double quoted"
136 > [merge-tools]
137 > 4463b3.diffargs = b3-naked 'single quoted' "double quoted"
138 > EOF
139 #if windows
140 $ hg --debug 4463b2 | grep '^running'
141 running 'echo b2-naked \'single quoted\' "double quoted" "*\\a" "*\\a"' in */extdiff.* (glob)
142 $ hg --debug 4463b3 | grep '^running'
143 running 'echo b3-naked \'single quoted\' "double quoted" "*\\a" "*\\a"' in */extdiff.* (glob)
144 $ hg --debug 4463b4 | grep '^running'
145 running 'echo "*\\a" "*\\a"' in */extdiff.* (glob)
146 $ hg --debug 4463b4 --option 'being quoted' | grep '^running'
147 running 'echo "being quoted" "*\\a" "*\\a"' in */extdiff.* (glob)
148 $ hg --debug extdiff -p echo --option 'being quoted' | grep '^running'
149 running '"echo" "being quoted" "*\\a" "*\\a"' in */extdiff.* (glob)
150 #else
151 $ hg --debug 4463b2 | grep '^running'
152 running 'echo b2-naked \'single quoted\' "double quoted" \'*/a\' \'$TESTTMP/a/a\'' in */extdiff.* (glob)
153 $ hg --debug 4463b3 | grep '^running'
154 running 'echo b3-naked \'single quoted\' "double quoted" \'*/a\' \'$TESTTMP/a/a\'' in */extdiff.* (glob)
155 $ hg --debug 4463b4 | grep '^running'
156 running "echo '*/a' '$TESTTMP/a/a'" in */extdiff.* (glob)
157 $ hg --debug 4463b4 --option 'being quoted' | grep '^running'
158 running "echo 'being quoted' '*/a' '$TESTTMP/a/a'" in */extdiff.* (glob)
159 $ hg --debug extdiff -p echo --option 'being quoted' | grep '^running'
160 running "'echo' 'being quoted' '*/a' '$TESTTMP/a/a'" in */extdiff.* (glob)
161 #endif
162
97 163 #if execbit
98 164
99 165 Test extdiff of multiple files in tmp dir:
100 166
101 167 $ hg update -C 0 > /dev/null
102 168 $ echo changed > a
103 169 $ echo changed > b
104 170 $ chmod +x b
105 171
106 172 Diff in working directory, before:
107 173
108 174 $ hg diff --git
109 175 diff --git a/a b/a
110 176 --- a/a
111 177 +++ b/a
112 178 @@ -1,1 +1,1 @@
113 179 -a
114 180 +changed
115 181 diff --git a/b b/b
116 182 old mode 100644
117 183 new mode 100755
118 184 --- a/b
119 185 +++ b/b
120 186 @@ -1,1 +1,1 @@
121 187 -b
122 188 +changed
123 189
124 190
125 191 Edit with extdiff -p:
126 192
127 193 Prepare custom diff/edit tool:
128 194
129 195 $ cat > 'diff tool.py' << EOT
130 196 > #!/usr/bin/env python
131 197 > import time
132 198 > time.sleep(1) # avoid unchanged-timestamp problems
133 199 > file('a/a', 'ab').write('edited\n')
134 200 > file('a/b', 'ab').write('edited\n')
135 201 > EOT
136 202
137 203 $ chmod +x 'diff tool.py'
138 204
139 205 will change to /tmp/extdiff.TMP and populate directories a.TMP and a
140 206 and start tool
141 207
142 208 $ hg extdiff -p "`pwd`/diff tool.py"
143 209 [1]
144 210
145 211 Diff in working directory, after:
146 212
147 213 $ hg diff --git
148 214 diff --git a/a b/a
149 215 --- a/a
150 216 +++ b/a
151 217 @@ -1,1 +1,2 @@
152 218 -a
153 219 +changed
154 220 +edited
155 221 diff --git a/b b/b
156 222 old mode 100644
157 223 new mode 100755
158 224 --- a/b
159 225 +++ b/b
160 226 @@ -1,1 +1,2 @@
161 227 -b
162 228 +changed
163 229 +edited
164 230
165 231 Test extdiff with --option:
166 232
167 233 $ hg extdiff -p echo -o this -c 1
168 234 this */extdiff.*/a.8a5febb7f867/a a.34eed99112ab/a (glob)
169 235 [1]
170 236
171 237 $ hg falabala -o this -c 1
172 238 diffing this */extdiff.*/a.8a5febb7f867/a a.34eed99112ab/a (glob)
173 239 [1]
174 240
175 241 Test extdiff's handling of options with spaces in them:
176 242
177 243 $ hg edspace -c 1
178 244 name <user@example.com> */extdiff.*/a.8a5febb7f867/a a.34eed99112ab/a (glob)
179 245 [1]
180 246
181 247 $ hg extdiff -p echo -o "name <user@example.com>" -c 1
182 248 name <user@example.com> */extdiff.*/a.8a5febb7f867/a a.34eed99112ab/a (glob)
183 249 [1]
184 250
185 251 Test with revsets:
186 252
187 253 $ hg extdif -p echo -c "rev(1)"
188 254 */extdiff.*/a.8a5febb7f867/a a.34eed99112ab/a (glob)
189 255 [1]
190 256
191 257 $ hg extdif -p echo -r "0::1"
192 258 */extdiff.*/a.8a5febb7f867/a a.34eed99112ab/a (glob)
193 259 [1]
194 260
195 261 Fallback to merge-tools.tool.executable|regkey
196 262 $ mkdir dir
197 263 $ cat > 'dir/tool.sh' << EOF
198 264 > #!/bin/sh
199 265 > echo "** custom diff **"
200 266 > EOF
201 267 $ chmod +x dir/tool.sh
202 268 $ tool=`pwd`/dir/tool.sh
203 269 $ hg --debug tl --config extdiff.tl= --config merge-tools.tl.executable=$tool
204 270 making snapshot of 2 files from rev * (glob)
205 271 a
206 272 b
207 273 making snapshot of 2 files from working directory
208 274 a
209 275 b
210 276 running "'$TESTTMP/a/dir/tool.sh' 'a.*' 'a'" in */extdiff.* (glob)
211 277 ** custom diff **
212 278 cleaning up temp directory
213 279 [1]
214 280
215 281 $ cd ..
216 282
217 283 #endif
218 284
219 285 #if symlink
220 286
221 287 Test symlinks handling (issue1909)
222 288
223 289 $ hg init testsymlinks
224 290 $ cd testsymlinks
225 291 $ echo a > a
226 292 $ hg ci -Am adda
227 293 adding a
228 294 $ echo a >> a
229 295 $ ln -s missing linka
230 296 $ hg add linka
231 297 $ hg falabala -r 0 --traceback
232 298 diffing testsymlinks.07f494440405 testsymlinks
233 299 [1]
234 300 $ cd ..
235 301
236 302 #endif
General Comments 0
You need to be logged in to leave comments. Login now