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