##// END OF EJS Templates
extdiff: escape filenames with vim/DirDiff and make quoting work with Windows...
Thomas Arendsen Hein -
r16242:55174ab8 stable
parent child Browse files
Show More
@@ -1,93 +1,93 b''
1 1 ; System-wide Mercurial config file.
2 2 ;
3 3 ; !!! Do Not Edit This File !!!
4 4 ;
5 5 ; This file will be replaced by the installer on every upgrade.
6 6 ; Editing this file can cause strange side effects on Vista.
7 7 ;
8 8 ; http://bitbucket.org/tortoisehg/stable/issue/135
9 9 ;
10 10 ; To change settings you see in this file, override (or enable) them in
11 11 ; your user Mercurial.ini file, where USERNAME is your Windows user name:
12 12 ;
13 13 ; XP or older - C:\Documents and Settings\USERNAME\Mercurial.ini
14 14 ; Vista or later - C:\Users\USERNAME\Mercurial.ini
15 15
16 16
17 17 [ui]
18 18 ; editor used to enter commit logs, etc. Most text editors will work.
19 19 editor = notepad
20 20 ; show changed files and be a bit more verbose if True
21 21 ; verbose = True
22 22
23 23 ; username data to appear in commits
24 24 ; it usually takes the form: Joe User <joe.user@host.com>
25 25 ; username = Joe User <j.user@example.com>
26 26
27 27 ; In order to push/pull over ssh you must specify an ssh tool
28 28 ;ssh = "C:\Progra~1\TortoiseSVN\bin\TortoisePlink.exe" -ssh -2
29 29 ;ssh = C:\cygwin\bin\ssh
30 30
31 31 ;
32 32 ; For more information about mercurial extensions, start here
33 33 ; http://www.selenic.com/mercurial/wiki/index.cgi/UsingExtensions
34 34 ;
35 35 ; Extensions shipped with Mercurial
36 36 ;
37 37 [extensions]
38 38 ;acl =
39 39 ;alias =
40 40 ;bugzilla =
41 41 ;children =
42 42 ;churn =
43 43 ;color =
44 44 ;convert =
45 45 ;eol =
46 46 ;extdiff =
47 47 ;fetch =
48 48 ;gpg =
49 49 ;graphlog =
50 50 ;hgcia =
51 51 ;hgk =
52 52 ;highlight =
53 53 ;interhg =
54 54 ;keyword =
55 55 ;mq =
56 56 ;notify =
57 57 ;pager =
58 58 ;patchbomb =
59 59 ;progress =
60 60 ;purge =
61 61 ;rebase =
62 62 ;record =
63 63 ;transplant =
64 64 ;win32mbcs =
65 65 ;zeroconf =
66 66
67 67 ;
68 68 ; Define external diff commands
69 69 ;
70 70 [extdiff]
71 71 ;cmd.bc3diff = C:\Program Files\Beyond Compare 3\BCompare.exe
72 72 ;cmd.vdiff = C:\Progra~1\TortoiseSVN\bin\TortoiseMerge.exe
73 73 ;cmd.vimdiff = gvim.exe
74 ;opts.vimdiff = -f '+next' '+execute "DirDiff ".argv(0)." ".argv(1)'
74 ;opts.vimdiff = -f "+next" "+execute 'DirDiff' fnameescape(argv(0)) fnameescape(argv(1))"
75 75
76 76
77 77 [hgk]
78 78 ; Replace the following with your path to hgk, uncomment it and
79 79 ; install ActiveTcl (or another win32 port like tclkit)
80 80 ; path="C:\Program Files\Mercurial\Contrib\hgk.tcl"
81 81 ; vdiff=vdiff
82 82
83 83
84 84 ;
85 85 ; The git extended diff format can represent binary files, file
86 86 ; permission changes, and rename information that the normal patch format
87 87 ; cannot describe. However it is also not compatible with tools which
88 88 ; expect normal patches. so enable git patches at your own risk.
89 89 ;
90 90 [diff]
91 91 ;git = false
92 92 ;nodates = false
93 93
@@ -1,328 +1,329 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 vdiff, runs kdiff3
27 27 vdiff = kdiff3
28 28
29 29 # add new command called meld, runs meld (no need to name twice)
30 30 meld =
31 31
32 32 # add new command called vimdiff, runs gvimdiff with DirDiff plugin
33 33 # (see http://www.vim.org/scripts/script.php?script_id=102) Non
34 34 # English user, be sure to put "let g:DirDiffDynamicDiffText = 1" in
35 35 # your .vimrc
36 vimdiff = gvim -f '+next' '+execute "DirDiff" argv(0) argv(1)'
36 vimdiff = gvim -f "+next" \\
37 "+execute 'DirDiff' fnameescape(argv(0)) fnameescape(argv(1))"
37 38
38 39 Tool arguments can include variables that are expanded at runtime::
39 40
40 41 $parent1, $plabel1 - filename, descriptive label of first parent
41 42 $child, $clabel - filename, descriptive label of child revision
42 43 $parent2, $plabel2 - filename, descriptive label of second parent
43 44 $root - repository root
44 45 $parent is an alias for $parent1.
45 46
46 47 The extdiff extension will look in your [diff-tools] and [merge-tools]
47 48 sections for diff tool arguments, when none are specified in [extdiff].
48 49
49 50 ::
50 51
51 52 [extdiff]
52 53 kdiff3 =
53 54
54 55 [diff-tools]
55 56 kdiff3.diffargs=--L1 '$plabel1' --L2 '$clabel' $parent $child
56 57
57 58 You can use -I/-X and list of file or directory names like normal
58 59 :hg:`diff` command. The extdiff extension makes snapshots of only
59 60 needed files, so running the external diff program will actually be
60 61 pretty fast (at least faster than having to compare the entire tree).
61 62 '''
62 63
63 64 from mercurial.i18n import _
64 65 from mercurial.node import short, nullid
65 66 from mercurial import scmutil, scmutil, util, commands, encoding
66 67 import os, shlex, shutil, tempfile, re
67 68
68 69 def snapshot(ui, repo, files, node, tmproot):
69 70 '''snapshot files as of some revision
70 71 if not using snapshot, -I/-X does not work and recursive diff
71 72 in tools like kdiff3 and meld displays too many files.'''
72 73 dirname = os.path.basename(repo.root)
73 74 if dirname == "":
74 75 dirname = "root"
75 76 if node is not None:
76 77 dirname = '%s.%s' % (dirname, short(node))
77 78 base = os.path.join(tmproot, dirname)
78 79 os.mkdir(base)
79 80 if node is not None:
80 81 ui.note(_('making snapshot of %d files from rev %s\n') %
81 82 (len(files), short(node)))
82 83 else:
83 84 ui.note(_('making snapshot of %d files from working directory\n') %
84 85 (len(files)))
85 86 wopener = scmutil.opener(base)
86 87 fns_and_mtime = []
87 88 ctx = repo[node]
88 89 for fn in files:
89 90 wfn = util.pconvert(fn)
90 91 if not wfn in ctx:
91 92 # File doesn't exist; could be a bogus modify
92 93 continue
93 94 ui.note(' %s\n' % wfn)
94 95 dest = os.path.join(base, wfn)
95 96 fctx = ctx[wfn]
96 97 data = repo.wwritedata(wfn, fctx.data())
97 98 if 'l' in fctx.flags():
98 99 wopener.symlink(data, wfn)
99 100 else:
100 101 wopener.write(wfn, data)
101 102 if 'x' in fctx.flags():
102 103 util.setflags(dest, False, True)
103 104 if node is None:
104 105 fns_and_mtime.append((dest, repo.wjoin(fn),
105 106 os.lstat(dest).st_mtime))
106 107 return dirname, fns_and_mtime
107 108
108 109 def dodiff(ui, repo, diffcmd, diffopts, pats, opts):
109 110 '''Do the actuall diff:
110 111
111 112 - copy to a temp structure if diffing 2 internal revisions
112 113 - copy to a temp structure if diffing working revision with
113 114 another one and more than 1 file is changed
114 115 - just invoke the diff for a single file in the working dir
115 116 '''
116 117
117 118 revs = opts.get('rev')
118 119 change = opts.get('change')
119 120 args = ' '.join(diffopts)
120 121 do3way = '$parent2' in args
121 122
122 123 if revs and change:
123 124 msg = _('cannot specify --rev and --change at the same time')
124 125 raise util.Abort(msg)
125 126 elif change:
126 127 node2 = scmutil.revsingle(repo, change, None).node()
127 128 node1a, node1b = repo.changelog.parents(node2)
128 129 else:
129 130 node1a, node2 = scmutil.revpair(repo, revs)
130 131 if not revs:
131 132 node1b = repo.dirstate.p2()
132 133 else:
133 134 node1b = nullid
134 135
135 136 # Disable 3-way merge if there is only one parent
136 137 if do3way:
137 138 if node1b == nullid:
138 139 do3way = False
139 140
140 141 matcher = scmutil.match(repo[node2], pats, opts)
141 142 mod_a, add_a, rem_a = map(set, repo.status(node1a, node2, matcher)[:3])
142 143 if do3way:
143 144 mod_b, add_b, rem_b = map(set, repo.status(node1b, node2, matcher)[:3])
144 145 else:
145 146 mod_b, add_b, rem_b = set(), set(), set()
146 147 modadd = mod_a | add_a | mod_b | add_b
147 148 common = modadd | rem_a | rem_b
148 149 if not common:
149 150 return 0
150 151
151 152 tmproot = tempfile.mkdtemp(prefix='extdiff.')
152 153 try:
153 154 # Always make a copy of node1a (and node1b, if applicable)
154 155 dir1a_files = mod_a | rem_a | ((mod_b | add_b) - add_a)
155 156 dir1a = snapshot(ui, repo, dir1a_files, node1a, tmproot)[0]
156 157 rev1a = '@%d' % repo[node1a].rev()
157 158 if do3way:
158 159 dir1b_files = mod_b | rem_b | ((mod_a | add_a) - add_b)
159 160 dir1b = snapshot(ui, repo, dir1b_files, node1b, tmproot)[0]
160 161 rev1b = '@%d' % repo[node1b].rev()
161 162 else:
162 163 dir1b = None
163 164 rev1b = ''
164 165
165 166 fns_and_mtime = []
166 167
167 168 # If node2 in not the wc or there is >1 change, copy it
168 169 dir2root = ''
169 170 rev2 = ''
170 171 if node2:
171 172 dir2 = snapshot(ui, repo, modadd, node2, tmproot)[0]
172 173 rev2 = '@%d' % repo[node2].rev()
173 174 elif len(common) > 1:
174 175 #we only actually need to get the files to copy back to
175 176 #the working dir in this case (because the other cases
176 177 #are: diffing 2 revisions or single file -- in which case
177 178 #the file is already directly passed to the diff tool).
178 179 dir2, fns_and_mtime = snapshot(ui, repo, modadd, None, tmproot)
179 180 else:
180 181 # This lets the diff tool open the changed file directly
181 182 dir2 = ''
182 183 dir2root = repo.root
183 184
184 185 label1a = rev1a
185 186 label1b = rev1b
186 187 label2 = rev2
187 188
188 189 # If only one change, diff the files instead of the directories
189 190 # Handle bogus modifies correctly by checking if the files exist
190 191 if len(common) == 1:
191 192 common_file = util.localpath(common.pop())
192 193 dir1a = os.path.join(tmproot, dir1a, common_file)
193 194 label1a = common_file + rev1a
194 195 if not os.path.isfile(dir1a):
195 196 dir1a = os.devnull
196 197 if do3way:
197 198 dir1b = os.path.join(tmproot, dir1b, common_file)
198 199 label1b = common_file + rev1b
199 200 if not os.path.isfile(dir1b):
200 201 dir1b = os.devnull
201 202 dir2 = os.path.join(dir2root, dir2, common_file)
202 203 label2 = common_file + rev2
203 204
204 205 # Function to quote file/dir names in the argument string.
205 206 # When not operating in 3-way mode, an empty string is
206 207 # returned for parent2
207 208 replace = dict(parent=dir1a, parent1=dir1a, parent2=dir1b,
208 209 plabel1=label1a, plabel2=label1b,
209 210 clabel=label2, child=dir2,
210 211 root=repo.root)
211 212 def quote(match):
212 213 key = match.group()[1:]
213 214 if not do3way and key == 'parent2':
214 215 return ''
215 216 return util.shellquote(replace[key])
216 217
217 218 # Match parent2 first, so 'parent1?' will match both parent1 and parent
218 219 regex = '\$(parent2|parent1?|child|plabel1|plabel2|clabel|root)'
219 220 if not do3way and not re.search(regex, args):
220 221 args += ' $parent1 $child'
221 222 args = re.sub(regex, quote, args)
222 223 cmdline = util.shellquote(diffcmd) + ' ' + args
223 224
224 225 ui.debug('running %r in %s\n' % (cmdline, tmproot))
225 226 util.system(cmdline, cwd=tmproot, out=ui.fout)
226 227
227 228 for copy_fn, working_fn, mtime in fns_and_mtime:
228 229 if os.lstat(copy_fn).st_mtime != mtime:
229 230 ui.debug('file changed while diffing. '
230 231 'Overwriting: %s (src: %s)\n' % (working_fn, copy_fn))
231 232 util.copyfile(copy_fn, working_fn)
232 233
233 234 return 1
234 235 finally:
235 236 ui.note(_('cleaning up temp directory\n'))
236 237 shutil.rmtree(tmproot)
237 238
238 239 def extdiff(ui, repo, *pats, **opts):
239 240 '''use external program to diff repository (or selected files)
240 241
241 242 Show differences between revisions for the specified files, using
242 243 an external program. The default program used is diff, with
243 244 default options "-Npru".
244 245
245 246 To select a different program, use the -p/--program option. The
246 247 program will be passed the names of two directories to compare. To
247 248 pass additional options to the program, use -o/--option. These
248 249 will be passed before the names of the directories to compare.
249 250
250 251 When two revision arguments are given, then changes are shown
251 252 between those revisions. If only one revision is specified then
252 253 that revision is compared to the working directory, and, when no
253 254 revisions are specified, the working directory files are compared
254 255 to its parent.'''
255 256 program = opts.get('program')
256 257 option = opts.get('option')
257 258 if not program:
258 259 program = 'diff'
259 260 option = option or ['-Npru']
260 261 return dodiff(ui, repo, program, option, pats, opts)
261 262
262 263 cmdtable = {
263 264 "extdiff":
264 265 (extdiff,
265 266 [('p', 'program', '',
266 267 _('comparison program to run'), _('CMD')),
267 268 ('o', 'option', [],
268 269 _('pass option to comparison program'), _('OPT')),
269 270 ('r', 'rev', [],
270 271 _('revision'), _('REV')),
271 272 ('c', 'change', '',
272 273 _('change made by revision'), _('REV')),
273 274 ] + commands.walkopts,
274 275 _('hg extdiff [OPT]... [FILE]...')),
275 276 }
276 277
277 278 def uisetup(ui):
278 279 for cmd, path in ui.configitems('extdiff'):
279 280 if cmd.startswith('cmd.'):
280 281 cmd = cmd[4:]
281 282 if not path:
282 283 path = cmd
283 284 diffopts = ui.config('extdiff', 'opts.' + cmd, '')
284 285 diffopts = diffopts and [diffopts] or []
285 286 elif cmd.startswith('opts.'):
286 287 continue
287 288 else:
288 289 # command = path opts
289 290 if path:
290 291 diffopts = shlex.split(path)
291 292 path = diffopts.pop(0)
292 293 else:
293 294 path, diffopts = cmd, []
294 295 # look for diff arguments in [diff-tools] then [merge-tools]
295 296 if diffopts == []:
296 297 args = ui.config('diff-tools', cmd+'.diffargs') or \
297 298 ui.config('merge-tools', cmd+'.diffargs')
298 299 if args:
299 300 diffopts = shlex.split(args)
300 301 def save(cmd, path, diffopts):
301 302 '''use closure to save diff command to use'''
302 303 def mydiff(ui, repo, *pats, **opts):
303 304 return dodiff(ui, repo, path, diffopts + opts['option'],
304 305 pats, opts)
305 306 doc = _('''\
306 307 use %(path)s to diff repository (or selected files)
307 308
308 309 Show differences between revisions for the specified files, using
309 310 the %(path)s program.
310 311
311 312 When two revision arguments are given, then changes are shown
312 313 between those revisions. If only one revision is specified then
313 314 that revision is compared to the working directory, and, when no
314 315 revisions are specified, the working directory files are compared
315 316 to its parent.\
316 317 ''') % dict(path=util.uirepr(path))
317 318
318 319 # We must translate the docstring right away since it is
319 320 # used as a format string. The string will unfortunately
320 321 # be translated again in commands.helpcmd and this will
321 322 # fail when the docstring contains non-ASCII characters.
322 323 # Decoding the string to a Unicode string here (using the
323 324 # right encoding) prevents that.
324 325 mydiff.__doc__ = doc.decode(encoding.encoding)
325 326 return mydiff
326 327 cmdtable[cmd] = (save(cmd, path, diffopts),
327 328 cmdtable['extdiff'][1][1:],
328 329 _('hg %s [OPTION]... [FILE]...') % cmd)
@@ -1,479 +1,480 b''
1 1 Test basic extension support
2 2
3 3 $ "$TESTDIR/hghave" no-outer-repo || exit 80
4 4
5 5 $ cat > foobar.py <<EOF
6 6 > import os
7 7 > from mercurial import commands
8 8 >
9 9 > def uisetup(ui):
10 10 > ui.write("uisetup called\\n")
11 11 >
12 12 > def reposetup(ui, repo):
13 13 > ui.write("reposetup called for %s\\n" % os.path.basename(repo.root))
14 14 > ui.write("ui %s= repo.ui\\n" % (ui == repo.ui and "=" or "!"))
15 15 >
16 16 > def foo(ui, *args, **kwargs):
17 17 > ui.write("Foo\\n")
18 18 >
19 19 > def bar(ui, *args, **kwargs):
20 20 > ui.write("Bar\\n")
21 21 >
22 22 > cmdtable = {
23 23 > "foo": (foo, [], "hg foo"),
24 24 > "bar": (bar, [], "hg bar"),
25 25 > }
26 26 >
27 27 > commands.norepo += ' bar'
28 28 > EOF
29 29 $ abspath=`pwd`/foobar.py
30 30
31 31 $ mkdir barfoo
32 32 $ cp foobar.py barfoo/__init__.py
33 33 $ barfoopath=`pwd`/barfoo
34 34
35 35 $ hg init a
36 36 $ cd a
37 37 $ echo foo > file
38 38 $ hg add file
39 39 $ hg commit -m 'add file'
40 40
41 41 $ echo '[extensions]' >> $HGRCPATH
42 42 $ echo "foobar = $abspath" >> $HGRCPATH
43 43 $ hg foo
44 44 uisetup called
45 45 reposetup called for a
46 46 ui == repo.ui
47 47 Foo
48 48
49 49 $ cd ..
50 50 $ hg clone a b
51 51 uisetup called
52 52 reposetup called for a
53 53 ui == repo.ui
54 54 reposetup called for b
55 55 ui == repo.ui
56 56 updating to branch default
57 57 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
58 58
59 59 $ hg bar
60 60 uisetup called
61 61 Bar
62 62 $ echo 'foobar = !' >> $HGRCPATH
63 63
64 64 module/__init__.py-style
65 65
66 66 $ echo "barfoo = $barfoopath" >> $HGRCPATH
67 67 $ cd a
68 68 $ hg foo
69 69 uisetup called
70 70 reposetup called for a
71 71 ui == repo.ui
72 72 Foo
73 73 $ echo 'barfoo = !' >> $HGRCPATH
74 74
75 75 Check that extensions are loaded in phases:
76 76
77 77 $ cat > foo.py <<EOF
78 78 > import os
79 79 > name = os.path.basename(__file__).rsplit('.', 1)[0]
80 80 > print "1) %s imported" % name
81 81 > def uisetup(ui):
82 82 > print "2) %s uisetup" % name
83 83 > def extsetup():
84 84 > print "3) %s extsetup" % name
85 85 > def reposetup(ui, repo):
86 86 > print "4) %s reposetup" % name
87 87 > EOF
88 88
89 89 $ cp foo.py bar.py
90 90 $ echo 'foo = foo.py' >> $HGRCPATH
91 91 $ echo 'bar = bar.py' >> $HGRCPATH
92 92
93 93 Command with no output, we just want to see the extensions loaded:
94 94
95 95 $ hg paths
96 96 1) foo imported
97 97 1) bar imported
98 98 2) foo uisetup
99 99 2) bar uisetup
100 100 3) foo extsetup
101 101 3) bar extsetup
102 102 4) foo reposetup
103 103 4) bar reposetup
104 104
105 105 Check hgweb's load order:
106 106
107 107 $ cat > hgweb.cgi <<EOF
108 108 > #!/usr/bin/env python
109 109 > from mercurial import demandimport; demandimport.enable()
110 110 > from mercurial.hgweb import hgweb
111 111 > from mercurial.hgweb import wsgicgi
112 112 >
113 113 > application = hgweb('.', 'test repo')
114 114 > wsgicgi.launch(application)
115 115 > EOF
116 116
117 117 $ SCRIPT_NAME='/' SERVER_PORT='80' SERVER_NAME='localhost' python hgweb.cgi \
118 118 > | grep '^[0-9]) ' # ignores HTML output
119 119 1) foo imported
120 120 1) bar imported
121 121 2) foo uisetup
122 122 2) bar uisetup
123 123 3) foo extsetup
124 124 3) bar extsetup
125 125 4) foo reposetup
126 126 4) bar reposetup
127 127 4) foo reposetup
128 128 4) bar reposetup
129 129
130 130 $ echo 'foo = !' >> $HGRCPATH
131 131 $ echo 'bar = !' >> $HGRCPATH
132 132
133 133 $ cd ..
134 134
135 135 $ cat > empty.py <<EOF
136 136 > '''empty cmdtable
137 137 > '''
138 138 > cmdtable = {}
139 139 > EOF
140 140 $ emptypath=`pwd`/empty.py
141 141 $ echo "empty = $emptypath" >> $HGRCPATH
142 142 $ hg help empty
143 143 empty extension - empty cmdtable
144 144
145 145 no commands defined
146 146
147 147 $ echo 'empty = !' >> $HGRCPATH
148 148
149 149 $ cat > debugextension.py <<EOF
150 150 > '''only debugcommands
151 151 > '''
152 152 > def debugfoobar(ui, repo, *args, **opts):
153 153 > "yet another debug command"
154 154 > pass
155 155 >
156 156 > def foo(ui, repo, *args, **opts):
157 157 > """yet another foo command
158 158 >
159 159 > This command has been DEPRECATED since forever.
160 160 > """
161 161 > pass
162 162 >
163 163 > cmdtable = {
164 164 > "debugfoobar": (debugfoobar, (), "hg debugfoobar"),
165 165 > "foo": (foo, (), "hg foo")
166 166 > }
167 167 > EOF
168 168 $ debugpath=`pwd`/debugextension.py
169 169 $ echo "debugextension = $debugpath" >> $HGRCPATH
170 170
171 171 $ hg help debugextension
172 172 debugextension extension - only debugcommands
173 173
174 174 no commands defined
175 175
176 176 $ hg --verbose help debugextension
177 177 debugextension extension - only debugcommands
178 178
179 179 list of commands:
180 180
181 181 foo:
182 182 yet another foo command
183 183
184 184 global options:
185 185
186 186 -R --repository REPO repository root directory or name of overlay bundle
187 187 file
188 188 --cwd DIR change working directory
189 189 -y --noninteractive do not prompt, automatically pick the first choice for
190 190 all prompts
191 191 -q --quiet suppress output
192 192 -v --verbose enable additional output
193 193 --config CONFIG [+] set/override config option (use 'section.name=value')
194 194 --debug enable debugging output
195 195 --debugger start debugger
196 196 --encoding ENCODE set the charset encoding (default: ascii)
197 197 --encodingmode MODE set the charset encoding mode (default: strict)
198 198 --traceback always print a traceback on exception
199 199 --time time how long the command takes
200 200 --profile print command execution profile
201 201 --version output version information and exit
202 202 -h --help display help and exit
203 203
204 204 [+] marked option can be specified multiple times
205 205
206 206 $ hg --debug help debugextension
207 207 debugextension extension - only debugcommands
208 208
209 209 list of commands:
210 210
211 211 debugfoobar:
212 212 yet another debug command
213 213 foo:
214 214 yet another foo command
215 215
216 216 global options:
217 217
218 218 -R --repository REPO repository root directory or name of overlay bundle
219 219 file
220 220 --cwd DIR change working directory
221 221 -y --noninteractive do not prompt, automatically pick the first choice for
222 222 all prompts
223 223 -q --quiet suppress output
224 224 -v --verbose enable additional output
225 225 --config CONFIG [+] set/override config option (use 'section.name=value')
226 226 --debug enable debugging output
227 227 --debugger start debugger
228 228 --encoding ENCODE set the charset encoding (default: ascii)
229 229 --encodingmode MODE set the charset encoding mode (default: strict)
230 230 --traceback always print a traceback on exception
231 231 --time time how long the command takes
232 232 --profile print command execution profile
233 233 --version output version information and exit
234 234 -h --help display help and exit
235 235
236 236 [+] marked option can be specified multiple times
237 237 $ echo 'debugextension = !' >> $HGRCPATH
238 238
239 239 Extension module help vs command help:
240 240
241 241 $ echo 'extdiff =' >> $HGRCPATH
242 242 $ hg help extdiff
243 243 hg extdiff [OPT]... [FILE]...
244 244
245 245 use external program to diff repository (or selected files)
246 246
247 247 Show differences between revisions for the specified files, using an
248 248 external program. The default program used is diff, with default options
249 249 "-Npru".
250 250
251 251 To select a different program, use the -p/--program option. The program
252 252 will be passed the names of two directories to compare. To pass additional
253 253 options to the program, use -o/--option. These will be passed before the
254 254 names of the directories to compare.
255 255
256 256 When two revision arguments are given, then changes are shown between
257 257 those revisions. If only one revision is specified then that revision is
258 258 compared to the working directory, and, when no revisions are specified,
259 259 the working directory files are compared to its parent.
260 260
261 261 use "hg help -e extdiff" to show help for the extdiff extension
262 262
263 263 options:
264 264
265 265 -p --program CMD comparison program to run
266 266 -o --option OPT [+] pass option to comparison program
267 267 -r --rev REV [+] revision
268 268 -c --change REV change made by revision
269 269 -I --include PATTERN [+] include names matching the given patterns
270 270 -X --exclude PATTERN [+] exclude names matching the given patterns
271 271
272 272 [+] marked option can be specified multiple times
273 273
274 274 use "hg -v help extdiff" to show more info
275 275
276 276 $ hg help --extension extdiff
277 277 extdiff extension - command to allow external programs to compare revisions
278 278
279 279 The extdiff Mercurial extension allows you to use external programs to compare
280 280 revisions, or revision with working directory. The external diff programs are
281 281 called with a configurable set of options and two non-option arguments: paths
282 282 to directories containing snapshots of files to compare.
283 283
284 284 The extdiff extension also allows you to configure new diff commands, so you
285 285 do not need to type "hg extdiff -p kdiff3" always.
286 286
287 287 [extdiff]
288 288 # add new command that runs GNU diff(1) in 'context diff' mode
289 289 cdiff = gdiff -Nprc5
290 290 ## or the old way:
291 291 #cmd.cdiff = gdiff
292 292 #opts.cdiff = -Nprc5
293 293
294 294 # add new command called vdiff, runs kdiff3
295 295 vdiff = kdiff3
296 296
297 297 # add new command called meld, runs meld (no need to name twice)
298 298 meld =
299 299
300 300 # add new command called vimdiff, runs gvimdiff with DirDiff plugin
301 301 # (see http://www.vim.org/scripts/script.php?script_id=102) Non
302 302 # English user, be sure to put "let g:DirDiffDynamicDiffText = 1" in
303 303 # your .vimrc
304 vimdiff = gvim -f '+next' '+execute "DirDiff" argv(0) argv(1)'
304 vimdiff = gvim -f "+next" \
305 "+execute 'DirDiff' fnameescape(argv(0)) fnameescape(argv(1))"
305 306
306 307 Tool arguments can include variables that are expanded at runtime:
307 308
308 309 $parent1, $plabel1 - filename, descriptive label of first parent
309 310 $child, $clabel - filename, descriptive label of child revision
310 311 $parent2, $plabel2 - filename, descriptive label of second parent
311 312 $root - repository root
312 313 $parent is an alias for $parent1.
313 314
314 315 The extdiff extension will look in your [diff-tools] and [merge-tools]
315 316 sections for diff tool arguments, when none are specified in [extdiff].
316 317
317 318 [extdiff]
318 319 kdiff3 =
319 320
320 321 [diff-tools]
321 322 kdiff3.diffargs=--L1 '$plabel1' --L2 '$clabel' $parent $child
322 323
323 324 You can use -I/-X and list of file or directory names like normal "hg diff"
324 325 command. The extdiff extension makes snapshots of only needed files, so
325 326 running the external diff program will actually be pretty fast (at least
326 327 faster than having to compare the entire tree).
327 328
328 329 list of commands:
329 330
330 331 extdiff use external program to diff repository (or selected files)
331 332
332 333 use "hg -v help extdiff" to show builtin aliases and global options
333 334
334 335 $ echo 'extdiff = !' >> $HGRCPATH
335 336
336 337 Test help topic with same name as extension
337 338
338 339 $ cat > multirevs.py <<EOF
339 340 > from mercurial import commands
340 341 > """multirevs extension
341 342 > Big multi-line module docstring."""
342 343 > def multirevs(ui, repo, arg, *args, **opts):
343 344 > """multirevs command"""
344 345 > pass
345 346 > cmdtable = {
346 347 > "multirevs": (multirevs, [], 'ARG')
347 348 > }
348 349 > commands.norepo += ' multirevs'
349 350 > EOF
350 351 $ echo "multirevs = multirevs.py" >> $HGRCPATH
351 352
352 353 $ hg help multirevs
353 354 Specifying Multiple Revisions
354 355
355 356 When Mercurial accepts more than one revision, they may be specified
356 357 individually, or provided as a topologically continuous range, separated
357 358 by the ":" character.
358 359
359 360 The syntax of range notation is [BEGIN]:[END], where BEGIN and END are
360 361 revision identifiers. Both BEGIN and END are optional. If BEGIN is not
361 362 specified, it defaults to revision number 0. If END is not specified, it
362 363 defaults to the tip. The range ":" thus means "all revisions".
363 364
364 365 If BEGIN is greater than END, revisions are treated in reverse order.
365 366
366 367 A range acts as a closed interval. This means that a range of 3:5 gives 3,
367 368 4 and 5. Similarly, a range of 9:6 gives 9, 8, 7, and 6.
368 369
369 370 use "hg help -c multirevs" to see help for the multirevs command
370 371
371 372 $ hg help -c multirevs
372 373 hg multirevs ARG
373 374
374 375 multirevs command
375 376
376 377 use "hg -v help multirevs" to show more info
377 378
378 379 $ hg multirevs
379 380 hg multirevs: invalid arguments
380 381 hg multirevs ARG
381 382
382 383 multirevs command
383 384
384 385 use "hg help multirevs" to show the full help text
385 386 [255]
386 387
387 388 $ echo "multirevs = !" >> $HGRCPATH
388 389
389 390 Issue811: Problem loading extensions twice (by site and by user)
390 391
391 392 $ debugpath=`pwd`/debugissue811.py
392 393 $ cat > debugissue811.py <<EOF
393 394 > '''show all loaded extensions
394 395 > '''
395 396 > from mercurial import extensions, commands
396 397 >
397 398 > def debugextensions(ui):
398 399 > "yet another debug command"
399 400 > ui.write("%s\n" % '\n'.join([x for x, y in extensions.extensions()]))
400 401 >
401 402 > cmdtable = {"debugextensions": (debugextensions, (), "hg debugextensions")}
402 403 > commands.norepo += " debugextensions"
403 404 > EOF
404 405 $ echo "debugissue811 = $debugpath" >> $HGRCPATH
405 406 $ echo "mq=" >> $HGRCPATH
406 407 $ echo "hgext.mq=" >> $HGRCPATH
407 408 $ echo "hgext/mq=" >> $HGRCPATH
408 409
409 410 Show extensions:
410 411
411 412 $ hg debugextensions
412 413 debugissue811
413 414 mq
414 415
415 416 Disabled extension commands:
416 417
417 418 $ HGRCPATH=
418 419 $ export HGRCPATH
419 420 $ hg help email
420 421 'email' is provided by the following extension:
421 422
422 423 patchbomb command to send changesets as (a series of) patch emails
423 424
424 425 use "hg help extensions" for information on enabling extensions
425 426 $ hg qdel
426 427 hg: unknown command 'qdel'
427 428 'qdelete' is provided by the following extension:
428 429
429 430 mq manage a stack of patches
430 431
431 432 use "hg help extensions" for information on enabling extensions
432 433 [255]
433 434 $ hg churn
434 435 hg: unknown command 'churn'
435 436 'churn' is provided by the following extension:
436 437
437 438 churn command to display statistics about repository history
438 439
439 440 use "hg help extensions" for information on enabling extensions
440 441 [255]
441 442
442 443 Disabled extensions:
443 444
444 445 $ hg help churn
445 446 churn extension - command to display statistics about repository history
446 447
447 448 use "hg help extensions" for information on enabling extensions
448 449 $ hg help patchbomb
449 450 patchbomb extension - command to send changesets as (a series of) patch emails
450 451
451 452 use "hg help extensions" for information on enabling extensions
452 453
453 454 Broken disabled extension and command:
454 455
455 456 $ mkdir hgext
456 457 $ echo > hgext/__init__.py
457 458 $ cat > hgext/broken.py <<EOF
458 459 > "broken extension'
459 460 > EOF
460 461 $ cat > path.py <<EOF
461 462 > import os, sys
462 463 > sys.path.insert(0, os.environ['HGEXTPATH'])
463 464 > EOF
464 465 $ HGEXTPATH=`pwd`
465 466 $ export HGEXTPATH
466 467
467 468 $ hg --config extensions.path=./path.py help broken
468 469 broken extension - (no help text available)
469 470
470 471 use "hg help extensions" for information on enabling extensions
471 472
472 473 $ cat > hgext/forest.py <<EOF
473 474 > cmdtable = None
474 475 > EOF
475 476 $ hg --config extensions.path=./path.py help foo > /dev/null
476 477 warning: error finding commands in $TESTTMP/hgext/forest.py (glob)
477 478 hg: unknown command 'foo'
478 479 warning: error finding commands in $TESTTMP/hgext/forest.py (glob)
479 480 [255]
General Comments 0
You need to be logged in to leave comments. Login now