##// END OF EJS Templates
extensions: remove the inotify extension (BC)...
Matt Mackall -
r20622:352abbb0 default
parent child Browse files
Show More
@@ -1,369 +1,369 b''
1 1 # extensions.py - extension handling for mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.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 import imp, os
9 9 import util, cmdutil, error
10 10 from i18n import _, gettext
11 11
12 12 _extensions = {}
13 13 _order = []
14 _ignore = ['hbisect', 'bookmarks', 'parentrevspec', 'interhg']
14 _ignore = ['hbisect', 'bookmarks', 'parentrevspec', 'interhg', 'inotify']
15 15
16 16 def extensions(ui=None):
17 17 if ui:
18 18 def enabled(name):
19 19 for format in ['%s', 'hgext.%s']:
20 20 conf = ui.config('extensions', format % name)
21 21 if conf is not None and not conf.startswith('!'):
22 22 return True
23 23 else:
24 24 enabled = lambda name: True
25 25 for name in _order:
26 26 module = _extensions[name]
27 27 if module and enabled(name):
28 28 yield name, module
29 29
30 30 def find(name):
31 31 '''return module with given extension name'''
32 32 mod = None
33 33 try:
34 34 mod = _extensions[name]
35 35 except KeyError:
36 36 for k, v in _extensions.iteritems():
37 37 if k.endswith('.' + name) or k.endswith('/' + name):
38 38 mod = v
39 39 break
40 40 if not mod:
41 41 raise KeyError(name)
42 42 return mod
43 43
44 44 def loadpath(path, module_name):
45 45 module_name = module_name.replace('.', '_')
46 46 path = util.expandpath(path)
47 47 if os.path.isdir(path):
48 48 # module/__init__.py style
49 49 d, f = os.path.split(path.rstrip('/'))
50 50 fd, fpath, desc = imp.find_module(f, [d])
51 51 return imp.load_module(module_name, fd, fpath, desc)
52 52 else:
53 53 try:
54 54 return imp.load_source(module_name, path)
55 55 except IOError, exc:
56 56 if not exc.filename:
57 57 exc.filename = path # python does not fill this
58 58 raise
59 59
60 60 def load(ui, name, path):
61 61 if name.startswith('hgext.') or name.startswith('hgext/'):
62 62 shortname = name[6:]
63 63 else:
64 64 shortname = name
65 65 if shortname in _ignore:
66 66 return None
67 67 if shortname in _extensions:
68 68 return _extensions[shortname]
69 69 _extensions[shortname] = None
70 70 if path:
71 71 # the module will be loaded in sys.modules
72 72 # choose an unique name so that it doesn't
73 73 # conflicts with other modules
74 74 mod = loadpath(path, 'hgext.%s' % name)
75 75 else:
76 76 def importh(name):
77 77 mod = __import__(name)
78 78 components = name.split('.')
79 79 for comp in components[1:]:
80 80 mod = getattr(mod, comp)
81 81 return mod
82 82 try:
83 83 mod = importh("hgext.%s" % name)
84 84 except ImportError, err:
85 85 ui.debug('could not import hgext.%s (%s): trying %s\n'
86 86 % (name, err, name))
87 87 mod = importh(name)
88 88 _extensions[shortname] = mod
89 89 _order.append(shortname)
90 90 return mod
91 91
92 92 def loadall(ui):
93 93 result = ui.configitems("extensions")
94 94 newindex = len(_order)
95 95 for (name, path) in result:
96 96 if path:
97 97 if path[0] == '!':
98 98 continue
99 99 try:
100 100 load(ui, name, path)
101 101 except KeyboardInterrupt:
102 102 raise
103 103 except Exception, inst:
104 104 if path:
105 105 ui.warn(_("*** failed to import extension %s from %s: %s\n")
106 106 % (name, path, inst))
107 107 else:
108 108 ui.warn(_("*** failed to import extension %s: %s\n")
109 109 % (name, inst))
110 110 if ui.traceback():
111 111 return 1
112 112
113 113 for name in _order[newindex:]:
114 114 uisetup = getattr(_extensions[name], 'uisetup', None)
115 115 if uisetup:
116 116 uisetup(ui)
117 117
118 118 for name in _order[newindex:]:
119 119 extsetup = getattr(_extensions[name], 'extsetup', None)
120 120 if extsetup:
121 121 try:
122 122 extsetup(ui)
123 123 except TypeError:
124 124 if extsetup.func_code.co_argcount != 0:
125 125 raise
126 126 extsetup() # old extsetup with no ui argument
127 127
128 128 def wrapcommand(table, command, wrapper):
129 129 '''Wrap the command named `command' in table
130 130
131 131 Replace command in the command table with wrapper. The wrapped command will
132 132 be inserted into the command table specified by the table argument.
133 133
134 134 The wrapper will be called like
135 135
136 136 wrapper(orig, *args, **kwargs)
137 137
138 138 where orig is the original (wrapped) function, and *args, **kwargs
139 139 are the arguments passed to it.
140 140 '''
141 141 assert util.safehasattr(wrapper, '__call__')
142 142 aliases, entry = cmdutil.findcmd(command, table)
143 143 for alias, e in table.iteritems():
144 144 if e is entry:
145 145 key = alias
146 146 break
147 147
148 148 origfn = entry[0]
149 149 def wrap(*args, **kwargs):
150 150 return util.checksignature(wrapper)(
151 151 util.checksignature(origfn), *args, **kwargs)
152 152
153 153 wrap.__doc__ = getattr(origfn, '__doc__')
154 154 wrap.__module__ = getattr(origfn, '__module__')
155 155
156 156 newentry = list(entry)
157 157 newentry[0] = wrap
158 158 table[key] = tuple(newentry)
159 159 return entry
160 160
161 161 def wrapfunction(container, funcname, wrapper):
162 162 '''Wrap the function named funcname in container
163 163
164 164 Replace the funcname member in the given container with the specified
165 165 wrapper. The container is typically a module, class, or instance.
166 166
167 167 The wrapper will be called like
168 168
169 169 wrapper(orig, *args, **kwargs)
170 170
171 171 where orig is the original (wrapped) function, and *args, **kwargs
172 172 are the arguments passed to it.
173 173
174 174 Wrapping methods of the repository object is not recommended since
175 175 it conflicts with extensions that extend the repository by
176 176 subclassing. All extensions that need to extend methods of
177 177 localrepository should use this subclassing trick: namely,
178 178 reposetup() should look like
179 179
180 180 def reposetup(ui, repo):
181 181 class myrepo(repo.__class__):
182 182 def whatever(self, *args, **kwargs):
183 183 [...extension stuff...]
184 184 super(myrepo, self).whatever(*args, **kwargs)
185 185 [...extension stuff...]
186 186
187 187 repo.__class__ = myrepo
188 188
189 189 In general, combining wrapfunction() with subclassing does not
190 190 work. Since you cannot control what other extensions are loaded by
191 191 your end users, you should play nicely with others by using the
192 192 subclass trick.
193 193 '''
194 194 assert util.safehasattr(wrapper, '__call__')
195 195 def wrap(*args, **kwargs):
196 196 return wrapper(origfn, *args, **kwargs)
197 197
198 198 origfn = getattr(container, funcname)
199 199 assert util.safehasattr(origfn, '__call__')
200 200 setattr(container, funcname, wrap)
201 201 return origfn
202 202
203 203 def _disabledpaths(strip_init=False):
204 204 '''find paths of disabled extensions. returns a dict of {name: path}
205 205 removes /__init__.py from packages if strip_init is True'''
206 206 import hgext
207 207 extpath = os.path.dirname(os.path.abspath(hgext.__file__))
208 208 try: # might not be a filesystem path
209 209 files = os.listdir(extpath)
210 210 except OSError:
211 211 return {}
212 212
213 213 exts = {}
214 214 for e in files:
215 215 if e.endswith('.py'):
216 216 name = e.rsplit('.', 1)[0]
217 217 path = os.path.join(extpath, e)
218 218 else:
219 219 name = e
220 220 path = os.path.join(extpath, e, '__init__.py')
221 221 if not os.path.exists(path):
222 222 continue
223 223 if strip_init:
224 224 path = os.path.dirname(path)
225 225 if name in exts or name in _order or name == '__init__':
226 226 continue
227 227 exts[name] = path
228 228 return exts
229 229
230 230 def _moduledoc(file):
231 231 '''return the top-level python documentation for the given file
232 232
233 233 Loosely inspired by pydoc.source_synopsis(), but rewritten to
234 234 handle triple quotes and to return the whole text instead of just
235 235 the synopsis'''
236 236 result = []
237 237
238 238 line = file.readline()
239 239 while line[:1] == '#' or not line.strip():
240 240 line = file.readline()
241 241 if not line:
242 242 break
243 243
244 244 start = line[:3]
245 245 if start == '"""' or start == "'''":
246 246 line = line[3:]
247 247 while line:
248 248 if line.rstrip().endswith(start):
249 249 line = line.split(start)[0]
250 250 if line:
251 251 result.append(line)
252 252 break
253 253 elif not line:
254 254 return None # unmatched delimiter
255 255 result.append(line)
256 256 line = file.readline()
257 257 else:
258 258 return None
259 259
260 260 return ''.join(result)
261 261
262 262 def _disabledhelp(path):
263 263 '''retrieve help synopsis of a disabled extension (without importing)'''
264 264 try:
265 265 file = open(path)
266 266 except IOError:
267 267 return
268 268 else:
269 269 doc = _moduledoc(file)
270 270 file.close()
271 271
272 272 if doc: # extracting localized synopsis
273 273 return gettext(doc).splitlines()[0]
274 274 else:
275 275 return _('(no help text available)')
276 276
277 277 def disabled():
278 278 '''find disabled extensions from hgext. returns a dict of {name: desc}'''
279 279 try:
280 280 from hgext import __index__
281 281 return dict((name, gettext(desc))
282 282 for name, desc in __index__.docs.iteritems()
283 283 if name not in _order)
284 284 except ImportError:
285 285 pass
286 286
287 287 paths = _disabledpaths()
288 288 if not paths:
289 289 return {}
290 290
291 291 exts = {}
292 292 for name, path in paths.iteritems():
293 293 doc = _disabledhelp(path)
294 294 if doc:
295 295 exts[name] = doc
296 296
297 297 return exts
298 298
299 299 def disabledext(name):
300 300 '''find a specific disabled extension from hgext. returns desc'''
301 301 try:
302 302 from hgext import __index__
303 303 if name in _order: # enabled
304 304 return
305 305 else:
306 306 return gettext(__index__.docs.get(name))
307 307 except ImportError:
308 308 pass
309 309
310 310 paths = _disabledpaths()
311 311 if name in paths:
312 312 return _disabledhelp(paths[name])
313 313
314 314 def disabledcmd(ui, cmd, strict=False):
315 315 '''import disabled extensions until cmd is found.
316 316 returns (cmdname, extname, module)'''
317 317
318 318 paths = _disabledpaths(strip_init=True)
319 319 if not paths:
320 320 raise error.UnknownCommand(cmd)
321 321
322 322 def findcmd(cmd, name, path):
323 323 try:
324 324 mod = loadpath(path, 'hgext.%s' % name)
325 325 except Exception:
326 326 return
327 327 try:
328 328 aliases, entry = cmdutil.findcmd(cmd,
329 329 getattr(mod, 'cmdtable', {}), strict)
330 330 except (error.AmbiguousCommand, error.UnknownCommand):
331 331 return
332 332 except Exception:
333 333 ui.warn(_('warning: error finding commands in %s\n') % path)
334 334 ui.traceback()
335 335 return
336 336 for c in aliases:
337 337 if c.startswith(cmd):
338 338 cmd = c
339 339 break
340 340 else:
341 341 cmd = aliases[0]
342 342 return (cmd, name, mod)
343 343
344 344 ext = None
345 345 # first, search for an extension with the same name as the command
346 346 path = paths.pop(cmd, None)
347 347 if path:
348 348 ext = findcmd(cmd, cmd, path)
349 349 if not ext:
350 350 # otherwise, interrogate each extension until there's a match
351 351 for name, path in paths.iteritems():
352 352 ext = findcmd(cmd, name, path)
353 353 if ext:
354 354 break
355 355 if ext and 'DEPRECATED' not in ext.__doc__:
356 356 return ext
357 357
358 358 raise error.UnknownCommand(cmd)
359 359
360 360 def enabled(shortname=True):
361 361 '''return a dict of {name: desc} of extensions'''
362 362 exts = {}
363 363 for ename, ext in extensions():
364 364 doc = (gettext(ext.__doc__) or _('(no help text available)'))
365 365 if shortname:
366 366 ename = ename.split('.')[-1]
367 367 exts[ename] = doc.splitlines()[0].strip()
368 368
369 369 return exts
@@ -1,577 +1,563 b''
1 1 #
2 2 # This is the mercurial setup script.
3 3 #
4 4 # 'python setup.py install', or
5 5 # 'python setup.py --help' for more options
6 6
7 7 import sys, platform
8 8 if getattr(sys, 'version_info', (0, 0, 0)) < (2, 4, 0, 'final'):
9 9 raise SystemExit("Mercurial requires Python 2.4 or later.")
10 10
11 11 if sys.version_info[0] >= 3:
12 12 def b(s):
13 13 '''A helper function to emulate 2.6+ bytes literals using string
14 14 literals.'''
15 15 return s.encode('latin1')
16 16 else:
17 17 def b(s):
18 18 '''A helper function to emulate 2.6+ bytes literals using string
19 19 literals.'''
20 20 return s
21 21
22 22 # Solaris Python packaging brain damage
23 23 try:
24 24 import hashlib
25 25 sha = hashlib.sha1()
26 26 except ImportError:
27 27 try:
28 28 import sha
29 29 except ImportError:
30 30 raise SystemExit(
31 31 "Couldn't import standard hashlib (incomplete Python install).")
32 32
33 33 try:
34 34 import zlib
35 35 except ImportError:
36 36 raise SystemExit(
37 37 "Couldn't import standard zlib (incomplete Python install).")
38 38
39 39 # The base IronPython distribution (as of 2.7.1) doesn't support bz2
40 40 isironpython = False
41 41 try:
42 42 isironpython = (platform.python_implementation()
43 43 .lower().find("ironpython") != -1)
44 44 except AttributeError:
45 45 pass
46 46
47 47 if isironpython:
48 48 sys.stderr.write("warning: IronPython detected (no bz2 support)\n")
49 49 else:
50 50 try:
51 51 import bz2
52 52 except ImportError:
53 53 raise SystemExit(
54 54 "Couldn't import standard bz2 (incomplete Python install).")
55 55
56 56 import os, subprocess, time
57 57 import shutil
58 58 import tempfile
59 59 from distutils import log
60 60 from distutils.core import setup, Command, Extension
61 61 from distutils.dist import Distribution
62 62 from distutils.command.build import build
63 63 from distutils.command.build_ext import build_ext
64 64 from distutils.command.build_py import build_py
65 65 from distutils.command.install_scripts import install_scripts
66 66 from distutils.spawn import spawn, find_executable
67 67 from distutils.ccompiler import new_compiler
68 68 from distutils import cygwinccompiler
69 69 from distutils.errors import CCompilerError, DistutilsExecError
70 70 from distutils.sysconfig import get_python_inc
71 71 from distutils.version import StrictVersion
72 72
73 73 convert2to3 = '--c2to3' in sys.argv
74 74 if convert2to3:
75 75 try:
76 76 from distutils.command.build_py import build_py_2to3 as build_py
77 77 from lib2to3.refactor import get_fixers_from_package as getfixers
78 78 except ImportError:
79 79 if sys.version_info[0] < 3:
80 80 raise SystemExit("--c2to3 is only compatible with python3.")
81 81 raise
82 82 sys.path.append('contrib')
83 83 elif sys.version_info[0] >= 3:
84 84 raise SystemExit("setup.py with python3 needs --c2to3 (experimental)")
85 85
86 86 scripts = ['hg']
87 87 if os.name == 'nt':
88 88 scripts.append('contrib/win32/hg.bat')
89 89
90 90 # simplified version of distutils.ccompiler.CCompiler.has_function
91 91 # that actually removes its temporary files.
92 92 def hasfunction(cc, funcname):
93 93 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
94 94 devnull = oldstderr = None
95 95 try:
96 96 try:
97 97 fname = os.path.join(tmpdir, 'funcname.c')
98 98 f = open(fname, 'w')
99 99 f.write('int main(void) {\n')
100 100 f.write(' %s();\n' % funcname)
101 101 f.write('}\n')
102 102 f.close()
103 103 # Redirect stderr to /dev/null to hide any error messages
104 104 # from the compiler.
105 105 # This will have to be changed if we ever have to check
106 106 # for a function on Windows.
107 107 devnull = open('/dev/null', 'w')
108 108 oldstderr = os.dup(sys.stderr.fileno())
109 109 os.dup2(devnull.fileno(), sys.stderr.fileno())
110 110 objects = cc.compile([fname], output_dir=tmpdir)
111 111 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
112 112 except Exception:
113 113 return False
114 114 return True
115 115 finally:
116 116 if oldstderr is not None:
117 117 os.dup2(oldstderr, sys.stderr.fileno())
118 118 if devnull is not None:
119 119 devnull.close()
120 120 shutil.rmtree(tmpdir)
121 121
122 122 # py2exe needs to be installed to work
123 123 try:
124 124 import py2exe
125 125 py2exeloaded = True
126 126 # import py2exe's patched Distribution class
127 127 from distutils.core import Distribution
128 128 except ImportError:
129 129 py2exeloaded = False
130 130
131 131 def runcmd(cmd, env):
132 132 if sys.platform == 'plan9':
133 133 # subprocess kludge to work around issues in half-baked Python
134 134 # ports, notably bichued/python:
135 135 _, out, err = os.popen3(cmd)
136 136 return str(out), str(err)
137 137 else:
138 138 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
139 139 stderr=subprocess.PIPE, env=env)
140 140 out, err = p.communicate()
141 141 return out, err
142 142
143 143 def runhg(cmd, env):
144 144 out, err = runcmd(cmd, env)
145 145 # If root is executing setup.py, but the repository is owned by
146 146 # another user (as in "sudo python setup.py install") we will get
147 147 # trust warnings since the .hg/hgrc file is untrusted. That is
148 148 # fine, we don't want to load it anyway. Python may warn about
149 149 # a missing __init__.py in mercurial/locale, we also ignore that.
150 150 err = [e for e in err.splitlines()
151 151 if not e.startswith(b('not trusting file')) \
152 152 and not e.startswith(b('warning: Not importing')) \
153 153 and not e.startswith(b('obsolete feature not enabled'))]
154 154 if err:
155 155 print >> sys.stderr, "stderr from '%s':" % (' '.join(cmd))
156 156 print >> sys.stderr, '\n'.join([' ' + e for e in err])
157 157 return ''
158 158 return out
159 159
160 160 version = ''
161 161
162 162 # Execute hg out of this directory with a custom environment which
163 163 # includes the pure Python modules in mercurial/pure. We also take
164 164 # care to not use any hgrc files and do no localization.
165 165 pypath = ['mercurial', os.path.join('mercurial', 'pure')]
166 166 env = {'PYTHONPATH': os.pathsep.join(pypath),
167 167 'HGRCPATH': '',
168 168 'LANGUAGE': 'C'}
169 169 if 'LD_LIBRARY_PATH' in os.environ:
170 170 env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']
171 171 if 'SystemRoot' in os.environ:
172 172 # Copy SystemRoot into the custom environment for Python 2.6
173 173 # under Windows. Otherwise, the subprocess will fail with
174 174 # error 0xc0150004. See: http://bugs.python.org/issue3440
175 175 env['SystemRoot'] = os.environ['SystemRoot']
176 176
177 177 if os.path.isdir('.hg'):
178 178 cmd = [sys.executable, 'hg', 'log', '-r', '.', '--template', '{tags}\n']
179 179 numerictags = [t for t in runhg(cmd, env).split() if t[0].isdigit()]
180 180 hgid = runhg([sys.executable, 'hg', 'id', '-i'], env).strip()
181 181 if numerictags: # tag(s) found
182 182 version = numerictags[-1]
183 183 if hgid.endswith('+'): # propagate the dirty status to the tag
184 184 version += '+'
185 185 else: # no tag found
186 186 cmd = [sys.executable, 'hg', 'parents', '--template',
187 187 '{latesttag}+{latesttagdistance}-']
188 188 version = runhg(cmd, env) + hgid
189 189 if version.endswith('+'):
190 190 version += time.strftime('%Y%m%d')
191 191 elif os.path.exists('.hg_archival.txt'):
192 192 kw = dict([[t.strip() for t in l.split(':', 1)]
193 193 for l in open('.hg_archival.txt')])
194 194 if 'tag' in kw:
195 195 version = kw['tag']
196 196 elif 'latesttag' in kw:
197 197 version = '%(latesttag)s+%(latesttagdistance)s-%(node).12s' % kw
198 198 else:
199 199 version = kw.get('node', '')[:12]
200 200
201 201 if version:
202 202 f = open("mercurial/__version__.py", "w")
203 203 f.write('# this file is autogenerated by setup.py\n')
204 204 f.write('version = "%s"\n' % version)
205 205 f.close()
206 206
207 207
208 208 try:
209 209 from mercurial import __version__
210 210 version = __version__.version
211 211 except ImportError:
212 212 version = 'unknown'
213 213
214 214 class hgbuild(build):
215 215 # Insert hgbuildmo first so that files in mercurial/locale/ are found
216 216 # when build_py is run next.
217 217 sub_commands = [('build_mo', None),
218 218
219 219 # We also need build_ext before build_py. Otherwise, when 2to3 is
220 220 # called (in build_py), it will not find osutil & friends,
221 221 # thinking that those modules are global and, consequently, making
222 222 # a mess, now that all module imports are global.
223 223
224 224 ('build_ext', build.has_ext_modules),
225 225 ] + build.sub_commands
226 226
227 227 class hgbuildmo(build):
228 228
229 229 description = "build translations (.mo files)"
230 230
231 231 def run(self):
232 232 if not find_executable('msgfmt'):
233 233 self.warn("could not find msgfmt executable, no translations "
234 234 "will be built")
235 235 return
236 236
237 237 podir = 'i18n'
238 238 if not os.path.isdir(podir):
239 239 self.warn("could not find %s/ directory" % podir)
240 240 return
241 241
242 242 join = os.path.join
243 243 for po in os.listdir(podir):
244 244 if not po.endswith('.po'):
245 245 continue
246 246 pofile = join(podir, po)
247 247 modir = join('locale', po[:-3], 'LC_MESSAGES')
248 248 mofile = join(modir, 'hg.mo')
249 249 mobuildfile = join('mercurial', mofile)
250 250 cmd = ['msgfmt', '-v', '-o', mobuildfile, pofile]
251 251 if sys.platform != 'sunos5':
252 252 # msgfmt on Solaris does not know about -c
253 253 cmd.append('-c')
254 254 self.mkpath(join('mercurial', modir))
255 255 self.make_file([pofile], mobuildfile, spawn, (cmd,))
256 256
257 257
258 258 class hgdist(Distribution):
259 259 pure = 0
260 260
261 261 global_options = Distribution.global_options + \
262 262 [('pure', None, "use pure (slow) Python "
263 263 "code instead of C extensions"),
264 264 ('c2to3', None, "(experimental!) convert "
265 265 "code with 2to3"),
266 266 ]
267 267
268 268 def has_ext_modules(self):
269 269 # self.ext_modules is emptied in hgbuildpy.finalize_options which is
270 270 # too late for some cases
271 271 return not self.pure and Distribution.has_ext_modules(self)
272 272
273 273 class hgbuildext(build_ext):
274 274
275 275 def build_extension(self, ext):
276 276 try:
277 277 build_ext.build_extension(self, ext)
278 278 except CCompilerError:
279 279 if not getattr(ext, 'optional', False):
280 280 raise
281 281 log.warn("Failed to build optional extension '%s' (skipping)",
282 282 ext.name)
283 283
284 284 class hgbuildpy(build_py):
285 285 if convert2to3:
286 286 fixer_names = sorted(set(getfixers("lib2to3.fixes") +
287 287 getfixers("hgfixes")))
288 288
289 289 def finalize_options(self):
290 290 build_py.finalize_options(self)
291 291
292 292 if self.distribution.pure:
293 293 if self.py_modules is None:
294 294 self.py_modules = []
295 295 for ext in self.distribution.ext_modules:
296 296 if ext.name.startswith("mercurial."):
297 297 self.py_modules.append("mercurial.pure.%s" % ext.name[10:])
298 298 self.distribution.ext_modules = []
299 299 else:
300 300 h = os.path.join(get_python_inc(), 'Python.h')
301 301 if not os.path.exists(h):
302 302 raise SystemExit('Python headers are required to build '
303 303 'Mercurial but weren\'t found in %s' % h)
304 304
305 305 def find_modules(self):
306 306 modules = build_py.find_modules(self)
307 307 for module in modules:
308 308 if module[0] == "mercurial.pure":
309 309 if module[1] != "__init__":
310 310 yield ("mercurial", module[1], module[2])
311 311 else:
312 312 yield module
313 313
314 314 class buildhgextindex(Command):
315 315 description = 'generate prebuilt index of hgext (for frozen package)'
316 316 user_options = []
317 317 _indexfilename = 'hgext/__index__.py'
318 318
319 319 def initialize_options(self):
320 320 pass
321 321
322 322 def finalize_options(self):
323 323 pass
324 324
325 325 def run(self):
326 326 if os.path.exists(self._indexfilename):
327 327 os.unlink(self._indexfilename)
328 328
329 329 # here no extension enabled, disabled() lists up everything
330 330 code = ('import pprint; from mercurial import extensions; '
331 331 'pprint.pprint(extensions.disabled())')
332 332 out, err = runcmd([sys.executable, '-c', code], env)
333 333 if err:
334 334 raise DistutilsExecError(err)
335 335
336 336 f = open(self._indexfilename, 'w')
337 337 f.write('# this file is autogenerated by setup.py\n')
338 338 f.write('docs = ')
339 339 f.write(out)
340 340 f.close()
341 341
342 342 class buildhgexe(build_ext):
343 343 description = 'compile hg.exe from mercurial/exewrapper.c'
344 344
345 345 def build_extensions(self):
346 346 if os.name != 'nt':
347 347 return
348 348 if isinstance(self.compiler, HackedMingw32CCompiler):
349 349 self.compiler.compiler_so = self.compiler.compiler # no -mdll
350 350 self.compiler.dll_libraries = [] # no -lmsrvc90
351 351 hv = sys.hexversion
352 352 pythonlib = 'python%d%d' % (hv >> 24, (hv >> 16) & 0xff)
353 353 f = open('mercurial/hgpythonlib.h', 'wb')
354 354 f.write('/* this file is autogenerated by setup.py */\n')
355 355 f.write('#define HGPYTHONLIB "%s"\n' % pythonlib)
356 356 f.close()
357 357 objects = self.compiler.compile(['mercurial/exewrapper.c'],
358 358 output_dir=self.build_temp)
359 359 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
360 360 target = os.path.join(dir, 'hg')
361 361 self.compiler.link_executable(objects, target,
362 362 libraries=[],
363 363 output_dir=self.build_temp)
364 364
365 365 class hginstallscripts(install_scripts):
366 366 '''
367 367 This is a specialization of install_scripts that replaces the @LIBDIR@ with
368 368 the configured directory for modules. If possible, the path is made relative
369 369 to the directory for scripts.
370 370 '''
371 371
372 372 def initialize_options(self):
373 373 install_scripts.initialize_options(self)
374 374
375 375 self.install_lib = None
376 376
377 377 def finalize_options(self):
378 378 install_scripts.finalize_options(self)
379 379 self.set_undefined_options('install',
380 380 ('install_lib', 'install_lib'))
381 381
382 382 def run(self):
383 383 install_scripts.run(self)
384 384
385 385 if (os.path.splitdrive(self.install_dir)[0] !=
386 386 os.path.splitdrive(self.install_lib)[0]):
387 387 # can't make relative paths from one drive to another, so use an
388 388 # absolute path instead
389 389 libdir = self.install_lib
390 390 else:
391 391 common = os.path.commonprefix((self.install_dir, self.install_lib))
392 392 rest = self.install_dir[len(common):]
393 393 uplevel = len([n for n in os.path.split(rest) if n])
394 394
395 395 libdir = uplevel * ('..' + os.sep) + self.install_lib[len(common):]
396 396
397 397 for outfile in self.outfiles:
398 398 fp = open(outfile, 'rb')
399 399 data = fp.read()
400 400 fp.close()
401 401
402 402 # skip binary files
403 403 if b('\0') in data:
404 404 continue
405 405
406 406 data = data.replace('@LIBDIR@', libdir.encode('string_escape'))
407 407 fp = open(outfile, 'wb')
408 408 fp.write(data)
409 409 fp.close()
410 410
411 411 cmdclass = {'build': hgbuild,
412 412 'build_mo': hgbuildmo,
413 413 'build_ext': hgbuildext,
414 414 'build_py': hgbuildpy,
415 415 'build_hgextindex': buildhgextindex,
416 416 'install_scripts': hginstallscripts,
417 417 'build_hgexe': buildhgexe,
418 418 }
419 419
420 420 packages = ['mercurial', 'mercurial.hgweb', 'mercurial.httpclient',
421 421 'hgext', 'hgext.convert', 'hgext.highlight', 'hgext.zeroconf',
422 422 'hgext.largefiles']
423 423
424 424 pymodules = []
425 425
426 426 common_depends = ['mercurial/util.h']
427 427
428 428 extmodules = [
429 429 Extension('mercurial.base85', ['mercurial/base85.c'],
430 430 depends=common_depends),
431 431 Extension('mercurial.bdiff', ['mercurial/bdiff.c'],
432 432 depends=common_depends),
433 433 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c'],
434 434 depends=common_depends),
435 435 Extension('mercurial.mpatch', ['mercurial/mpatch.c'],
436 436 depends=common_depends),
437 437 Extension('mercurial.parsers', ['mercurial/dirs.c',
438 438 'mercurial/parsers.c',
439 439 'mercurial/pathencode.c'],
440 440 depends=common_depends),
441 441 ]
442 442
443 443 osutil_ldflags = []
444 444
445 445 if sys.platform == 'darwin':
446 446 osutil_ldflags += ['-framework', 'ApplicationServices']
447 447
448 448 # disable osutil.c under windows + python 2.4 (issue1364)
449 449 if sys.platform == 'win32' and sys.version_info < (2, 5, 0, 'final'):
450 450 pymodules.append('mercurial.pure.osutil')
451 451 else:
452 452 extmodules.append(Extension('mercurial.osutil', ['mercurial/osutil.c'],
453 453 extra_link_args=osutil_ldflags,
454 454 depends=common_depends))
455 455
456 456 # the -mno-cygwin option has been deprecated for years
457 457 Mingw32CCompiler = cygwinccompiler.Mingw32CCompiler
458 458
459 459 class HackedMingw32CCompiler(cygwinccompiler.Mingw32CCompiler):
460 460 def __init__(self, *args, **kwargs):
461 461 Mingw32CCompiler.__init__(self, *args, **kwargs)
462 462 for i in 'compiler compiler_so linker_exe linker_so'.split():
463 463 try:
464 464 getattr(self, i).remove('-mno-cygwin')
465 465 except ValueError:
466 466 pass
467 467
468 468 cygwinccompiler.Mingw32CCompiler = HackedMingw32CCompiler
469 469
470 if sys.platform.startswith('linux') and os.uname()[2] > '2.6':
471 # The inotify extension is only usable with Linux 2.6 kernels.
472 # You also need a reasonably recent C library.
473 # In any case, if it fails to build the error will be skipped ('optional').
474 cc = new_compiler()
475 if hasfunction(cc, 'inotify_add_watch'):
476 inotify = Extension('hgext.inotify.linux._inotify',
477 ['hgext/inotify/linux/_inotify.c'],
478 ['mercurial'],
479 depends=common_depends)
480 inotify.optional = True
481 extmodules.append(inotify)
482 packages.extend(['hgext.inotify', 'hgext.inotify.linux'])
483
484 470 packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo',
485 471 'help/*.txt']}
486 472
487 473 def ordinarypath(p):
488 474 return p and p[0] != '.' and p[-1] != '~'
489 475
490 476 for root in ('templates',):
491 477 for curdir, dirs, files in os.walk(os.path.join('mercurial', root)):
492 478 curdir = curdir.split(os.sep, 1)[1]
493 479 dirs[:] = filter(ordinarypath, dirs)
494 480 for f in filter(ordinarypath, files):
495 481 f = os.path.join(curdir, f)
496 482 packagedata['mercurial'].append(f)
497 483
498 484 datafiles = []
499 485 setupversion = version
500 486 extra = {}
501 487
502 488 if py2exeloaded:
503 489 extra['console'] = [
504 490 {'script':'hg',
505 491 'copyright':'Copyright (C) 2005-2010 Matt Mackall and others',
506 492 'product_version':version}]
507 493 # sub command of 'build' because 'py2exe' does not handle sub_commands
508 494 build.sub_commands.insert(0, ('build_hgextindex', None))
509 495
510 496 if os.name == 'nt':
511 497 # Windows binary file versions for exe/dll files must have the
512 498 # form W.X.Y.Z, where W,X,Y,Z are numbers in the range 0..65535
513 499 setupversion = version.split('+', 1)[0]
514 500
515 501 if sys.platform == 'darwin' and os.path.exists('/usr/bin/xcodebuild'):
516 502 # XCode 4.0 dropped support for ppc architecture, which is hardcoded in
517 503 # distutils.sysconfig
518 504 version = runcmd(['/usr/bin/xcodebuild', '-version'], {})[0].splitlines()
519 505 if version:
520 506 version = version[0]
521 507 xcode4 = (version.startswith('Xcode') and
522 508 StrictVersion(version.split()[1]) >= StrictVersion('4.0'))
523 509 else:
524 510 # xcodebuild returns empty on OS X Lion with XCode 4.3 not
525 511 # installed, but instead with only command-line tools. Assume
526 512 # that only happens on >= Lion, thus no PPC support.
527 513 xcode4 = True
528 514
529 515 if xcode4:
530 516 os.environ['ARCHFLAGS'] = ''
531 517
532 518 setup(name='mercurial',
533 519 version=setupversion,
534 520 author='Matt Mackall and many others',
535 521 author_email='mercurial@selenic.com',
536 522 url='http://mercurial.selenic.com/',
537 523 download_url='http://mercurial.selenic.com/release/',
538 524 description=('Fast scalable distributed SCM (revision control, version '
539 525 'control) system'),
540 526 long_description=('Mercurial is a distributed SCM tool written in Python.'
541 527 ' It is used by a number of large projects that require'
542 528 ' fast, reliable distributed revision control, such as '
543 529 'Mozilla.'),
544 530 license='GNU GPLv2 or any later version',
545 531 classifiers=[
546 532 'Development Status :: 6 - Mature',
547 533 'Environment :: Console',
548 534 'Intended Audience :: Developers',
549 535 'Intended Audience :: System Administrators',
550 536 'License :: OSI Approved :: GNU General Public License (GPL)',
551 537 'Natural Language :: Danish',
552 538 'Natural Language :: English',
553 539 'Natural Language :: German',
554 540 'Natural Language :: Italian',
555 541 'Natural Language :: Japanese',
556 542 'Natural Language :: Portuguese (Brazilian)',
557 543 'Operating System :: Microsoft :: Windows',
558 544 'Operating System :: OS Independent',
559 545 'Operating System :: POSIX',
560 546 'Programming Language :: C',
561 547 'Programming Language :: Python',
562 548 'Topic :: Software Development :: Version Control',
563 549 ],
564 550 scripts=scripts,
565 551 packages=packages,
566 552 py_modules=pymodules,
567 553 ext_modules=extmodules,
568 554 data_files=datafiles,
569 555 package_data=packagedata,
570 556 cmdclass=cmdclass,
571 557 distclass=hgdist,
572 558 options=dict(py2exe=dict(packages=['hgext', 'email']),
573 559 bdist_mpkg=dict(zipdist=True,
574 560 license='COPYING',
575 561 readme='contrib/macosx/Readme.html',
576 562 welcome='contrib/macosx/Welcome.html')),
577 563 **extra)
@@ -1,35 +1,27 b''
1 1 # invalid filenames
2 2 test-add.t
3 3 test-init.t
4 4 test-clone.t
5 5 test-contrib.t
6 6 test-hgweb-raw.t
7 7 test-walk.t
8 8
9 9 # no sockets or fifos
10 10 test-hup.t
11 test-inotify-debuginotify.t
12 test-inotify-dirty-dirstate.t
13 test-inotify-issue1208.t
14 test-inotify-issue1371.t
15 test-inotify-issue1542.t
16 test-inotify-lookup.t
17 test-inotify.t
18 test-inotify-issue1556.t
19 11
20 12 # no hardlinks
21 13 test-hardlinks.t
22 14 test-relink.t
23 15
24 16 # exec bit problems
25 17 test-convert-bzr-114.t
26 18 test-convert-bzr-directories.t
27 19 test-convert-bzr-merges.t
28 20 test-convert-bzr-treeroot.t
29 21 test-convert-darcs.t
30 22 test-merge-tools.t
31 23
32 24 # debugstate exec bit false positives
33 25 test-dirstate.t
34 26 test-filebranch.t
35 27 test-merge-remove.t
@@ -1,344 +1,328 b''
1 1 import os, stat, socket
2 2 import re
3 3 import sys
4 4 import tempfile
5 5
6 6 tempprefix = 'hg-hghave-'
7 7
8 8 def matchoutput(cmd, regexp, ignorestatus=False):
9 9 """Return True if cmd executes successfully and its output
10 10 is matched by the supplied regular expression.
11 11 """
12 12 r = re.compile(regexp)
13 13 fh = os.popen(cmd)
14 14 s = fh.read()
15 15 try:
16 16 ret = fh.close()
17 17 except IOError:
18 18 # Happen in Windows test environment
19 19 ret = 1
20 20 return (ignorestatus or ret is None) and r.search(s)
21 21
22 22 def has_baz():
23 23 return matchoutput('baz --version 2>&1', r'baz Bazaar version')
24 24
25 25 def has_bzr():
26 26 try:
27 27 import bzrlib
28 28 return bzrlib.__doc__ is not None
29 29 except ImportError:
30 30 return False
31 31
32 32 def has_bzr114():
33 33 try:
34 34 import bzrlib
35 35 return (bzrlib.__doc__ is not None
36 36 and bzrlib.version_info[:2] >= (1, 14))
37 37 except ImportError:
38 38 return False
39 39
40 40 def has_cvs():
41 41 re = r'Concurrent Versions System.*?server'
42 42 return matchoutput('cvs --version 2>&1', re) and not has_msys()
43 43
44 44 def has_cvs112():
45 45 re = r'Concurrent Versions System \(CVS\) 1.12.*?server'
46 46 return matchoutput('cvs --version 2>&1', re) and not has_msys()
47 47
48 48 def has_darcs():
49 49 return matchoutput('darcs --version', r'2\.[2-9]', True)
50 50
51 51 def has_mtn():
52 52 return matchoutput('mtn --version', r'monotone', True) and not matchoutput(
53 53 'mtn --version', r'monotone 0\.', True)
54 54
55 55 def has_eol_in_paths():
56 56 try:
57 57 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix, suffix='\n\r')
58 58 os.close(fd)
59 59 os.remove(path)
60 60 return True
61 61 except (IOError, OSError):
62 62 return False
63 63
64 64 def has_executablebit():
65 65 try:
66 66 EXECFLAGS = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
67 67 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
68 68 try:
69 69 os.close(fh)
70 70 m = os.stat(fn).st_mode & 0777
71 71 new_file_has_exec = m & EXECFLAGS
72 72 os.chmod(fn, m ^ EXECFLAGS)
73 73 exec_flags_cannot_flip = ((os.stat(fn).st_mode & 0777) == m)
74 74 finally:
75 75 os.unlink(fn)
76 76 except (IOError, OSError):
77 77 # we don't care, the user probably won't be able to commit anyway
78 78 return False
79 79 return not (new_file_has_exec or exec_flags_cannot_flip)
80 80
81 81 def has_icasefs():
82 82 # Stolen from mercurial.util
83 83 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
84 84 os.close(fd)
85 85 try:
86 86 s1 = os.stat(path)
87 87 d, b = os.path.split(path)
88 88 p2 = os.path.join(d, b.upper())
89 89 if path == p2:
90 90 p2 = os.path.join(d, b.lower())
91 91 try:
92 92 s2 = os.stat(p2)
93 93 return s2 == s1
94 94 except OSError:
95 95 return False
96 96 finally:
97 97 os.remove(path)
98 98
99 def has_inotify():
100 try:
101 import hgext.inotify.linux.watcher
102 except ImportError:
103 return False
104 name = tempfile.mktemp(dir='.', prefix=tempprefix)
105 sock = socket.socket(socket.AF_UNIX)
106 try:
107 sock.bind(name)
108 except socket.error:
109 return False
110 sock.close()
111 os.unlink(name)
112 return True
113
114 99 def has_fifo():
115 100 if getattr(os, "mkfifo", None) is None:
116 101 return False
117 102 name = tempfile.mktemp(dir='.', prefix=tempprefix)
118 103 try:
119 104 os.mkfifo(name)
120 105 os.unlink(name)
121 106 return True
122 107 except OSError:
123 108 return False
124 109
125 110 def has_killdaemons():
126 111 return True
127 112
128 113 def has_cacheable_fs():
129 114 from mercurial import util
130 115
131 116 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
132 117 os.close(fd)
133 118 try:
134 119 return util.cachestat(path).cacheable()
135 120 finally:
136 121 os.remove(path)
137 122
138 123 def has_lsprof():
139 124 try:
140 125 import _lsprof
141 126 return True
142 127 except ImportError:
143 128 return False
144 129
145 130 def has_gettext():
146 131 return matchoutput('msgfmt --version', 'GNU gettext-tools')
147 132
148 133 def has_git():
149 134 return matchoutput('git --version 2>&1', r'^git version')
150 135
151 136 def has_docutils():
152 137 try:
153 138 from docutils.core import publish_cmdline
154 139 return True
155 140 except ImportError:
156 141 return False
157 142
158 143 def getsvnversion():
159 144 m = matchoutput('svn --version --quiet 2>&1', r'^(\d+)\.(\d+)')
160 145 if not m:
161 146 return (0, 0)
162 147 return (int(m.group(1)), int(m.group(2)))
163 148
164 149 def has_svn15():
165 150 return getsvnversion() >= (1, 5)
166 151
167 152 def has_svn13():
168 153 return getsvnversion() >= (1, 3)
169 154
170 155 def has_svn():
171 156 return matchoutput('svn --version 2>&1', r'^svn, version') and \
172 157 matchoutput('svnadmin --version 2>&1', r'^svnadmin, version')
173 158
174 159 def has_svn_bindings():
175 160 try:
176 161 import svn.core
177 162 version = svn.core.SVN_VER_MAJOR, svn.core.SVN_VER_MINOR
178 163 if version < (1, 4):
179 164 return False
180 165 return True
181 166 except ImportError:
182 167 return False
183 168
184 169 def has_p4():
185 170 return (matchoutput('p4 -V', r'Rev\. P4/') and
186 171 matchoutput('p4d -V', r'Rev\. P4D/'))
187 172
188 173 def has_symlink():
189 174 if getattr(os, "symlink", None) is None:
190 175 return False
191 176 name = tempfile.mktemp(dir='.', prefix=tempprefix)
192 177 try:
193 178 os.symlink(".", name)
194 179 os.unlink(name)
195 180 return True
196 181 except (OSError, AttributeError):
197 182 return False
198 183
199 184 def has_hardlink():
200 185 from mercurial import util
201 186 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
202 187 os.close(fh)
203 188 name = tempfile.mktemp(dir='.', prefix=tempprefix)
204 189 try:
205 190 try:
206 191 util.oslink(fn, name)
207 192 os.unlink(name)
208 193 return True
209 194 except OSError:
210 195 return False
211 196 finally:
212 197 os.unlink(fn)
213 198
214 199 def has_tla():
215 200 return matchoutput('tla --version 2>&1', r'The GNU Arch Revision')
216 201
217 202 def has_gpg():
218 203 return matchoutput('gpg --version 2>&1', r'GnuPG')
219 204
220 205 def has_unix_permissions():
221 206 d = tempfile.mkdtemp(dir='.', prefix=tempprefix)
222 207 try:
223 208 fname = os.path.join(d, 'foo')
224 209 for umask in (077, 007, 022):
225 210 os.umask(umask)
226 211 f = open(fname, 'w')
227 212 f.close()
228 213 mode = os.stat(fname).st_mode
229 214 os.unlink(fname)
230 215 if mode & 0777 != ~umask & 0666:
231 216 return False
232 217 return True
233 218 finally:
234 219 os.rmdir(d)
235 220
236 221 def has_root():
237 222 return getattr(os, 'geteuid', None) and os.geteuid() == 0
238 223
239 224 def has_pyflakes():
240 225 return matchoutput("sh -c \"echo 'import re' 2>&1 | pyflakes\"",
241 226 r"<stdin>:1: 're' imported but unused",
242 227 True)
243 228
244 229 def has_pygments():
245 230 try:
246 231 import pygments
247 232 return True
248 233 except ImportError:
249 234 return False
250 235
251 236 def has_python243():
252 237 return sys.version_info >= (2, 4, 3)
253 238
254 239 def has_outer_repo():
255 240 # failing for other reasons than 'no repo' imply that there is a repo
256 241 return not matchoutput('hg root 2>&1',
257 242 r'abort: no repository found', True)
258 243
259 244 def has_ssl():
260 245 try:
261 246 import ssl
262 247 import OpenSSL
263 248 OpenSSL.SSL.Context
264 249 return True
265 250 except ImportError:
266 251 return False
267 252
268 253 def has_windows():
269 254 return os.name == 'nt'
270 255
271 256 def has_system_sh():
272 257 return os.name != 'nt'
273 258
274 259 def has_serve():
275 260 return os.name != 'nt' # gross approximation
276 261
277 262 def has_tic():
278 263 try:
279 264 import curses
280 265 curses.COLOR_BLUE
281 266 return matchoutput('test -x "`which tic`"', '')
282 267 except ImportError:
283 268 return False
284 269
285 270 def has_msys():
286 271 return os.getenv('MSYSTEM')
287 272
288 273 def has_aix():
289 274 return sys.platform.startswith("aix")
290 275
291 276 def has_absimport():
292 277 import __future__
293 278 from mercurial import util
294 279 return util.safehasattr(__future__, "absolute_import")
295 280
296 281 def has_py3k():
297 282 return 3 == sys.version_info[0]
298 283
299 284 checks = {
300 285 "true": (lambda: True, "yak shaving"),
301 286 "false": (lambda: False, "nail clipper"),
302 287 "baz": (has_baz, "GNU Arch baz client"),
303 288 "bzr": (has_bzr, "Canonical's Bazaar client"),
304 289 "bzr114": (has_bzr114, "Canonical's Bazaar client >= 1.14"),
305 290 "cacheable": (has_cacheable_fs, "cacheable filesystem"),
306 291 "cvs": (has_cvs, "cvs client/server"),
307 292 "cvs112": (has_cvs112, "cvs client/server >= 1.12"),
308 293 "darcs": (has_darcs, "darcs client"),
309 294 "docutils": (has_docutils, "Docutils text processing library"),
310 295 "eol-in-paths": (has_eol_in_paths, "end-of-lines in paths"),
311 296 "execbit": (has_executablebit, "executable bit"),
312 297 "fifo": (has_fifo, "named pipes"),
313 298 "gettext": (has_gettext, "GNU Gettext (msgfmt)"),
314 299 "git": (has_git, "git command line client"),
315 300 "gpg": (has_gpg, "gpg client"),
316 301 "hardlink": (has_hardlink, "hardlinks"),
317 302 "icasefs": (has_icasefs, "case insensitive file system"),
318 "inotify": (has_inotify, "inotify extension support"),
319 303 "killdaemons": (has_killdaemons, 'killdaemons.py support'),
320 304 "lsprof": (has_lsprof, "python lsprof module"),
321 305 "mtn": (has_mtn, "monotone client (>= 1.0)"),
322 306 "outer-repo": (has_outer_repo, "outer repo"),
323 307 "p4": (has_p4, "Perforce server and client"),
324 308 "pyflakes": (has_pyflakes, "Pyflakes python linter"),
325 309 "pygments": (has_pygments, "Pygments source highlighting library"),
326 310 "python243": (has_python243, "python >= 2.4.3"),
327 311 "root": (has_root, "root permissions"),
328 312 "serve": (has_serve, "platform and python can manage 'hg serve -d'"),
329 313 "ssl": (has_ssl, "python >= 2.6 ssl module and python OpenSSL"),
330 314 "svn": (has_svn, "subversion client and admin tools"),
331 315 "svn13": (has_svn13, "subversion client and admin tools >= 1.3"),
332 316 "svn15": (has_svn15, "subversion client and admin tools >= 1.5"),
333 317 "svn-bindings": (has_svn_bindings, "subversion python bindings"),
334 318 "symlink": (has_symlink, "symbolic links"),
335 319 "system-sh": (has_system_sh, "system() uses sh"),
336 320 "tic": (has_tic, "terminfo compiler and curses module"),
337 321 "tla": (has_tla, "GNU Arch tla client"),
338 322 "unix-permissions": (has_unix_permissions, "unix-style permissions"),
339 323 "windows": (has_windows, "Windows"),
340 324 "msys": (has_msys, "Windows with MSYS"),
341 325 "aix": (has_aix, "AIX"),
342 326 "absimport": (has_absimport, "absolute_import in __future__"),
343 327 "py3k": (has_py3k, "running with Python 3.x"),
344 328 }
@@ -1,1302 +1,1294 b''
1 1 #!/usr/bin/env python
2 2 #
3 3 # run-tests.py - Run a set of tests on Mercurial
4 4 #
5 5 # Copyright 2006 Matt Mackall <mpm@selenic.com>
6 6 #
7 7 # This software may be used and distributed according to the terms of the
8 8 # GNU General Public License version 2 or any later version.
9 9
10 10 # Modifying this script is tricky because it has many modes:
11 11 # - serial (default) vs parallel (-jN, N > 1)
12 12 # - no coverage (default) vs coverage (-c, -C, -s)
13 13 # - temp install (default) vs specific hg script (--with-hg, --local)
14 14 # - tests are a mix of shell scripts and Python scripts
15 15 #
16 16 # If you change this script, it is recommended that you ensure you
17 17 # haven't broken it by running it in various modes with a representative
18 18 # sample of test scripts. For example:
19 19 #
20 20 # 1) serial, no coverage, temp install:
21 21 # ./run-tests.py test-s*
22 22 # 2) serial, no coverage, local hg:
23 23 # ./run-tests.py --local test-s*
24 24 # 3) serial, coverage, temp install:
25 25 # ./run-tests.py -c test-s*
26 26 # 4) serial, coverage, local hg:
27 27 # ./run-tests.py -c --local test-s* # unsupported
28 28 # 5) parallel, no coverage, temp install:
29 29 # ./run-tests.py -j2 test-s*
30 30 # 6) parallel, no coverage, local hg:
31 31 # ./run-tests.py -j2 --local test-s*
32 32 # 7) parallel, coverage, temp install:
33 33 # ./run-tests.py -j2 -c test-s* # currently broken
34 34 # 8) parallel, coverage, local install:
35 35 # ./run-tests.py -j2 -c --local test-s* # unsupported (and broken)
36 36 # 9) parallel, custom tmp dir:
37 37 # ./run-tests.py -j2 --tmpdir /tmp/myhgtests
38 38 #
39 39 # (You could use any subset of the tests: test-s* happens to match
40 40 # enough that it's worth doing parallel runs, few enough that it
41 41 # completes fairly quickly, includes both shell and Python scripts, and
42 42 # includes some scripts that run daemon processes.)
43 43
44 44 from distutils import version
45 45 import difflib
46 46 import errno
47 47 import optparse
48 48 import os
49 49 import shutil
50 50 import subprocess
51 51 import signal
52 52 import sys
53 53 import tempfile
54 54 import time
55 55 import random
56 56 import re
57 57 import threading
58 58 import killdaemons as killmod
59 59 import Queue as queue
60 60
61 61 processlock = threading.Lock()
62 62
63 63 # subprocess._cleanup can race with any Popen.wait or Popen.poll on py24
64 64 # http://bugs.python.org/issue1731717 for details. We shouldn't be producing
65 65 # zombies but it's pretty harmless even if we do.
66 66 if sys.version_info < (2, 5):
67 67 subprocess._cleanup = lambda: None
68 68
69 69 closefds = os.name == 'posix'
70 70 def Popen4(cmd, wd, timeout, env=None):
71 71 processlock.acquire()
72 72 p = subprocess.Popen(cmd, shell=True, bufsize=-1, cwd=wd, env=env,
73 73 close_fds=closefds,
74 74 stdin=subprocess.PIPE, stdout=subprocess.PIPE,
75 75 stderr=subprocess.STDOUT)
76 76 processlock.release()
77 77
78 78 p.fromchild = p.stdout
79 79 p.tochild = p.stdin
80 80 p.childerr = p.stderr
81 81
82 82 p.timeout = False
83 83 if timeout:
84 84 def t():
85 85 start = time.time()
86 86 while time.time() - start < timeout and p.returncode is None:
87 87 time.sleep(.1)
88 88 p.timeout = True
89 89 if p.returncode is None:
90 90 terminate(p)
91 91 threading.Thread(target=t).start()
92 92
93 93 return p
94 94
95 95 # reserved exit code to skip test (used by hghave)
96 96 SKIPPED_STATUS = 80
97 97 SKIPPED_PREFIX = 'skipped: '
98 98 FAILED_PREFIX = 'hghave check failed: '
99 99 PYTHON = sys.executable.replace('\\', '/')
100 100 IMPL_PATH = 'PYTHONPATH'
101 101 if 'java' in sys.platform:
102 102 IMPL_PATH = 'JYTHONPATH'
103 103
104 104 requiredtools = [os.path.basename(sys.executable), "diff", "grep", "unzip",
105 105 "gunzip", "bunzip2", "sed"]
106 106 createdfiles = []
107 107
108 108 defaults = {
109 109 'jobs': ('HGTEST_JOBS', 1),
110 110 'timeout': ('HGTEST_TIMEOUT', 180),
111 111 'port': ('HGTEST_PORT', 20059),
112 112 'shell': ('HGTEST_SHELL', 'sh'),
113 113 }
114 114
115 115 def parselistfiles(files, listtype, warn=True):
116 116 entries = dict()
117 117 for filename in files:
118 118 try:
119 119 path = os.path.expanduser(os.path.expandvars(filename))
120 120 f = open(path, "r")
121 121 except IOError, err:
122 122 if err.errno != errno.ENOENT:
123 123 raise
124 124 if warn:
125 125 print "warning: no such %s file: %s" % (listtype, filename)
126 126 continue
127 127
128 128 for line in f.readlines():
129 129 line = line.split('#', 1)[0].strip()
130 130 if line:
131 131 entries[line] = filename
132 132
133 133 f.close()
134 134 return entries
135 135
136 136 def parseargs():
137 137 parser = optparse.OptionParser("%prog [options] [tests]")
138 138
139 139 # keep these sorted
140 140 parser.add_option("--blacklist", action="append",
141 141 help="skip tests listed in the specified blacklist file")
142 142 parser.add_option("--whitelist", action="append",
143 143 help="always run tests listed in the specified whitelist file")
144 144 parser.add_option("-C", "--annotate", action="store_true",
145 145 help="output files annotated with coverage")
146 146 parser.add_option("-c", "--cover", action="store_true",
147 147 help="print a test coverage report")
148 148 parser.add_option("-d", "--debug", action="store_true",
149 149 help="debug mode: write output of test scripts to console"
150 150 " rather than capturing and diff'ing it (disables timeout)")
151 151 parser.add_option("-f", "--first", action="store_true",
152 152 help="exit on the first test failure")
153 153 parser.add_option("-H", "--htmlcov", action="store_true",
154 154 help="create an HTML report of the coverage of the files")
155 parser.add_option("--inotify", action="store_true",
156 help="enable inotify extension when running tests")
157 155 parser.add_option("-i", "--interactive", action="store_true",
158 156 help="prompt to accept changed output")
159 157 parser.add_option("-j", "--jobs", type="int",
160 158 help="number of jobs to run in parallel"
161 159 " (default: $%s or %d)" % defaults['jobs'])
162 160 parser.add_option("--keep-tmpdir", action="store_true",
163 161 help="keep temporary directory after running tests")
164 162 parser.add_option("-k", "--keywords",
165 163 help="run tests matching keywords")
166 164 parser.add_option("-l", "--local", action="store_true",
167 165 help="shortcut for --with-hg=<testdir>/../hg")
168 166 parser.add_option("--loop", action="store_true",
169 167 help="loop tests repeatedly")
170 168 parser.add_option("-n", "--nodiff", action="store_true",
171 169 help="skip showing test changes")
172 170 parser.add_option("-p", "--port", type="int",
173 171 help="port on which servers should listen"
174 172 " (default: $%s or %d)" % defaults['port'])
175 173 parser.add_option("--compiler", type="string",
176 174 help="compiler to build with")
177 175 parser.add_option("--pure", action="store_true",
178 176 help="use pure Python code instead of C extensions")
179 177 parser.add_option("-R", "--restart", action="store_true",
180 178 help="restart at last error")
181 179 parser.add_option("-r", "--retest", action="store_true",
182 180 help="retest failed tests")
183 181 parser.add_option("-S", "--noskips", action="store_true",
184 182 help="don't report skip tests verbosely")
185 183 parser.add_option("--shell", type="string",
186 184 help="shell to use (default: $%s or %s)" % defaults['shell'])
187 185 parser.add_option("-t", "--timeout", type="int",
188 186 help="kill errant tests after TIMEOUT seconds"
189 187 " (default: $%s or %d)" % defaults['timeout'])
190 188 parser.add_option("--time", action="store_true",
191 189 help="time how long each test takes")
192 190 parser.add_option("--tmpdir", type="string",
193 191 help="run tests in the given temporary directory"
194 192 " (implies --keep-tmpdir)")
195 193 parser.add_option("-v", "--verbose", action="store_true",
196 194 help="output verbose messages")
197 195 parser.add_option("--view", type="string",
198 196 help="external diff viewer")
199 197 parser.add_option("--with-hg", type="string",
200 198 metavar="HG",
201 199 help="test using specified hg script rather than a "
202 200 "temporary installation")
203 201 parser.add_option("-3", "--py3k-warnings", action="store_true",
204 202 help="enable Py3k warnings on Python 2.6+")
205 203 parser.add_option('--extra-config-opt', action="append",
206 204 help='set the given config opt in the test hgrc')
207 205 parser.add_option('--random', action="store_true",
208 206 help='run tests in random order')
209 207
210 208 for option, (envvar, default) in defaults.items():
211 209 defaults[option] = type(default)(os.environ.get(envvar, default))
212 210 parser.set_defaults(**defaults)
213 211 (options, args) = parser.parse_args()
214 212
215 213 # jython is always pure
216 214 if 'java' in sys.platform or '__pypy__' in sys.modules:
217 215 options.pure = True
218 216
219 217 if options.with_hg:
220 218 options.with_hg = os.path.expanduser(options.with_hg)
221 219 if not (os.path.isfile(options.with_hg) and
222 220 os.access(options.with_hg, os.X_OK)):
223 221 parser.error('--with-hg must specify an executable hg script')
224 222 if not os.path.basename(options.with_hg) == 'hg':
225 223 sys.stderr.write('warning: --with-hg should specify an hg script\n')
226 224 if options.local:
227 225 testdir = os.path.dirname(os.path.realpath(sys.argv[0]))
228 226 hgbin = os.path.join(os.path.dirname(testdir), 'hg')
229 227 if os.name != 'nt' and not os.access(hgbin, os.X_OK):
230 228 parser.error('--local specified, but %r not found or not executable'
231 229 % hgbin)
232 230 options.with_hg = hgbin
233 231
234 232 options.anycoverage = options.cover or options.annotate or options.htmlcov
235 233 if options.anycoverage:
236 234 try:
237 235 import coverage
238 236 covver = version.StrictVersion(coverage.__version__).version
239 237 if covver < (3, 3):
240 238 parser.error('coverage options require coverage 3.3 or later')
241 239 except ImportError:
242 240 parser.error('coverage options now require the coverage package')
243 241
244 242 if options.anycoverage and options.local:
245 243 # this needs some path mangling somewhere, I guess
246 244 parser.error("sorry, coverage options do not work when --local "
247 245 "is specified")
248 246
249 247 global verbose
250 248 if options.verbose:
251 249 verbose = ''
252 250
253 251 if options.tmpdir:
254 252 options.tmpdir = os.path.expanduser(options.tmpdir)
255 253
256 254 if options.jobs < 1:
257 255 parser.error('--jobs must be positive')
258 256 if options.interactive and options.debug:
259 257 parser.error("-i/--interactive and -d/--debug are incompatible")
260 258 if options.debug:
261 259 if options.timeout != defaults['timeout']:
262 260 sys.stderr.write(
263 261 'warning: --timeout option ignored with --debug\n')
264 262 options.timeout = 0
265 263 if options.py3k_warnings:
266 264 if sys.version_info[:2] < (2, 6) or sys.version_info[:2] >= (3, 0):
267 265 parser.error('--py3k-warnings can only be used on Python 2.6+')
268 266 if options.blacklist:
269 267 options.blacklist = parselistfiles(options.blacklist, 'blacklist')
270 268 if options.whitelist:
271 269 options.whitelisted = parselistfiles(options.whitelist, 'whitelist')
272 270 else:
273 271 options.whitelisted = {}
274 272
275 273 return (options, args)
276 274
277 275 def rename(src, dst):
278 276 """Like os.rename(), trade atomicity and opened files friendliness
279 277 for existing destination support.
280 278 """
281 279 shutil.copy(src, dst)
282 280 os.remove(src)
283 281
284 282 def parsehghaveoutput(lines):
285 283 '''Parse hghave log lines.
286 284 Return tuple of lists (missing, failed):
287 285 * the missing/unknown features
288 286 * the features for which existence check failed'''
289 287 missing = []
290 288 failed = []
291 289 for line in lines:
292 290 if line.startswith(SKIPPED_PREFIX):
293 291 line = line.splitlines()[0]
294 292 missing.append(line[len(SKIPPED_PREFIX):])
295 293 elif line.startswith(FAILED_PREFIX):
296 294 line = line.splitlines()[0]
297 295 failed.append(line[len(FAILED_PREFIX):])
298 296
299 297 return missing, failed
300 298
301 299 def showdiff(expected, output, ref, err):
302 300 print
303 301 for line in difflib.unified_diff(expected, output, ref, err):
304 302 sys.stdout.write(line)
305 303
306 304 verbose = False
307 305 def vlog(*msg):
308 306 if verbose is not False:
309 307 iolock.acquire()
310 308 if verbose:
311 309 print verbose,
312 310 for m in msg:
313 311 print m,
314 312 print
315 313 sys.stdout.flush()
316 314 iolock.release()
317 315
318 316 def log(*msg):
319 317 iolock.acquire()
320 318 if verbose:
321 319 print verbose,
322 320 for m in msg:
323 321 print m,
324 322 print
325 323 sys.stdout.flush()
326 324 iolock.release()
327 325
328 326 def findprogram(program):
329 327 """Search PATH for a executable program"""
330 328 for p in os.environ.get('PATH', os.defpath).split(os.pathsep):
331 329 name = os.path.join(p, program)
332 330 if os.name == 'nt' or os.access(name, os.X_OK):
333 331 return name
334 332 return None
335 333
336 334 def createhgrc(path, options):
337 335 # create a fresh hgrc
338 336 hgrc = open(path, 'w')
339 337 hgrc.write('[ui]\n')
340 338 hgrc.write('slash = True\n')
341 339 hgrc.write('interactive = False\n')
342 340 hgrc.write('[defaults]\n')
343 341 hgrc.write('backout = -d "0 0"\n')
344 342 hgrc.write('commit = -d "0 0"\n')
345 343 hgrc.write('shelve = --date "0 0"\n')
346 344 hgrc.write('tag = -d "0 0"\n')
347 if options.inotify:
348 hgrc.write('[extensions]\n')
349 hgrc.write('inotify=\n')
350 hgrc.write('[inotify]\n')
351 hgrc.write('pidfile=daemon.pids')
352 hgrc.write('appendpid=True\n')
353 345 if options.extra_config_opt:
354 346 for opt in options.extra_config_opt:
355 347 section, key = opt.split('.', 1)
356 348 assert '=' in key, ('extra config opt %s must '
357 349 'have an = for assignment' % opt)
358 350 hgrc.write('[%s]\n%s\n' % (section, key))
359 351 hgrc.close()
360 352
361 353 def createenv(options, testtmp, threadtmp, port):
362 354 env = os.environ.copy()
363 355 env['TESTTMP'] = testtmp
364 356 env['HOME'] = testtmp
365 357 env["HGPORT"] = str(port)
366 358 env["HGPORT1"] = str(port + 1)
367 359 env["HGPORT2"] = str(port + 2)
368 360 env["HGRCPATH"] = os.path.join(threadtmp, '.hgrc')
369 361 env["DAEMON_PIDS"] = os.path.join(threadtmp, 'daemon.pids')
370 362 env["HGEDITOR"] = sys.executable + ' -c "import sys; sys.exit(0)"'
371 363 env["HGMERGE"] = "internal:merge"
372 364 env["HGUSER"] = "test"
373 365 env["HGENCODING"] = "ascii"
374 366 env["HGENCODINGMODE"] = "strict"
375 367
376 368 # Reset some environment variables to well-known values so that
377 369 # the tests produce repeatable output.
378 370 env['LANG'] = env['LC_ALL'] = env['LANGUAGE'] = 'C'
379 371 env['TZ'] = 'GMT'
380 372 env["EMAIL"] = "Foo Bar <foo.bar@example.com>"
381 373 env['COLUMNS'] = '80'
382 374 env['TERM'] = 'xterm'
383 375
384 376 for k in ('HG HGPROF CDPATH GREP_OPTIONS http_proxy no_proxy ' +
385 377 'NO_PROXY').split():
386 378 if k in env:
387 379 del env[k]
388 380
389 381 # unset env related to hooks
390 382 for k in env.keys():
391 383 if k.startswith('HG_'):
392 384 del env[k]
393 385
394 386 return env
395 387
396 388 def checktools():
397 389 # Before we go any further, check for pre-requisite tools
398 390 # stuff from coreutils (cat, rm, etc) are not tested
399 391 for p in requiredtools:
400 392 if os.name == 'nt' and not p.endswith('.exe'):
401 393 p += '.exe'
402 394 found = findprogram(p)
403 395 if found:
404 396 vlog("# Found prerequisite", p, "at", found)
405 397 else:
406 398 print "WARNING: Did not find prerequisite tool: "+p
407 399
408 400 def terminate(proc):
409 401 """Terminate subprocess (with fallback for Python versions < 2.6)"""
410 402 vlog('# Terminating process %d' % proc.pid)
411 403 try:
412 404 getattr(proc, 'terminate', lambda : os.kill(proc.pid, signal.SIGTERM))()
413 405 except OSError:
414 406 pass
415 407
416 408 def killdaemons(pidfile):
417 409 return killmod.killdaemons(pidfile, tryhard=False, remove=True,
418 410 logfn=vlog)
419 411
420 412 def cleanup(options):
421 413 if not options.keep_tmpdir:
422 414 vlog("# Cleaning up HGTMP", HGTMP)
423 415 shutil.rmtree(HGTMP, True)
424 416 for f in createdfiles:
425 417 try:
426 418 os.remove(f)
427 419 except OSError:
428 420 pass
429 421
430 422 def usecorrectpython():
431 423 # some tests run python interpreter. they must use same
432 424 # interpreter we use or bad things will happen.
433 425 pyexename = sys.platform == 'win32' and 'python.exe' or 'python'
434 426 if getattr(os, 'symlink', None):
435 427 vlog("# Making python executable in test path a symlink to '%s'" %
436 428 sys.executable)
437 429 mypython = os.path.join(TMPBINDIR, pyexename)
438 430 try:
439 431 if os.readlink(mypython) == sys.executable:
440 432 return
441 433 os.unlink(mypython)
442 434 except OSError, err:
443 435 if err.errno != errno.ENOENT:
444 436 raise
445 437 if findprogram(pyexename) != sys.executable:
446 438 try:
447 439 os.symlink(sys.executable, mypython)
448 440 createdfiles.append(mypython)
449 441 except OSError, err:
450 442 # child processes may race, which is harmless
451 443 if err.errno != errno.EEXIST:
452 444 raise
453 445 else:
454 446 exedir, exename = os.path.split(sys.executable)
455 447 vlog("# Modifying search path to find %s as %s in '%s'" %
456 448 (exename, pyexename, exedir))
457 449 path = os.environ['PATH'].split(os.pathsep)
458 450 while exedir in path:
459 451 path.remove(exedir)
460 452 os.environ['PATH'] = os.pathsep.join([exedir] + path)
461 453 if not findprogram(pyexename):
462 454 print "WARNING: Cannot find %s in search path" % pyexename
463 455
464 456 def installhg(options):
465 457 vlog("# Performing temporary installation of HG")
466 458 installerrs = os.path.join("tests", "install.err")
467 459 compiler = ''
468 460 if options.compiler:
469 461 compiler = '--compiler ' + options.compiler
470 462 pure = options.pure and "--pure" or ""
471 463 py3 = ''
472 464 if sys.version_info[0] == 3:
473 465 py3 = '--c2to3'
474 466
475 467 # Run installer in hg root
476 468 script = os.path.realpath(sys.argv[0])
477 469 hgroot = os.path.dirname(os.path.dirname(script))
478 470 os.chdir(hgroot)
479 471 nohome = '--home=""'
480 472 if os.name == 'nt':
481 473 # The --home="" trick works only on OS where os.sep == '/'
482 474 # because of a distutils convert_path() fast-path. Avoid it at
483 475 # least on Windows for now, deal with .pydistutils.cfg bugs
484 476 # when they happen.
485 477 nohome = ''
486 478 cmd = ('%(exe)s setup.py %(py3)s %(pure)s clean --all'
487 479 ' build %(compiler)s --build-base="%(base)s"'
488 480 ' install --force --prefix="%(prefix)s" --install-lib="%(libdir)s"'
489 481 ' --install-scripts="%(bindir)s" %(nohome)s >%(logfile)s 2>&1'
490 482 % dict(exe=sys.executable, py3=py3, pure=pure, compiler=compiler,
491 483 base=os.path.join(HGTMP, "build"),
492 484 prefix=INST, libdir=PYTHONDIR, bindir=BINDIR,
493 485 nohome=nohome, logfile=installerrs))
494 486 vlog("# Running", cmd)
495 487 if os.system(cmd) == 0:
496 488 if not options.verbose:
497 489 os.remove(installerrs)
498 490 else:
499 491 f = open(installerrs)
500 492 for line in f:
501 493 print line,
502 494 f.close()
503 495 sys.exit(1)
504 496 os.chdir(TESTDIR)
505 497
506 498 usecorrectpython()
507 499
508 500 if options.py3k_warnings and not options.anycoverage:
509 501 vlog("# Updating hg command to enable Py3k Warnings switch")
510 502 f = open(os.path.join(BINDIR, 'hg'), 'r')
511 503 lines = [line.rstrip() for line in f]
512 504 lines[0] += ' -3'
513 505 f.close()
514 506 f = open(os.path.join(BINDIR, 'hg'), 'w')
515 507 for line in lines:
516 508 f.write(line + '\n')
517 509 f.close()
518 510
519 511 hgbat = os.path.join(BINDIR, 'hg.bat')
520 512 if os.path.isfile(hgbat):
521 513 # hg.bat expects to be put in bin/scripts while run-tests.py
522 514 # installation layout put it in bin/ directly. Fix it
523 515 f = open(hgbat, 'rb')
524 516 data = f.read()
525 517 f.close()
526 518 if '"%~dp0..\python" "%~dp0hg" %*' in data:
527 519 data = data.replace('"%~dp0..\python" "%~dp0hg" %*',
528 520 '"%~dp0python" "%~dp0hg" %*')
529 521 f = open(hgbat, 'wb')
530 522 f.write(data)
531 523 f.close()
532 524 else:
533 525 print 'WARNING: cannot fix hg.bat reference to python.exe'
534 526
535 527 if options.anycoverage:
536 528 custom = os.path.join(TESTDIR, 'sitecustomize.py')
537 529 target = os.path.join(PYTHONDIR, 'sitecustomize.py')
538 530 vlog('# Installing coverage trigger to %s' % target)
539 531 shutil.copyfile(custom, target)
540 532 rc = os.path.join(TESTDIR, '.coveragerc')
541 533 vlog('# Installing coverage rc to %s' % rc)
542 534 os.environ['COVERAGE_PROCESS_START'] = rc
543 535 fn = os.path.join(INST, '..', '.coverage')
544 536 os.environ['COVERAGE_FILE'] = fn
545 537
546 538 def outputtimes(options):
547 539 vlog('# Producing time report')
548 540 times.sort(key=lambda t: (t[1], t[0]), reverse=True)
549 541 cols = '%7.3f %s'
550 542 print '\n%-7s %s' % ('Time', 'Test')
551 543 for test, timetaken in times:
552 544 print cols % (timetaken, test)
553 545
554 546 def outputcoverage(options):
555 547
556 548 vlog('# Producing coverage report')
557 549 os.chdir(PYTHONDIR)
558 550
559 551 def covrun(*args):
560 552 cmd = 'coverage %s' % ' '.join(args)
561 553 vlog('# Running: %s' % cmd)
562 554 os.system(cmd)
563 555
564 556 covrun('-c')
565 557 omit = ','.join(os.path.join(x, '*') for x in [BINDIR, TESTDIR])
566 558 covrun('-i', '-r', '"--omit=%s"' % omit) # report
567 559 if options.htmlcov:
568 560 htmldir = os.path.join(TESTDIR, 'htmlcov')
569 561 covrun('-i', '-b', '"--directory=%s"' % htmldir, '"--omit=%s"' % omit)
570 562 if options.annotate:
571 563 adir = os.path.join(TESTDIR, 'annotated')
572 564 if not os.path.isdir(adir):
573 565 os.mkdir(adir)
574 566 covrun('-i', '-a', '"--directory=%s"' % adir, '"--omit=%s"' % omit)
575 567
576 568 def pytest(test, wd, options, replacements, env):
577 569 py3kswitch = options.py3k_warnings and ' -3' or ''
578 570 cmd = '%s%s "%s"' % (PYTHON, py3kswitch, test)
579 571 vlog("# Running", cmd)
580 572 if os.name == 'nt':
581 573 replacements.append((r'\r\n', '\n'))
582 574 return run(cmd, wd, options, replacements, env)
583 575
584 576 needescape = re.compile(r'[\x00-\x08\x0b-\x1f\x7f-\xff]').search
585 577 escapesub = re.compile(r'[\x00-\x08\x0b-\x1f\\\x7f-\xff]').sub
586 578 escapemap = dict((chr(i), r'\x%02x' % i) for i in range(256))
587 579 escapemap.update({'\\': '\\\\', '\r': r'\r'})
588 580 def escapef(m):
589 581 return escapemap[m.group(0)]
590 582 def stringescape(s):
591 583 return escapesub(escapef, s)
592 584
593 585 def rematch(el, l):
594 586 try:
595 587 # use \Z to ensure that the regex matches to the end of the string
596 588 if os.name == 'nt':
597 589 return re.match(el + r'\r?\n\Z', l)
598 590 return re.match(el + r'\n\Z', l)
599 591 except re.error:
600 592 # el is an invalid regex
601 593 return False
602 594
603 595 def globmatch(el, l):
604 596 # The only supported special characters are * and ? plus / which also
605 597 # matches \ on windows. Escaping of these caracters is supported.
606 598 if el + '\n' == l:
607 599 if os.altsep:
608 600 # matching on "/" is not needed for this line
609 601 return '-glob'
610 602 return True
611 603 i, n = 0, len(el)
612 604 res = ''
613 605 while i < n:
614 606 c = el[i]
615 607 i += 1
616 608 if c == '\\' and el[i] in '*?\\/':
617 609 res += el[i - 1:i + 1]
618 610 i += 1
619 611 elif c == '*':
620 612 res += '.*'
621 613 elif c == '?':
622 614 res += '.'
623 615 elif c == '/' and os.altsep:
624 616 res += '[/\\\\]'
625 617 else:
626 618 res += re.escape(c)
627 619 return rematch(res, l)
628 620
629 621 def linematch(el, l):
630 622 if el == l: # perfect match (fast)
631 623 return True
632 624 if el:
633 625 if el.endswith(" (esc)\n"):
634 626 el = el[:-7].decode('string-escape') + '\n'
635 627 if el == l or os.name == 'nt' and el[:-1] + '\r\n' == l:
636 628 return True
637 629 if el.endswith(" (re)\n"):
638 630 return rematch(el[:-6], l)
639 631 if el.endswith(" (glob)\n"):
640 632 return globmatch(el[:-8], l)
641 633 if os.altsep and l.replace('\\', '/') == el:
642 634 return '+glob'
643 635 return False
644 636
645 637 def tsttest(test, wd, options, replacements, env):
646 638 # We generate a shell script which outputs unique markers to line
647 639 # up script results with our source. These markers include input
648 640 # line number and the last return code
649 641 salt = "SALT" + str(time.time())
650 642 def addsalt(line, inpython):
651 643 if inpython:
652 644 script.append('%s %d 0\n' % (salt, line))
653 645 else:
654 646 script.append('echo %s %s $?\n' % (salt, line))
655 647
656 648 # After we run the shell script, we re-unify the script output
657 649 # with non-active parts of the source, with synchronization by our
658 650 # SALT line number markers. The after table contains the
659 651 # non-active components, ordered by line number
660 652 after = {}
661 653 pos = prepos = -1
662 654
663 655 # Expected shellscript output
664 656 expected = {}
665 657
666 658 # We keep track of whether or not we're in a Python block so we
667 659 # can generate the surrounding doctest magic
668 660 inpython = False
669 661
670 662 # True or False when in a true or false conditional section
671 663 skipping = None
672 664
673 665 def hghave(reqs):
674 666 # TODO: do something smarter when all other uses of hghave is gone
675 667 tdir = TESTDIR.replace('\\', '/')
676 668 proc = Popen4('%s -c "%s/hghave %s"' %
677 669 (options.shell, tdir, ' '.join(reqs)), wd, 0)
678 670 stdout, stderr = proc.communicate()
679 671 ret = proc.wait()
680 672 if wifexited(ret):
681 673 ret = os.WEXITSTATUS(ret)
682 674 if ret == 2:
683 675 print stdout
684 676 sys.exit(1)
685 677 return ret == 0
686 678
687 679 f = open(test)
688 680 t = f.readlines()
689 681 f.close()
690 682
691 683 script = []
692 684 if options.debug:
693 685 script.append('set -x\n')
694 686 if os.getenv('MSYSTEM'):
695 687 script.append('alias pwd="pwd -W"\n')
696 688 n = 0
697 689 for n, l in enumerate(t):
698 690 if not l.endswith('\n'):
699 691 l += '\n'
700 692 if l.startswith('#if'):
701 693 if skipping is not None:
702 694 after.setdefault(pos, []).append(' !!! nested #if\n')
703 695 skipping = not hghave(l.split()[1:])
704 696 after.setdefault(pos, []).append(l)
705 697 elif l.startswith('#else'):
706 698 if skipping is None:
707 699 after.setdefault(pos, []).append(' !!! missing #if\n')
708 700 skipping = not skipping
709 701 after.setdefault(pos, []).append(l)
710 702 elif l.startswith('#endif'):
711 703 if skipping is None:
712 704 after.setdefault(pos, []).append(' !!! missing #if\n')
713 705 skipping = None
714 706 after.setdefault(pos, []).append(l)
715 707 elif skipping:
716 708 after.setdefault(pos, []).append(l)
717 709 elif l.startswith(' >>> '): # python inlines
718 710 after.setdefault(pos, []).append(l)
719 711 prepos = pos
720 712 pos = n
721 713 if not inpython:
722 714 # we've just entered a Python block, add the header
723 715 inpython = True
724 716 addsalt(prepos, False) # make sure we report the exit code
725 717 script.append('%s -m heredoctest <<EOF\n' % PYTHON)
726 718 addsalt(n, True)
727 719 script.append(l[2:])
728 720 elif l.startswith(' ... '): # python inlines
729 721 after.setdefault(prepos, []).append(l)
730 722 script.append(l[2:])
731 723 elif l.startswith(' $ '): # commands
732 724 if inpython:
733 725 script.append("EOF\n")
734 726 inpython = False
735 727 after.setdefault(pos, []).append(l)
736 728 prepos = pos
737 729 pos = n
738 730 addsalt(n, False)
739 731 cmd = l[4:].split()
740 732 if len(cmd) == 2 and cmd[0] == 'cd':
741 733 l = ' $ cd %s || exit 1\n' % cmd[1]
742 734 script.append(l[4:])
743 735 elif l.startswith(' > '): # continuations
744 736 after.setdefault(prepos, []).append(l)
745 737 script.append(l[4:])
746 738 elif l.startswith(' '): # results
747 739 # queue up a list of expected results
748 740 expected.setdefault(pos, []).append(l[2:])
749 741 else:
750 742 if inpython:
751 743 script.append("EOF\n")
752 744 inpython = False
753 745 # non-command/result - queue up for merged output
754 746 after.setdefault(pos, []).append(l)
755 747
756 748 if inpython:
757 749 script.append("EOF\n")
758 750 if skipping is not None:
759 751 after.setdefault(pos, []).append(' !!! missing #endif\n')
760 752 addsalt(n + 1, False)
761 753
762 754 # Write out the script and execute it
763 755 name = wd + '.sh'
764 756 f = open(name, 'w')
765 757 for l in script:
766 758 f.write(l)
767 759 f.close()
768 760
769 761 cmd = '%s "%s"' % (options.shell, name)
770 762 vlog("# Running", cmd)
771 763 exitcode, output = run(cmd, wd, options, replacements, env)
772 764 # do not merge output if skipped, return hghave message instead
773 765 # similarly, with --debug, output is None
774 766 if exitcode == SKIPPED_STATUS or output is None:
775 767 return exitcode, output
776 768
777 769 # Merge the script output back into a unified test
778 770
779 771 warnonly = 1 # 1: not yet, 2: yes, 3: for sure not
780 772 if exitcode != 0: # failure has been reported
781 773 warnonly = 3 # set to "for sure not"
782 774 pos = -1
783 775 postout = []
784 776 for l in output:
785 777 lout, lcmd = l, None
786 778 if salt in l:
787 779 lout, lcmd = l.split(salt, 1)
788 780
789 781 if lout:
790 782 if not lout.endswith('\n'):
791 783 lout += ' (no-eol)\n'
792 784
793 785 # find the expected output at the current position
794 786 el = None
795 787 if pos in expected and expected[pos]:
796 788 el = expected[pos].pop(0)
797 789
798 790 r = linematch(el, lout)
799 791 if isinstance(r, str):
800 792 if r == '+glob':
801 793 lout = el[:-1] + ' (glob)\n'
802 794 r = '' # warn only this line
803 795 elif r == '-glob':
804 796 lout = ''.join(el.rsplit(' (glob)', 1))
805 797 r = '' # warn only this line
806 798 else:
807 799 log('\ninfo, unknown linematch result: %r\n' % r)
808 800 r = False
809 801 if r:
810 802 postout.append(" " + el)
811 803 else:
812 804 if needescape(lout):
813 805 lout = stringescape(lout.rstrip('\n')) + " (esc)\n"
814 806 postout.append(" " + lout) # let diff deal with it
815 807 if r != '': # if line failed
816 808 warnonly = 3 # set to "for sure not"
817 809 elif warnonly == 1: # is "not yet" (and line is warn only)
818 810 warnonly = 2 # set to "yes" do warn
819 811
820 812 if lcmd:
821 813 # add on last return code
822 814 ret = int(lcmd.split()[1])
823 815 if ret != 0:
824 816 postout.append(" [%s]\n" % ret)
825 817 if pos in after:
826 818 # merge in non-active test bits
827 819 postout += after.pop(pos)
828 820 pos = int(lcmd.split()[0])
829 821
830 822 if pos in after:
831 823 postout += after.pop(pos)
832 824
833 825 if warnonly == 2:
834 826 exitcode = False # set exitcode to warned
835 827 return exitcode, postout
836 828
837 829 wifexited = getattr(os, "WIFEXITED", lambda x: False)
838 830 def run(cmd, wd, options, replacements, env):
839 831 """Run command in a sub-process, capturing the output (stdout and stderr).
840 832 Return a tuple (exitcode, output). output is None in debug mode."""
841 833 # TODO: Use subprocess.Popen if we're running on Python 2.4
842 834 if options.debug:
843 835 proc = subprocess.Popen(cmd, shell=True, cwd=wd, env=env)
844 836 ret = proc.wait()
845 837 return (ret, None)
846 838
847 839 proc = Popen4(cmd, wd, options.timeout, env)
848 840 def cleanup():
849 841 terminate(proc)
850 842 ret = proc.wait()
851 843 if ret == 0:
852 844 ret = signal.SIGTERM << 8
853 845 killdaemons(env['DAEMON_PIDS'])
854 846 return ret
855 847
856 848 output = ''
857 849 proc.tochild.close()
858 850
859 851 try:
860 852 output = proc.fromchild.read()
861 853 except KeyboardInterrupt:
862 854 vlog('# Handling keyboard interrupt')
863 855 cleanup()
864 856 raise
865 857
866 858 ret = proc.wait()
867 859 if wifexited(ret):
868 860 ret = os.WEXITSTATUS(ret)
869 861
870 862 if proc.timeout:
871 863 ret = 'timeout'
872 864
873 865 if ret:
874 866 killdaemons(env['DAEMON_PIDS'])
875 867
876 868 if abort:
877 869 raise KeyboardInterrupt()
878 870
879 871 for s, r in replacements:
880 872 output = re.sub(s, r, output)
881 873 return ret, output.splitlines(True)
882 874
883 875 def runone(options, test, count):
884 876 '''returns a result element: (code, test, msg)'''
885 877
886 878 def skip(msg):
887 879 if options.verbose:
888 880 log("\nSkipping %s: %s" % (testpath, msg))
889 881 return 's', test, msg
890 882
891 883 def fail(msg, ret):
892 884 warned = ret is False
893 885 if not options.nodiff:
894 886 log("\n%s: %s %s" % (warned and 'Warning' or 'ERROR', test, msg))
895 887 if (not ret and options.interactive
896 888 and os.path.exists(testpath + ".err")):
897 889 iolock.acquire()
898 890 print "Accept this change? [n] ",
899 891 answer = sys.stdin.readline().strip()
900 892 iolock.release()
901 893 if answer.lower() in "y yes".split():
902 894 if test.endswith(".t"):
903 895 rename(testpath + ".err", testpath)
904 896 else:
905 897 rename(testpath + ".err", testpath + ".out")
906 898 return '.', test, ''
907 899 return warned and '~' or '!', test, msg
908 900
909 901 def success():
910 902 return '.', test, ''
911 903
912 904 def ignore(msg):
913 905 return 'i', test, msg
914 906
915 907 def describe(ret):
916 908 if ret < 0:
917 909 return 'killed by signal %d' % -ret
918 910 return 'returned error code %d' % ret
919 911
920 912 testpath = os.path.join(TESTDIR, test)
921 913 err = os.path.join(TESTDIR, test + ".err")
922 914 lctest = test.lower()
923 915
924 916 if not os.path.exists(testpath):
925 917 return skip("doesn't exist")
926 918
927 919 if not (options.whitelisted and test in options.whitelisted):
928 920 if options.blacklist and test in options.blacklist:
929 921 return skip("blacklisted")
930 922
931 923 if options.retest and not os.path.exists(test + ".err"):
932 924 return ignore("not retesting")
933 925
934 926 if options.keywords:
935 927 fp = open(test)
936 928 t = fp.read().lower() + test.lower()
937 929 fp.close()
938 930 for k in options.keywords.lower().split():
939 931 if k in t:
940 932 break
941 933 else:
942 934 return ignore("doesn't match keyword")
943 935
944 936 if not lctest.startswith("test-"):
945 937 return skip("not a test file")
946 938 for ext, func, out in testtypes:
947 939 if lctest.endswith(ext):
948 940 runner = func
949 941 ref = os.path.join(TESTDIR, test + out)
950 942 break
951 943 else:
952 944 return skip("unknown test type")
953 945
954 946 vlog("# Test", test)
955 947
956 948 if os.path.exists(err):
957 949 os.remove(err) # Remove any previous output files
958 950
959 951 # Make a tmp subdirectory to work in
960 952 threadtmp = os.path.join(HGTMP, "child%d" % count)
961 953 testtmp = os.path.join(threadtmp, os.path.basename(test))
962 954 os.mkdir(threadtmp)
963 955 os.mkdir(testtmp)
964 956
965 957 port = options.port + count * 3
966 958 replacements = [
967 959 (r':%s\b' % port, ':$HGPORT'),
968 960 (r':%s\b' % (port + 1), ':$HGPORT1'),
969 961 (r':%s\b' % (port + 2), ':$HGPORT2'),
970 962 ]
971 963 if os.name == 'nt':
972 964 replacements.append(
973 965 (''.join(c.isalpha() and '[%s%s]' % (c.lower(), c.upper()) or
974 966 c in '/\\' and r'[/\\]' or
975 967 c.isdigit() and c or
976 968 '\\' + c
977 969 for c in testtmp), '$TESTTMP'))
978 970 else:
979 971 replacements.append((re.escape(testtmp), '$TESTTMP'))
980 972
981 973 env = createenv(options, testtmp, threadtmp, port)
982 974 createhgrc(env['HGRCPATH'], options)
983 975
984 976 starttime = time.time()
985 977 try:
986 978 ret, out = runner(testpath, testtmp, options, replacements, env)
987 979 except KeyboardInterrupt:
988 980 endtime = time.time()
989 981 log('INTERRUPTED: %s (after %d seconds)' % (test, endtime - starttime))
990 982 raise
991 983 endtime = time.time()
992 984 times.append((test, endtime - starttime))
993 985 vlog("# Ret was:", ret)
994 986
995 987 killdaemons(env['DAEMON_PIDS'])
996 988
997 989 skipped = (ret == SKIPPED_STATUS)
998 990
999 991 # If we're not in --debug mode and reference output file exists,
1000 992 # check test output against it.
1001 993 if options.debug:
1002 994 refout = None # to match "out is None"
1003 995 elif os.path.exists(ref):
1004 996 f = open(ref, "r")
1005 997 refout = f.read().splitlines(True)
1006 998 f.close()
1007 999 else:
1008 1000 refout = []
1009 1001
1010 1002 if (ret != 0 or out != refout) and not skipped and not options.debug:
1011 1003 # Save errors to a file for diagnosis
1012 1004 f = open(err, "wb")
1013 1005 for line in out:
1014 1006 f.write(line)
1015 1007 f.close()
1016 1008
1017 1009 if skipped:
1018 1010 if out is None: # debug mode: nothing to parse
1019 1011 missing = ['unknown']
1020 1012 failed = None
1021 1013 else:
1022 1014 missing, failed = parsehghaveoutput(out)
1023 1015 if not missing:
1024 1016 missing = ['irrelevant']
1025 1017 if failed:
1026 1018 result = fail("hghave failed checking for %s" % failed[-1], ret)
1027 1019 skipped = False
1028 1020 else:
1029 1021 result = skip(missing[-1])
1030 1022 elif ret == 'timeout':
1031 1023 result = fail("timed out", ret)
1032 1024 elif out != refout:
1033 1025 if not options.nodiff:
1034 1026 iolock.acquire()
1035 1027 if options.view:
1036 1028 os.system("%s %s %s" % (options.view, ref, err))
1037 1029 else:
1038 1030 showdiff(refout, out, ref, err)
1039 1031 iolock.release()
1040 1032 if ret:
1041 1033 result = fail("output changed and " + describe(ret), ret)
1042 1034 else:
1043 1035 result = fail("output changed", ret)
1044 1036 elif ret:
1045 1037 result = fail(describe(ret), ret)
1046 1038 else:
1047 1039 result = success()
1048 1040
1049 1041 if not options.verbose:
1050 1042 iolock.acquire()
1051 1043 sys.stdout.write(result[0])
1052 1044 sys.stdout.flush()
1053 1045 iolock.release()
1054 1046
1055 1047 if not options.keep_tmpdir:
1056 1048 shutil.rmtree(threadtmp, True)
1057 1049 return result
1058 1050
1059 1051 _hgpath = None
1060 1052
1061 1053 def _gethgpath():
1062 1054 """Return the path to the mercurial package that is actually found by
1063 1055 the current Python interpreter."""
1064 1056 global _hgpath
1065 1057 if _hgpath is not None:
1066 1058 return _hgpath
1067 1059
1068 1060 cmd = '%s -c "import mercurial; print (mercurial.__path__[0])"'
1069 1061 pipe = os.popen(cmd % PYTHON)
1070 1062 try:
1071 1063 _hgpath = pipe.read().strip()
1072 1064 finally:
1073 1065 pipe.close()
1074 1066 return _hgpath
1075 1067
1076 1068 def _checkhglib(verb):
1077 1069 """Ensure that the 'mercurial' package imported by python is
1078 1070 the one we expect it to be. If not, print a warning to stderr."""
1079 1071 expecthg = os.path.join(PYTHONDIR, 'mercurial')
1080 1072 actualhg = _gethgpath()
1081 1073 if os.path.abspath(actualhg) != os.path.abspath(expecthg):
1082 1074 sys.stderr.write('warning: %s with unexpected mercurial lib: %s\n'
1083 1075 ' (expected %s)\n'
1084 1076 % (verb, actualhg, expecthg))
1085 1077
1086 1078 results = {'.':[], '!':[], '~': [], 's':[], 'i':[]}
1087 1079 times = []
1088 1080 iolock = threading.Lock()
1089 1081 abort = False
1090 1082
1091 1083 def scheduletests(options, tests):
1092 1084 jobs = options.jobs
1093 1085 done = queue.Queue()
1094 1086 running = 0
1095 1087 count = 0
1096 1088 global abort
1097 1089
1098 1090 def job(test, count):
1099 1091 try:
1100 1092 done.put(runone(options, test, count))
1101 1093 except KeyboardInterrupt:
1102 1094 pass
1103 1095 except: # re-raises
1104 1096 done.put(('!', test, 'run-test raised an error, see traceback'))
1105 1097 raise
1106 1098
1107 1099 try:
1108 1100 while tests or running:
1109 1101 if not done.empty() or running == jobs or not tests:
1110 1102 try:
1111 1103 code, test, msg = done.get(True, 1)
1112 1104 results[code].append((test, msg))
1113 1105 if options.first and code not in '.si':
1114 1106 break
1115 1107 except queue.Empty:
1116 1108 continue
1117 1109 running -= 1
1118 1110 if tests and not running == jobs:
1119 1111 test = tests.pop(0)
1120 1112 if options.loop:
1121 1113 tests.append(test)
1122 1114 t = threading.Thread(target=job, name=test, args=(test, count))
1123 1115 t.start()
1124 1116 running += 1
1125 1117 count += 1
1126 1118 except KeyboardInterrupt:
1127 1119 abort = True
1128 1120
1129 1121 def runtests(options, tests):
1130 1122 try:
1131 1123 if INST:
1132 1124 installhg(options)
1133 1125 _checkhglib("Testing")
1134 1126 else:
1135 1127 usecorrectpython()
1136 1128
1137 1129 if options.restart:
1138 1130 orig = list(tests)
1139 1131 while tests:
1140 1132 if os.path.exists(tests[0] + ".err"):
1141 1133 break
1142 1134 tests.pop(0)
1143 1135 if not tests:
1144 1136 print "running all tests"
1145 1137 tests = orig
1146 1138
1147 1139 scheduletests(options, tests)
1148 1140
1149 1141 failed = len(results['!'])
1150 1142 warned = len(results['~'])
1151 1143 tested = len(results['.']) + failed + warned
1152 1144 skipped = len(results['s'])
1153 1145 ignored = len(results['i'])
1154 1146
1155 1147 print
1156 1148 if not options.noskips:
1157 1149 for s in results['s']:
1158 1150 print "Skipped %s: %s" % s
1159 1151 for s in results['~']:
1160 1152 print "Warned %s: %s" % s
1161 1153 for s in results['!']:
1162 1154 print "Failed %s: %s" % s
1163 1155 _checkhglib("Tested")
1164 1156 print "# Ran %d tests, %d skipped, %d warned, %d failed." % (
1165 1157 tested, skipped + ignored, warned, failed)
1166 1158 if results['!']:
1167 1159 print 'python hash seed:', os.environ['PYTHONHASHSEED']
1168 1160 if options.time:
1169 1161 outputtimes(options)
1170 1162
1171 1163 if options.anycoverage:
1172 1164 outputcoverage(options)
1173 1165 except KeyboardInterrupt:
1174 1166 failed = True
1175 1167 print "\ninterrupted!"
1176 1168
1177 1169 if failed:
1178 1170 return 1
1179 1171 if warned:
1180 1172 return 80
1181 1173
1182 1174 testtypes = [('.py', pytest, '.out'),
1183 1175 ('.t', tsttest, '')]
1184 1176
1185 1177 def main():
1186 1178 (options, args) = parseargs()
1187 1179 os.umask(022)
1188 1180
1189 1181 checktools()
1190 1182
1191 1183 if len(args) == 0:
1192 1184 args = [t for t in os.listdir(".")
1193 1185 if t.startswith("test-")
1194 1186 and (t.endswith(".py") or t.endswith(".t"))]
1195 1187
1196 1188 tests = args
1197 1189
1198 1190 if options.random:
1199 1191 random.shuffle(tests)
1200 1192 else:
1201 1193 # keywords for slow tests
1202 1194 slow = 'svn gendoc check-code-hg'.split()
1203 1195 def sortkey(f):
1204 1196 # run largest tests first, as they tend to take the longest
1205 1197 try:
1206 1198 val = -os.stat(f).st_size
1207 1199 except OSError, e:
1208 1200 if e.errno != errno.ENOENT:
1209 1201 raise
1210 1202 return -1e9 # file does not exist, tell early
1211 1203 for kw in slow:
1212 1204 if kw in f:
1213 1205 val *= 10
1214 1206 return val
1215 1207 tests.sort(key=sortkey)
1216 1208
1217 1209 if 'PYTHONHASHSEED' not in os.environ:
1218 1210 # use a random python hash seed all the time
1219 1211 # we do the randomness ourself to know what seed is used
1220 1212 os.environ['PYTHONHASHSEED'] = str(random.getrandbits(32))
1221 1213
1222 1214 global TESTDIR, HGTMP, INST, BINDIR, TMPBINDIR, PYTHONDIR, COVERAGE_FILE
1223 1215 TESTDIR = os.environ["TESTDIR"] = os.getcwd()
1224 1216 if options.tmpdir:
1225 1217 options.keep_tmpdir = True
1226 1218 tmpdir = options.tmpdir
1227 1219 if os.path.exists(tmpdir):
1228 1220 # Meaning of tmpdir has changed since 1.3: we used to create
1229 1221 # HGTMP inside tmpdir; now HGTMP is tmpdir. So fail if
1230 1222 # tmpdir already exists.
1231 1223 sys.exit("error: temp dir %r already exists" % tmpdir)
1232 1224
1233 1225 # Automatically removing tmpdir sounds convenient, but could
1234 1226 # really annoy anyone in the habit of using "--tmpdir=/tmp"
1235 1227 # or "--tmpdir=$HOME".
1236 1228 #vlog("# Removing temp dir", tmpdir)
1237 1229 #shutil.rmtree(tmpdir)
1238 1230 os.makedirs(tmpdir)
1239 1231 else:
1240 1232 d = None
1241 1233 if os.name == 'nt':
1242 1234 # without this, we get the default temp dir location, but
1243 1235 # in all lowercase, which causes troubles with paths (issue3490)
1244 1236 d = os.getenv('TMP')
1245 1237 tmpdir = tempfile.mkdtemp('', 'hgtests.', d)
1246 1238 HGTMP = os.environ['HGTMP'] = os.path.realpath(tmpdir)
1247 1239
1248 1240 if options.with_hg:
1249 1241 INST = None
1250 1242 BINDIR = os.path.dirname(os.path.realpath(options.with_hg))
1251 1243 TMPBINDIR = os.path.join(HGTMP, 'install', 'bin')
1252 1244 os.makedirs(TMPBINDIR)
1253 1245
1254 1246 # This looks redundant with how Python initializes sys.path from
1255 1247 # the location of the script being executed. Needed because the
1256 1248 # "hg" specified by --with-hg is not the only Python script
1257 1249 # executed in the test suite that needs to import 'mercurial'
1258 1250 # ... which means it's not really redundant at all.
1259 1251 PYTHONDIR = BINDIR
1260 1252 else:
1261 1253 INST = os.path.join(HGTMP, "install")
1262 1254 BINDIR = os.environ["BINDIR"] = os.path.join(INST, "bin")
1263 1255 TMPBINDIR = BINDIR
1264 1256 PYTHONDIR = os.path.join(INST, "lib", "python")
1265 1257
1266 1258 os.environ["BINDIR"] = BINDIR
1267 1259 os.environ["PYTHON"] = PYTHON
1268 1260
1269 1261 path = [BINDIR] + os.environ["PATH"].split(os.pathsep)
1270 1262 if TMPBINDIR != BINDIR:
1271 1263 path = [TMPBINDIR] + path
1272 1264 os.environ["PATH"] = os.pathsep.join(path)
1273 1265
1274 1266 # Include TESTDIR in PYTHONPATH so that out-of-tree extensions
1275 1267 # can run .../tests/run-tests.py test-foo where test-foo
1276 1268 # adds an extension to HGRC. Also include run-test.py directory to import
1277 1269 # modules like heredoctest.
1278 1270 pypath = [PYTHONDIR, TESTDIR, os.path.abspath(os.path.dirname(__file__))]
1279 1271 # We have to augment PYTHONPATH, rather than simply replacing
1280 1272 # it, in case external libraries are only available via current
1281 1273 # PYTHONPATH. (In particular, the Subversion bindings on OS X
1282 1274 # are in /opt/subversion.)
1283 1275 oldpypath = os.environ.get(IMPL_PATH)
1284 1276 if oldpypath:
1285 1277 pypath.append(oldpypath)
1286 1278 os.environ[IMPL_PATH] = os.pathsep.join(pypath)
1287 1279
1288 1280 COVERAGE_FILE = os.path.join(TESTDIR, ".coverage")
1289 1281
1290 1282 vlog("# Using TESTDIR", TESTDIR)
1291 1283 vlog("# Using HGTMP", HGTMP)
1292 1284 vlog("# Using PATH", os.environ["PATH"])
1293 1285 vlog("# Using", IMPL_PATH, os.environ[IMPL_PATH])
1294 1286
1295 1287 try:
1296 1288 sys.exit(runtests(options, tests) or 0)
1297 1289 finally:
1298 1290 time.sleep(.1)
1299 1291 cleanup(options)
1300 1292
1301 1293 if __name__ == '__main__':
1302 1294 main()
@@ -1,21 +1,20 b''
1 1 $ "$TESTDIR/hghave" pyflakes || exit 80
2 2 $ cd "`dirname "$TESTDIR"`"
3 3
4 4 run pyflakes on all tracked files ending in .py or without a file ending
5 5 (skipping binary file random-seed)
6 6 $ hg manifest 2>/dev/null | egrep "\.py$|^[^.]*$" | grep -v /random_seed$ \
7 7 > | xargs pyflakes 2>/dev/null | "$TESTDIR/filterpyflakes.py"
8 8 contrib/win32/hgwebdir_wsgi.py:*: 'win32traceutil' imported but unused (glob)
9 9 setup.py:*: 'sha' imported but unused (glob)
10 10 setup.py:*: 'zlib' imported but unused (glob)
11 11 setup.py:*: 'bz2' imported but unused (glob)
12 12 setup.py:*: 'py2exe' imported but unused (glob)
13 13 tests/hghave.py:*: 'hgext' imported but unused (glob)
14 14 tests/hghave.py:*: '_lsprof' imported but unused (glob)
15 15 tests/hghave.py:*: 'publish_cmdline' imported but unused (glob)
16 16 tests/hghave.py:*: 'pygments' imported but unused (glob)
17 17 tests/hghave.py:*: 'ssl' imported but unused (glob)
18 18 contrib/win32/hgwebdir_wsgi.py:*: 'from isapi.install import *' used; unable to detect undefined names (glob)
19 hgext/inotify/linux/__init__.py:*: 'from _inotify import *' used; unable to detect undefined names (glob)
20 19
21 20
@@ -1,36 +1,36 b''
1 1 import os
2 2 from mercurial import ui, commands, extensions
3 3
4 ignore = set(['highlight', 'inotify', 'win32text', 'factotum'])
4 ignore = set(['highlight', 'win32text', 'factotum'])
5 5
6 6 if os.name != 'nt':
7 7 ignore.add('win32mbcs')
8 8
9 9 disabled = [ext for ext in extensions.disabled().keys() if ext not in ignore]
10 10
11 11 hgrc = open(os.environ["HGRCPATH"], 'w')
12 12 hgrc.write('[extensions]\n')
13 13
14 14 for ext in disabled:
15 15 hgrc.write(ext + '=\n')
16 16
17 17 hgrc.close()
18 18
19 19 u = ui.ui()
20 20 extensions.loadall(u)
21 21
22 22 globalshort = set()
23 23 globallong = set()
24 24 for option in commands.globalopts:
25 25 option[0] and globalshort.add(option[0])
26 26 option[1] and globallong.add(option[1])
27 27
28 28 for cmd, entry in commands.table.iteritems():
29 29 seenshort = globalshort.copy()
30 30 seenlong = globallong.copy()
31 31 for option in entry[1]:
32 32 if (option[0] and option[0] in seenshort) or \
33 33 (option[1] and option[1] in seenlong):
34 34 print "command '" + cmd + "' has duplicate option " + str(option)
35 35 seenshort.add(option[0])
36 36 seenlong.add(option[1])
@@ -1,1995 +1,1995 b''
1 1 Short help:
2 2
3 3 $ hg
4 4 Mercurial Distributed SCM
5 5
6 6 basic commands:
7 7
8 8 add add the specified files on the next commit
9 9 annotate show changeset information by line for each file
10 10 clone make a copy of an existing repository
11 11 commit commit the specified files or all outstanding changes
12 12 diff diff repository (or selected files)
13 13 export dump the header and diffs for one or more changesets
14 14 forget forget the specified files on the next commit
15 15 init create a new repository in the given directory
16 16 log show revision history of entire repository or files
17 17 merge merge working directory with another revision
18 18 pull pull changes from the specified source
19 19 push push changes to the specified destination
20 20 remove remove the specified files on the next commit
21 21 serve start stand-alone webserver
22 22 status show changed files in the working directory
23 23 summary summarize working directory state
24 24 update update working directory (or switch revisions)
25 25
26 26 use "hg help" for the full list of commands or "hg -v" for details
27 27
28 28 $ hg -q
29 29 add add the specified files on the next commit
30 30 annotate show changeset information by line for each file
31 31 clone make a copy of an existing repository
32 32 commit commit the specified files or all outstanding changes
33 33 diff diff repository (or selected files)
34 34 export dump the header and diffs for one or more changesets
35 35 forget forget the specified files on the next commit
36 36 init create a new repository in the given directory
37 37 log show revision history of entire repository or files
38 38 merge merge working directory with another revision
39 39 pull pull changes from the specified source
40 40 push push changes to the specified destination
41 41 remove remove the specified files on the next commit
42 42 serve start stand-alone webserver
43 43 status show changed files in the working directory
44 44 summary summarize working directory state
45 45 update update working directory (or switch revisions)
46 46
47 47 $ hg help
48 48 Mercurial Distributed SCM
49 49
50 50 list of commands:
51 51
52 52 add add the specified files on the next commit
53 53 addremove add all new files, delete all missing files
54 54 annotate show changeset information by line for each file
55 55 archive create an unversioned archive of a repository revision
56 56 backout reverse effect of earlier changeset
57 57 bisect subdivision search of changesets
58 58 bookmarks track a line of development with movable markers
59 59 branch set or show the current branch name
60 60 branches list repository named branches
61 61 bundle create a changegroup file
62 62 cat output the current or given revision of files
63 63 clone make a copy of an existing repository
64 64 commit commit the specified files or all outstanding changes
65 65 config show combined config settings from all hgrc files
66 66 copy mark files as copied for the next commit
67 67 diff diff repository (or selected files)
68 68 export dump the header and diffs for one or more changesets
69 69 forget forget the specified files on the next commit
70 70 graft copy changes from other branches onto the current branch
71 71 grep search for a pattern in specified files and revisions
72 72 heads show branch heads
73 73 help show help for a given topic or a help overview
74 74 identify identify the working copy or specified revision
75 75 import import an ordered set of patches
76 76 incoming show new changesets found in source
77 77 init create a new repository in the given directory
78 78 locate locate files matching specific patterns
79 79 log show revision history of entire repository or files
80 80 manifest output the current or given revision of the project manifest
81 81 merge merge working directory with another revision
82 82 outgoing show changesets not found in the destination
83 83 parents show the parents of the working directory or revision
84 84 paths show aliases for remote repositories
85 85 phase set or show the current phase name
86 86 pull pull changes from the specified source
87 87 push push changes to the specified destination
88 88 recover roll back an interrupted transaction
89 89 remove remove the specified files on the next commit
90 90 rename rename files; equivalent of copy + remove
91 91 resolve redo merges or set/view the merge status of files
92 92 revert restore files to their checkout state
93 93 root print the root (top) of the current working directory
94 94 serve start stand-alone webserver
95 95 status show changed files in the working directory
96 96 summary summarize working directory state
97 97 tag add one or more tags for the current or given revision
98 98 tags list repository tags
99 99 unbundle apply one or more changegroup files
100 100 update update working directory (or switch revisions)
101 101 verify verify the integrity of the repository
102 102 version output version and copyright information
103 103
104 104 additional help topics:
105 105
106 106 config Configuration Files
107 107 dates Date Formats
108 108 diffs Diff Formats
109 109 environment Environment Variables
110 110 extensions Using Additional Features
111 111 filesets Specifying File Sets
112 112 glossary Glossary
113 113 hgignore Syntax for Mercurial Ignore Files
114 114 hgweb Configuring hgweb
115 115 merge-tools Merge Tools
116 116 multirevs Specifying Multiple Revisions
117 117 patterns File Name Patterns
118 118 phases Working with Phases
119 119 revisions Specifying Single Revisions
120 120 revsets Specifying Revision Sets
121 121 subrepos Subrepositories
122 122 templating Template Usage
123 123 urls URL Paths
124 124
125 125 use "hg -v help" to show builtin aliases and global options
126 126
127 127 $ hg -q help
128 128 add add the specified files on the next commit
129 129 addremove add all new files, delete all missing files
130 130 annotate show changeset information by line for each file
131 131 archive create an unversioned archive of a repository revision
132 132 backout reverse effect of earlier changeset
133 133 bisect subdivision search of changesets
134 134 bookmarks track a line of development with movable markers
135 135 branch set or show the current branch name
136 136 branches list repository named branches
137 137 bundle create a changegroup file
138 138 cat output the current or given revision of files
139 139 clone make a copy of an existing repository
140 140 commit commit the specified files or all outstanding changes
141 141 config show combined config settings from all hgrc files
142 142 copy mark files as copied for the next commit
143 143 diff diff repository (or selected files)
144 144 export dump the header and diffs for one or more changesets
145 145 forget forget the specified files on the next commit
146 146 graft copy changes from other branches onto the current branch
147 147 grep search for a pattern in specified files and revisions
148 148 heads show branch heads
149 149 help show help for a given topic or a help overview
150 150 identify identify the working copy or specified revision
151 151 import import an ordered set of patches
152 152 incoming show new changesets found in source
153 153 init create a new repository in the given directory
154 154 locate locate files matching specific patterns
155 155 log show revision history of entire repository or files
156 156 manifest output the current or given revision of the project manifest
157 157 merge merge working directory with another revision
158 158 outgoing show changesets not found in the destination
159 159 parents show the parents of the working directory or revision
160 160 paths show aliases for remote repositories
161 161 phase set or show the current phase name
162 162 pull pull changes from the specified source
163 163 push push changes to the specified destination
164 164 recover roll back an interrupted transaction
165 165 remove remove the specified files on the next commit
166 166 rename rename files; equivalent of copy + remove
167 167 resolve redo merges or set/view the merge status of files
168 168 revert restore files to their checkout state
169 169 root print the root (top) of the current working directory
170 170 serve start stand-alone webserver
171 171 status show changed files in the working directory
172 172 summary summarize working directory state
173 173 tag add one or more tags for the current or given revision
174 174 tags list repository tags
175 175 unbundle apply one or more changegroup files
176 176 update update working directory (or switch revisions)
177 177 verify verify the integrity of the repository
178 178 version output version and copyright information
179 179
180 180 additional help topics:
181 181
182 182 config Configuration Files
183 183 dates Date Formats
184 184 diffs Diff Formats
185 185 environment Environment Variables
186 186 extensions Using Additional Features
187 187 filesets Specifying File Sets
188 188 glossary Glossary
189 189 hgignore Syntax for Mercurial Ignore Files
190 190 hgweb Configuring hgweb
191 191 merge-tools Merge Tools
192 192 multirevs Specifying Multiple Revisions
193 193 patterns File Name Patterns
194 194 phases Working with Phases
195 195 revisions Specifying Single Revisions
196 196 revsets Specifying Revision Sets
197 197 subrepos Subrepositories
198 198 templating Template Usage
199 199 urls URL Paths
200 200
201 201 Test extension help:
202 $ hg help extensions --config extensions.rebase= --config extensions.children= | grep -v inotify
202 $ hg help extensions --config extensions.rebase= --config extensions.children=
203 203 Using Additional Features
204 204 """""""""""""""""""""""""
205 205
206 206 Mercurial has the ability to add new features through the use of
207 207 extensions. Extensions may add new commands, add options to existing
208 208 commands, change the default behavior of commands, or implement hooks.
209 209
210 210 To enable the "foo" extension, either shipped with Mercurial or in the
211 211 Python search path, create an entry for it in your configuration file,
212 212 like this:
213 213
214 214 [extensions]
215 215 foo =
216 216
217 217 You may also specify the full path to an extension:
218 218
219 219 [extensions]
220 220 myfeature = ~/.hgext/myfeature.py
221 221
222 222 See "hg help config" for more information on configuration files.
223 223
224 224 Extensions are not loaded by default for a variety of reasons: they can
225 225 increase startup overhead; they may be meant for advanced usage only; they
226 226 may provide potentially dangerous abilities (such as letting you destroy
227 227 or modify history); they might not be ready for prime time; or they may
228 228 alter some usual behaviors of stock Mercurial. It is thus up to the user
229 229 to activate extensions as needed.
230 230
231 231 To explicitly disable an extension enabled in a configuration file of
232 232 broader scope, prepend its path with !:
233 233
234 234 [extensions]
235 235 # disabling extension bar residing in /path/to/extension/bar.py
236 236 bar = !/path/to/extension/bar.py
237 237 # ditto, but no path was supplied for extension baz
238 238 baz = !
239 239
240 240 enabled extensions:
241 241
242 242 children command to display child changesets (DEPRECATED)
243 243 rebase command to move sets of revisions to a different ancestor
244 244
245 245 disabled extensions:
246 246
247 247 acl hooks for controlling repository access
248 248 blackbox log repository events to a blackbox for debugging
249 249 bugzilla hooks for integrating with the Bugzilla bug tracker
250 250 churn command to display statistics about repository history
251 251 color colorize output from some commands
252 252 convert import revisions from foreign VCS repositories into
253 253 Mercurial
254 254 eol automatically manage newlines in repository files
255 255 extdiff command to allow external programs to compare revisions
256 256 factotum http authentication with factotum
257 257 gpg commands to sign and verify changesets
258 258 hgcia hooks for integrating with the CIA.vc notification service
259 259 hgk browse the repository in a graphical way
260 260 highlight syntax highlighting for hgweb (requires Pygments)
261 261 histedit interactive history editing
262 262 interhg expand expressions into changelog and summaries
263 263 keyword expand keywords in tracked files
264 264 largefiles track large binary files
265 265 mq manage a stack of patches
266 266 notify hooks for sending email push notifications
267 267 pager browse command output with an external pager
268 268 patchbomb command to send changesets as (a series of) patch emails
269 269 progress show progress bars for some actions
270 270 purge command to delete untracked files from the working
271 271 directory
272 272 record commands to interactively select changes for
273 273 commit/qrefresh
274 274 relink recreates hardlinks between repository clones
275 275 schemes extend schemes with shortcuts to repository swarms
276 276 share share a common history between several working directories
277 277 shelve save and restore changes to the working directory
278 278 strip strip changesets and their descendents from history
279 279 transplant command to transplant changesets from another branch
280 280 win32mbcs allow the use of MBCS paths with problematic encodings
281 281 win32text perform automatic newline conversion
282 282 zeroconf discover and advertise repositories on the local network
283 283 Test short command list with verbose option
284 284
285 285 $ hg -v help shortlist
286 286 Mercurial Distributed SCM
287 287
288 288 basic commands:
289 289
290 290 add add the specified files on the next commit
291 291 annotate, blame
292 292 show changeset information by line for each file
293 293 clone make a copy of an existing repository
294 294 commit, ci commit the specified files or all outstanding changes
295 295 diff diff repository (or selected files)
296 296 export dump the header and diffs for one or more changesets
297 297 forget forget the specified files on the next commit
298 298 init create a new repository in the given directory
299 299 log, history show revision history of entire repository or files
300 300 merge merge working directory with another revision
301 301 pull pull changes from the specified source
302 302 push push changes to the specified destination
303 303 remove, rm remove the specified files on the next commit
304 304 serve start stand-alone webserver
305 305 status, st show changed files in the working directory
306 306 summary, sum summarize working directory state
307 307 update, up, checkout, co
308 308 update working directory (or switch revisions)
309 309
310 310 global options:
311 311
312 312 -R --repository REPO repository root directory or name of overlay bundle
313 313 file
314 314 --cwd DIR change working directory
315 315 -y --noninteractive do not prompt, automatically pick the first choice for
316 316 all prompts
317 317 -q --quiet suppress output
318 318 -v --verbose enable additional output
319 319 --config CONFIG [+] set/override config option (use 'section.name=value')
320 320 --debug enable debugging output
321 321 --debugger start debugger
322 322 --encoding ENCODE set the charset encoding (default: ascii)
323 323 --encodingmode MODE set the charset encoding mode (default: strict)
324 324 --traceback always print a traceback on exception
325 325 --time time how long the command takes
326 326 --profile print command execution profile
327 327 --version output version information and exit
328 328 -h --help display help and exit
329 329 --hidden consider hidden changesets
330 330
331 331 [+] marked option can be specified multiple times
332 332
333 333 use "hg help" for the full list of commands
334 334
335 335 $ hg add -h
336 336 hg add [OPTION]... [FILE]...
337 337
338 338 add the specified files on the next commit
339 339
340 340 Schedule files to be version controlled and added to the repository.
341 341
342 342 The files will be added to the repository at the next commit. To undo an
343 343 add before that, see "hg forget".
344 344
345 345 If no names are given, add all files to the repository.
346 346
347 347 Returns 0 if all files are successfully added.
348 348
349 349 options:
350 350
351 351 -I --include PATTERN [+] include names matching the given patterns
352 352 -X --exclude PATTERN [+] exclude names matching the given patterns
353 353 -S --subrepos recurse into subrepositories
354 354 -n --dry-run do not perform actions, just print output
355 355
356 356 [+] marked option can be specified multiple times
357 357
358 358 use "hg -v help add" to show more complete help and the global options
359 359
360 360 Verbose help for add
361 361
362 362 $ hg add -hv
363 363 hg add [OPTION]... [FILE]...
364 364
365 365 add the specified files on the next commit
366 366
367 367 Schedule files to be version controlled and added to the repository.
368 368
369 369 The files will be added to the repository at the next commit. To undo an
370 370 add before that, see "hg forget".
371 371
372 372 If no names are given, add all files to the repository.
373 373
374 374 An example showing how new (unknown) files are added automatically by "hg
375 375 add":
376 376
377 377 $ ls
378 378 foo.c
379 379 $ hg status
380 380 ? foo.c
381 381 $ hg add
382 382 adding foo.c
383 383 $ hg status
384 384 A foo.c
385 385
386 386 Returns 0 if all files are successfully added.
387 387
388 388 options:
389 389
390 390 -I --include PATTERN [+] include names matching the given patterns
391 391 -X --exclude PATTERN [+] exclude names matching the given patterns
392 392 -S --subrepos recurse into subrepositories
393 393 -n --dry-run do not perform actions, just print output
394 394
395 395 [+] marked option can be specified multiple times
396 396
397 397 global options:
398 398
399 399 -R --repository REPO repository root directory or name of overlay bundle
400 400 file
401 401 --cwd DIR change working directory
402 402 -y --noninteractive do not prompt, automatically pick the first choice for
403 403 all prompts
404 404 -q --quiet suppress output
405 405 -v --verbose enable additional output
406 406 --config CONFIG [+] set/override config option (use 'section.name=value')
407 407 --debug enable debugging output
408 408 --debugger start debugger
409 409 --encoding ENCODE set the charset encoding (default: ascii)
410 410 --encodingmode MODE set the charset encoding mode (default: strict)
411 411 --traceback always print a traceback on exception
412 412 --time time how long the command takes
413 413 --profile print command execution profile
414 414 --version output version information and exit
415 415 -h --help display help and exit
416 416 --hidden consider hidden changesets
417 417
418 418 [+] marked option can be specified multiple times
419 419
420 420 Test help option with version option
421 421
422 422 $ hg add -h --version
423 423 Mercurial Distributed SCM (version *) (glob)
424 424 (see http://mercurial.selenic.com for more information)
425 425
426 426 Copyright (C) 2005-2014 Matt Mackall and others
427 427 This is free software; see the source for copying conditions. There is NO
428 428 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
429 429
430 430 $ hg add --skjdfks
431 431 hg add: option --skjdfks not recognized
432 432 hg add [OPTION]... [FILE]...
433 433
434 434 add the specified files on the next commit
435 435
436 436 options:
437 437
438 438 -I --include PATTERN [+] include names matching the given patterns
439 439 -X --exclude PATTERN [+] exclude names matching the given patterns
440 440 -S --subrepos recurse into subrepositories
441 441 -n --dry-run do not perform actions, just print output
442 442
443 443 [+] marked option can be specified multiple times
444 444
445 445 use "hg help add" to show the full help text
446 446 [255]
447 447
448 448 Test ambiguous command help
449 449
450 450 $ hg help ad
451 451 list of commands:
452 452
453 453 add add the specified files on the next commit
454 454 addremove add all new files, delete all missing files
455 455
456 456 use "hg -v help ad" to show builtin aliases and global options
457 457
458 458 Test command without options
459 459
460 460 $ hg help verify
461 461 hg verify
462 462
463 463 verify the integrity of the repository
464 464
465 465 Verify the integrity of the current repository.
466 466
467 467 This will perform an extensive check of the repository's integrity,
468 468 validating the hashes and checksums of each entry in the changelog,
469 469 manifest, and tracked files, as well as the integrity of their crosslinks
470 470 and indices.
471 471
472 472 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption for more
473 473 information about recovery from corruption of the repository.
474 474
475 475 Returns 0 on success, 1 if errors are encountered.
476 476
477 477 use "hg -v help verify" to show the global options
478 478
479 479 $ hg help diff
480 480 hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...
481 481
482 482 diff repository (or selected files)
483 483
484 484 Show differences between revisions for the specified files.
485 485
486 486 Differences between files are shown using the unified diff format.
487 487
488 488 Note:
489 489 diff may generate unexpected results for merges, as it will default to
490 490 comparing against the working directory's first parent changeset if no
491 491 revisions are specified.
492 492
493 493 When two revision arguments are given, then changes are shown between
494 494 those revisions. If only one revision is specified then that revision is
495 495 compared to the working directory, and, when no revisions are specified,
496 496 the working directory files are compared to its parent.
497 497
498 498 Alternatively you can specify -c/--change with a revision to see the
499 499 changes in that changeset relative to its first parent.
500 500
501 501 Without the -a/--text option, diff will avoid generating diffs of files it
502 502 detects as binary. With -a, diff will generate a diff anyway, probably
503 503 with undesirable results.
504 504
505 505 Use the -g/--git option to generate diffs in the git extended diff format.
506 506 For more information, read "hg help diffs".
507 507
508 508 Returns 0 on success.
509 509
510 510 options:
511 511
512 512 -r --rev REV [+] revision
513 513 -c --change REV change made by revision
514 514 -a --text treat all files as text
515 515 -g --git use git extended diff format
516 516 --nodates omit dates from diff headers
517 517 -p --show-function show which function each change is in
518 518 --reverse produce a diff that undoes the changes
519 519 -w --ignore-all-space ignore white space when comparing lines
520 520 -b --ignore-space-change ignore changes in the amount of white space
521 521 -B --ignore-blank-lines ignore changes whose lines are all blank
522 522 -U --unified NUM number of lines of context to show
523 523 --stat output diffstat-style summary of changes
524 524 -I --include PATTERN [+] include names matching the given patterns
525 525 -X --exclude PATTERN [+] exclude names matching the given patterns
526 526 -S --subrepos recurse into subrepositories
527 527
528 528 [+] marked option can be specified multiple times
529 529
530 530 use "hg -v help diff" to show more complete help and the global options
531 531
532 532 $ hg help status
533 533 hg status [OPTION]... [FILE]...
534 534
535 535 aliases: st
536 536
537 537 show changed files in the working directory
538 538
539 539 Show status of files in the repository. If names are given, only files
540 540 that match are shown. Files that are clean or ignored or the source of a
541 541 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
542 542 -C/--copies or -A/--all are given. Unless options described with "show
543 543 only ..." are given, the options -mardu are used.
544 544
545 545 Option -q/--quiet hides untracked (unknown and ignored) files unless
546 546 explicitly requested with -u/--unknown or -i/--ignored.
547 547
548 548 Note:
549 549 status may appear to disagree with diff if permissions have changed or
550 550 a merge has occurred. The standard diff format does not report
551 551 permission changes and diff only reports changes relative to one merge
552 552 parent.
553 553
554 554 If one revision is given, it is used as the base revision. If two
555 555 revisions are given, the differences between them are shown. The --change
556 556 option can also be used as a shortcut to list the changed files of a
557 557 revision from its first parent.
558 558
559 559 The codes used to show the status of files are:
560 560
561 561 M = modified
562 562 A = added
563 563 R = removed
564 564 C = clean
565 565 ! = missing (deleted by non-hg command, but still tracked)
566 566 ? = not tracked
567 567 I = ignored
568 568 = origin of the previous file listed as A (added)
569 569
570 570 Returns 0 on success.
571 571
572 572 options:
573 573
574 574 -A --all show status of all files
575 575 -m --modified show only modified files
576 576 -a --added show only added files
577 577 -r --removed show only removed files
578 578 -d --deleted show only deleted (but tracked) files
579 579 -c --clean show only files without changes
580 580 -u --unknown show only unknown (not tracked) files
581 581 -i --ignored show only ignored files
582 582 -n --no-status hide status prefix
583 583 -C --copies show source of copied files
584 584 -0 --print0 end filenames with NUL, for use with xargs
585 585 --rev REV [+] show difference from revision
586 586 --change REV list the changed files of a revision
587 587 -I --include PATTERN [+] include names matching the given patterns
588 588 -X --exclude PATTERN [+] exclude names matching the given patterns
589 589 -S --subrepos recurse into subrepositories
590 590
591 591 [+] marked option can be specified multiple times
592 592
593 593 use "hg -v help status" to show more complete help and the global options
594 594
595 595 $ hg -q help status
596 596 hg status [OPTION]... [FILE]...
597 597
598 598 show changed files in the working directory
599 599
600 600 $ hg help foo
601 601 hg: unknown command 'foo'
602 602 Mercurial Distributed SCM
603 603
604 604 basic commands:
605 605
606 606 add add the specified files on the next commit
607 607 annotate show changeset information by line for each file
608 608 clone make a copy of an existing repository
609 609 commit commit the specified files or all outstanding changes
610 610 diff diff repository (or selected files)
611 611 export dump the header and diffs for one or more changesets
612 612 forget forget the specified files on the next commit
613 613 init create a new repository in the given directory
614 614 log show revision history of entire repository or files
615 615 merge merge working directory with another revision
616 616 pull pull changes from the specified source
617 617 push push changes to the specified destination
618 618 remove remove the specified files on the next commit
619 619 serve start stand-alone webserver
620 620 status show changed files in the working directory
621 621 summary summarize working directory state
622 622 update update working directory (or switch revisions)
623 623
624 624 use "hg help" for the full list of commands or "hg -v" for details
625 625 [255]
626 626
627 627 $ hg skjdfks
628 628 hg: unknown command 'skjdfks'
629 629 Mercurial Distributed SCM
630 630
631 631 basic commands:
632 632
633 633 add add the specified files on the next commit
634 634 annotate show changeset information by line for each file
635 635 clone make a copy of an existing repository
636 636 commit commit the specified files or all outstanding changes
637 637 diff diff repository (or selected files)
638 638 export dump the header and diffs for one or more changesets
639 639 forget forget the specified files on the next commit
640 640 init create a new repository in the given directory
641 641 log show revision history of entire repository or files
642 642 merge merge working directory with another revision
643 643 pull pull changes from the specified source
644 644 push push changes to the specified destination
645 645 remove remove the specified files on the next commit
646 646 serve start stand-alone webserver
647 647 status show changed files in the working directory
648 648 summary summarize working directory state
649 649 update update working directory (or switch revisions)
650 650
651 651 use "hg help" for the full list of commands or "hg -v" for details
652 652 [255]
653 653
654 654 $ cat > helpext.py <<EOF
655 655 > import os
656 656 > from mercurial import commands
657 657 >
658 658 > def nohelp(ui, *args, **kwargs):
659 659 > pass
660 660 >
661 661 > cmdtable = {
662 662 > "nohelp": (nohelp, [], "hg nohelp"),
663 663 > }
664 664 >
665 665 > commands.norepo += ' nohelp'
666 666 > EOF
667 667 $ echo '[extensions]' >> $HGRCPATH
668 668 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
669 669
670 670 Test command with no help text
671 671
672 672 $ hg help nohelp
673 673 hg nohelp
674 674
675 675 (no help text available)
676 676
677 677 use "hg -v help nohelp" to show the global options
678 678
679 679 $ hg help -k nohelp
680 680 Commands:
681 681
682 682 nohelp hg nohelp
683 683
684 684 Extension Commands:
685 685
686 686 nohelp (no help text available)
687 687
688 688 Test that default list of commands omits extension commands
689 689
690 690 $ hg help
691 691 Mercurial Distributed SCM
692 692
693 693 list of commands:
694 694
695 695 add add the specified files on the next commit
696 696 addremove add all new files, delete all missing files
697 697 annotate show changeset information by line for each file
698 698 archive create an unversioned archive of a repository revision
699 699 backout reverse effect of earlier changeset
700 700 bisect subdivision search of changesets
701 701 bookmarks track a line of development with movable markers
702 702 branch set or show the current branch name
703 703 branches list repository named branches
704 704 bundle create a changegroup file
705 705 cat output the current or given revision of files
706 706 clone make a copy of an existing repository
707 707 commit commit the specified files or all outstanding changes
708 708 config show combined config settings from all hgrc files
709 709 copy mark files as copied for the next commit
710 710 diff diff repository (or selected files)
711 711 export dump the header and diffs for one or more changesets
712 712 forget forget the specified files on the next commit
713 713 graft copy changes from other branches onto the current branch
714 714 grep search for a pattern in specified files and revisions
715 715 heads show branch heads
716 716 help show help for a given topic or a help overview
717 717 identify identify the working copy or specified revision
718 718 import import an ordered set of patches
719 719 incoming show new changesets found in source
720 720 init create a new repository in the given directory
721 721 locate locate files matching specific patterns
722 722 log show revision history of entire repository or files
723 723 manifest output the current or given revision of the project manifest
724 724 merge merge working directory with another revision
725 725 outgoing show changesets not found in the destination
726 726 parents show the parents of the working directory or revision
727 727 paths show aliases for remote repositories
728 728 phase set or show the current phase name
729 729 pull pull changes from the specified source
730 730 push push changes to the specified destination
731 731 recover roll back an interrupted transaction
732 732 remove remove the specified files on the next commit
733 733 rename rename files; equivalent of copy + remove
734 734 resolve redo merges or set/view the merge status of files
735 735 revert restore files to their checkout state
736 736 root print the root (top) of the current working directory
737 737 serve start stand-alone webserver
738 738 status show changed files in the working directory
739 739 summary summarize working directory state
740 740 tag add one or more tags for the current or given revision
741 741 tags list repository tags
742 742 unbundle apply one or more changegroup files
743 743 update update working directory (or switch revisions)
744 744 verify verify the integrity of the repository
745 745 version output version and copyright information
746 746
747 747 enabled extensions:
748 748
749 749 helpext (no help text available)
750 750
751 751 additional help topics:
752 752
753 753 config Configuration Files
754 754 dates Date Formats
755 755 diffs Diff Formats
756 756 environment Environment Variables
757 757 extensions Using Additional Features
758 758 filesets Specifying File Sets
759 759 glossary Glossary
760 760 hgignore Syntax for Mercurial Ignore Files
761 761 hgweb Configuring hgweb
762 762 merge-tools Merge Tools
763 763 multirevs Specifying Multiple Revisions
764 764 patterns File Name Patterns
765 765 phases Working with Phases
766 766 revisions Specifying Single Revisions
767 767 revsets Specifying Revision Sets
768 768 subrepos Subrepositories
769 769 templating Template Usage
770 770 urls URL Paths
771 771
772 772 use "hg -v help" to show builtin aliases and global options
773 773
774 774
775 775
776 776 Test list of commands with command with no help text
777 777
778 778 $ hg help helpext
779 779 helpext extension - no help text available
780 780
781 781 list of commands:
782 782
783 783 nohelp (no help text available)
784 784
785 785 use "hg -v help helpext" to show builtin aliases and global options
786 786
787 787 Test a help topic
788 788
789 789 $ hg help revs
790 790 Specifying Single Revisions
791 791 """""""""""""""""""""""""""
792 792
793 793 Mercurial supports several ways to specify individual revisions.
794 794
795 795 A plain integer is treated as a revision number. Negative integers are
796 796 treated as sequential offsets from the tip, with -1 denoting the tip, -2
797 797 denoting the revision prior to the tip, and so forth.
798 798
799 799 A 40-digit hexadecimal string is treated as a unique revision identifier.
800 800
801 801 A hexadecimal string less than 40 characters long is treated as a unique
802 802 revision identifier and is referred to as a short-form identifier. A
803 803 short-form identifier is only valid if it is the prefix of exactly one
804 804 full-length identifier.
805 805
806 806 Any other string is treated as a bookmark, tag, or branch name. A bookmark
807 807 is a movable pointer to a revision. A tag is a permanent name associated
808 808 with a revision. A branch name denotes the tipmost open branch head of
809 809 that branch - or if they are all closed, the tipmost closed head of the
810 810 branch. Bookmark, tag, and branch names must not contain the ":"
811 811 character.
812 812
813 813 The reserved name "tip" always identifies the most recent revision.
814 814
815 815 The reserved name "null" indicates the null revision. This is the revision
816 816 of an empty repository, and the parent of revision 0.
817 817
818 818 The reserved name "." indicates the working directory parent. If no
819 819 working directory is checked out, it is equivalent to null. If an
820 820 uncommitted merge is in progress, "." is the revision of the first parent.
821 821
822 822 Test templating help
823 823
824 824 $ hg help templating | egrep '(desc|diffstat|firstline|nonempty) '
825 825 desc String. The text of the changeset description.
826 826 diffstat String. Statistics of changes with the following format:
827 827 firstline Any text. Returns the first line of text.
828 828 nonempty Any text. Returns '(none)' if the string is empty.
829 829
830 830 Test help hooks
831 831
832 832 $ cat > helphook1.py <<EOF
833 833 > from mercurial import help
834 834 >
835 835 > def rewrite(topic, doc):
836 836 > return doc + '\nhelphook1\n'
837 837 >
838 838 > def extsetup(ui):
839 839 > help.addtopichook('revsets', rewrite)
840 840 > EOF
841 841 $ cat > helphook2.py <<EOF
842 842 > from mercurial import help
843 843 >
844 844 > def rewrite(topic, doc):
845 845 > return doc + '\nhelphook2\n'
846 846 >
847 847 > def extsetup(ui):
848 848 > help.addtopichook('revsets', rewrite)
849 849 > EOF
850 850 $ echo '[extensions]' >> $HGRCPATH
851 851 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
852 852 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
853 853 $ hg help revsets | grep helphook
854 854 helphook1
855 855 helphook2
856 856
857 857 Test keyword search help
858 858
859 859 $ cat > prefixedname.py <<EOF
860 860 > '''matched against word "clone"
861 861 > '''
862 862 > EOF
863 863 $ echo '[extensions]' >> $HGRCPATH
864 864 $ echo "dot.dot.prefixedname = `pwd`/prefixedname.py" >> $HGRCPATH
865 865 $ hg help -k clone
866 866 Topics:
867 867
868 868 config Configuration Files
869 869 extensions Using Additional Features
870 870 glossary Glossary
871 871 phases Working with Phases
872 872 subrepos Subrepositories
873 873 urls URL Paths
874 874
875 875 Commands:
876 876
877 877 bookmarks track a line of development with movable markers
878 878 clone make a copy of an existing repository
879 879 paths show aliases for remote repositories
880 880 update update working directory (or switch revisions)
881 881
882 882 Extensions:
883 883
884 884 prefixedname matched against word "clone"
885 885 relink recreates hardlinks between repository clones
886 886
887 887 Extension Commands:
888 888
889 889 qclone clone main and patch repository at same time
890 890
891 891 Test omit indicating for help
892 892
893 893 $ cat > addverboseitems.py <<EOF
894 894 > '''extension to test omit indicating.
895 895 >
896 896 > This paragraph is never omitted (for extension)
897 897 >
898 898 > .. container:: verbose
899 899 >
900 900 > This paragraph is omitted,
901 901 > if :hg:\`help\` is invoked witout \`\`-v\`\` (for extension)
902 902 >
903 903 > This paragraph is never omitted, too (for extension)
904 904 > '''
905 905 >
906 906 > from mercurial import help, commands
907 907 > testtopic = """This paragraph is never omitted (for topic).
908 908 >
909 909 > .. container:: verbose
910 910 >
911 911 > This paragraph is omitted,
912 912 > if :hg:\`help\` is invoked witout \`\`-v\`\` (for topic)
913 913 >
914 914 > This paragraph is never omitted, too (for topic)
915 915 > """
916 916 > def extsetup(ui):
917 917 > help.helptable.append((["topic-containing-verbose"],
918 918 > "This is the topic to test omit indicating.",
919 919 > lambda : testtopic))
920 920 > EOF
921 921 $ echo '[extensions]' >> $HGRCPATH
922 922 $ echo "addverboseitems = `pwd`/addverboseitems.py" >> $HGRCPATH
923 923 $ hg help addverboseitems
924 924 addverboseitems extension - extension to test omit indicating.
925 925
926 926 This paragraph is never omitted (for extension)
927 927
928 928 This paragraph is never omitted, too (for extension)
929 929
930 930 use "hg help -v addverboseitems" to show more complete help
931 931
932 932 no commands defined
933 933 $ hg help -v addverboseitems
934 934 addverboseitems extension - extension to test omit indicating.
935 935
936 936 This paragraph is never omitted (for extension)
937 937
938 938 This paragraph is omitted, if "hg help" is invoked witout "-v" (for extension)
939 939
940 940 This paragraph is never omitted, too (for extension)
941 941
942 942 no commands defined
943 943 $ hg help topic-containing-verbose
944 944 This is the topic to test omit indicating.
945 945 """"""""""""""""""""""""""""""""""""""""""
946 946
947 947 This paragraph is never omitted (for topic).
948 948
949 949 This paragraph is never omitted, too (for topic)
950 950
951 951 use "hg help -v topic-containing-verbose" to show more complete help
952 952 $ hg help -v topic-containing-verbose
953 953 This is the topic to test omit indicating.
954 954 """"""""""""""""""""""""""""""""""""""""""
955 955
956 956 This paragraph is never omitted (for topic).
957 957
958 958 This paragraph is omitted, if "hg help" is invoked witout "-v" (for topic)
959 959
960 960 This paragraph is never omitted, too (for topic)
961 961
962 962 Test usage of section marks in help documents
963 963
964 964 $ cd "$TESTDIR"/../doc
965 965 $ python check-seclevel.py
966 966 $ cd $TESTTMP
967 967
968 968 #if serve
969 969
970 970 Test the help pages in hgweb.
971 971
972 972 Dish up an empty repo; serve it cold.
973 973
974 974 $ hg init "$TESTTMP/test"
975 975 $ hg serve -R "$TESTTMP/test" -n test -p $HGPORT -d --pid-file=hg.pid
976 976 $ cat hg.pid >> $DAEMON_PIDS
977 977
978 978 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT "help"
979 979 200 Script output follows
980 980
981 981 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
982 982 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
983 983 <head>
984 984 <link rel="icon" href="/static/hgicon.png" type="image/png" />
985 985 <meta name="robots" content="index, nofollow" />
986 986 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
987 987 <script type="text/javascript" src="/static/mercurial.js"></script>
988 988
989 989 <title>Help: Index</title>
990 990 </head>
991 991 <body>
992 992
993 993 <div class="container">
994 994 <div class="menu">
995 995 <div class="logo">
996 996 <a href="http://mercurial.selenic.com/">
997 997 <img src="/static/hglogo.png" alt="mercurial" /></a>
998 998 </div>
999 999 <ul>
1000 1000 <li><a href="/shortlog">log</a></li>
1001 1001 <li><a href="/graph">graph</a></li>
1002 1002 <li><a href="/tags">tags</a></li>
1003 1003 <li><a href="/bookmarks">bookmarks</a></li>
1004 1004 <li><a href="/branches">branches</a></li>
1005 1005 </ul>
1006 1006 <ul>
1007 1007 <li class="active">help</li>
1008 1008 </ul>
1009 1009 </div>
1010 1010
1011 1011 <div class="main">
1012 1012 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
1013 1013 <form class="search" action="/log">
1014 1014
1015 1015 <p><input name="rev" id="search1" type="text" size="30" /></p>
1016 1016 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
1017 1017 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
1018 1018 </form>
1019 1019 <table class="bigtable">
1020 1020 <tr><td colspan="2"><h2><a name="main" href="#topics">Topics</a></h2></td></tr>
1021 1021
1022 1022 <tr><td>
1023 1023 <a href="/help/config">
1024 1024 config
1025 1025 </a>
1026 1026 </td><td>
1027 1027 Configuration Files
1028 1028 </td></tr>
1029 1029 <tr><td>
1030 1030 <a href="/help/dates">
1031 1031 dates
1032 1032 </a>
1033 1033 </td><td>
1034 1034 Date Formats
1035 1035 </td></tr>
1036 1036 <tr><td>
1037 1037 <a href="/help/diffs">
1038 1038 diffs
1039 1039 </a>
1040 1040 </td><td>
1041 1041 Diff Formats
1042 1042 </td></tr>
1043 1043 <tr><td>
1044 1044 <a href="/help/environment">
1045 1045 environment
1046 1046 </a>
1047 1047 </td><td>
1048 1048 Environment Variables
1049 1049 </td></tr>
1050 1050 <tr><td>
1051 1051 <a href="/help/extensions">
1052 1052 extensions
1053 1053 </a>
1054 1054 </td><td>
1055 1055 Using Additional Features
1056 1056 </td></tr>
1057 1057 <tr><td>
1058 1058 <a href="/help/filesets">
1059 1059 filesets
1060 1060 </a>
1061 1061 </td><td>
1062 1062 Specifying File Sets
1063 1063 </td></tr>
1064 1064 <tr><td>
1065 1065 <a href="/help/glossary">
1066 1066 glossary
1067 1067 </a>
1068 1068 </td><td>
1069 1069 Glossary
1070 1070 </td></tr>
1071 1071 <tr><td>
1072 1072 <a href="/help/hgignore">
1073 1073 hgignore
1074 1074 </a>
1075 1075 </td><td>
1076 1076 Syntax for Mercurial Ignore Files
1077 1077 </td></tr>
1078 1078 <tr><td>
1079 1079 <a href="/help/hgweb">
1080 1080 hgweb
1081 1081 </a>
1082 1082 </td><td>
1083 1083 Configuring hgweb
1084 1084 </td></tr>
1085 1085 <tr><td>
1086 1086 <a href="/help/merge-tools">
1087 1087 merge-tools
1088 1088 </a>
1089 1089 </td><td>
1090 1090 Merge Tools
1091 1091 </td></tr>
1092 1092 <tr><td>
1093 1093 <a href="/help/multirevs">
1094 1094 multirevs
1095 1095 </a>
1096 1096 </td><td>
1097 1097 Specifying Multiple Revisions
1098 1098 </td></tr>
1099 1099 <tr><td>
1100 1100 <a href="/help/patterns">
1101 1101 patterns
1102 1102 </a>
1103 1103 </td><td>
1104 1104 File Name Patterns
1105 1105 </td></tr>
1106 1106 <tr><td>
1107 1107 <a href="/help/phases">
1108 1108 phases
1109 1109 </a>
1110 1110 </td><td>
1111 1111 Working with Phases
1112 1112 </td></tr>
1113 1113 <tr><td>
1114 1114 <a href="/help/revisions">
1115 1115 revisions
1116 1116 </a>
1117 1117 </td><td>
1118 1118 Specifying Single Revisions
1119 1119 </td></tr>
1120 1120 <tr><td>
1121 1121 <a href="/help/revsets">
1122 1122 revsets
1123 1123 </a>
1124 1124 </td><td>
1125 1125 Specifying Revision Sets
1126 1126 </td></tr>
1127 1127 <tr><td>
1128 1128 <a href="/help/subrepos">
1129 1129 subrepos
1130 1130 </a>
1131 1131 </td><td>
1132 1132 Subrepositories
1133 1133 </td></tr>
1134 1134 <tr><td>
1135 1135 <a href="/help/templating">
1136 1136 templating
1137 1137 </a>
1138 1138 </td><td>
1139 1139 Template Usage
1140 1140 </td></tr>
1141 1141 <tr><td>
1142 1142 <a href="/help/urls">
1143 1143 urls
1144 1144 </a>
1145 1145 </td><td>
1146 1146 URL Paths
1147 1147 </td></tr>
1148 1148 <tr><td>
1149 1149 <a href="/help/topic-containing-verbose">
1150 1150 topic-containing-verbose
1151 1151 </a>
1152 1152 </td><td>
1153 1153 This is the topic to test omit indicating.
1154 1154 </td></tr>
1155 1155
1156 1156 <tr><td colspan="2"><h2><a name="main" href="#main">Main Commands</a></h2></td></tr>
1157 1157
1158 1158 <tr><td>
1159 1159 <a href="/help/add">
1160 1160 add
1161 1161 </a>
1162 1162 </td><td>
1163 1163 add the specified files on the next commit
1164 1164 </td></tr>
1165 1165 <tr><td>
1166 1166 <a href="/help/annotate">
1167 1167 annotate
1168 1168 </a>
1169 1169 </td><td>
1170 1170 show changeset information by line for each file
1171 1171 </td></tr>
1172 1172 <tr><td>
1173 1173 <a href="/help/clone">
1174 1174 clone
1175 1175 </a>
1176 1176 </td><td>
1177 1177 make a copy of an existing repository
1178 1178 </td></tr>
1179 1179 <tr><td>
1180 1180 <a href="/help/commit">
1181 1181 commit
1182 1182 </a>
1183 1183 </td><td>
1184 1184 commit the specified files or all outstanding changes
1185 1185 </td></tr>
1186 1186 <tr><td>
1187 1187 <a href="/help/diff">
1188 1188 diff
1189 1189 </a>
1190 1190 </td><td>
1191 1191 diff repository (or selected files)
1192 1192 </td></tr>
1193 1193 <tr><td>
1194 1194 <a href="/help/export">
1195 1195 export
1196 1196 </a>
1197 1197 </td><td>
1198 1198 dump the header and diffs for one or more changesets
1199 1199 </td></tr>
1200 1200 <tr><td>
1201 1201 <a href="/help/forget">
1202 1202 forget
1203 1203 </a>
1204 1204 </td><td>
1205 1205 forget the specified files on the next commit
1206 1206 </td></tr>
1207 1207 <tr><td>
1208 1208 <a href="/help/init">
1209 1209 init
1210 1210 </a>
1211 1211 </td><td>
1212 1212 create a new repository in the given directory
1213 1213 </td></tr>
1214 1214 <tr><td>
1215 1215 <a href="/help/log">
1216 1216 log
1217 1217 </a>
1218 1218 </td><td>
1219 1219 show revision history of entire repository or files
1220 1220 </td></tr>
1221 1221 <tr><td>
1222 1222 <a href="/help/merge">
1223 1223 merge
1224 1224 </a>
1225 1225 </td><td>
1226 1226 merge working directory with another revision
1227 1227 </td></tr>
1228 1228 <tr><td>
1229 1229 <a href="/help/pull">
1230 1230 pull
1231 1231 </a>
1232 1232 </td><td>
1233 1233 pull changes from the specified source
1234 1234 </td></tr>
1235 1235 <tr><td>
1236 1236 <a href="/help/push">
1237 1237 push
1238 1238 </a>
1239 1239 </td><td>
1240 1240 push changes to the specified destination
1241 1241 </td></tr>
1242 1242 <tr><td>
1243 1243 <a href="/help/remove">
1244 1244 remove
1245 1245 </a>
1246 1246 </td><td>
1247 1247 remove the specified files on the next commit
1248 1248 </td></tr>
1249 1249 <tr><td>
1250 1250 <a href="/help/serve">
1251 1251 serve
1252 1252 </a>
1253 1253 </td><td>
1254 1254 start stand-alone webserver
1255 1255 </td></tr>
1256 1256 <tr><td>
1257 1257 <a href="/help/status">
1258 1258 status
1259 1259 </a>
1260 1260 </td><td>
1261 1261 show changed files in the working directory
1262 1262 </td></tr>
1263 1263 <tr><td>
1264 1264 <a href="/help/summary">
1265 1265 summary
1266 1266 </a>
1267 1267 </td><td>
1268 1268 summarize working directory state
1269 1269 </td></tr>
1270 1270 <tr><td>
1271 1271 <a href="/help/update">
1272 1272 update
1273 1273 </a>
1274 1274 </td><td>
1275 1275 update working directory (or switch revisions)
1276 1276 </td></tr>
1277 1277
1278 1278 <tr><td colspan="2"><h2><a name="other" href="#other">Other Commands</a></h2></td></tr>
1279 1279
1280 1280 <tr><td>
1281 1281 <a href="/help/addremove">
1282 1282 addremove
1283 1283 </a>
1284 1284 </td><td>
1285 1285 add all new files, delete all missing files
1286 1286 </td></tr>
1287 1287 <tr><td>
1288 1288 <a href="/help/archive">
1289 1289 archive
1290 1290 </a>
1291 1291 </td><td>
1292 1292 create an unversioned archive of a repository revision
1293 1293 </td></tr>
1294 1294 <tr><td>
1295 1295 <a href="/help/backout">
1296 1296 backout
1297 1297 </a>
1298 1298 </td><td>
1299 1299 reverse effect of earlier changeset
1300 1300 </td></tr>
1301 1301 <tr><td>
1302 1302 <a href="/help/bisect">
1303 1303 bisect
1304 1304 </a>
1305 1305 </td><td>
1306 1306 subdivision search of changesets
1307 1307 </td></tr>
1308 1308 <tr><td>
1309 1309 <a href="/help/bookmarks">
1310 1310 bookmarks
1311 1311 </a>
1312 1312 </td><td>
1313 1313 track a line of development with movable markers
1314 1314 </td></tr>
1315 1315 <tr><td>
1316 1316 <a href="/help/branch">
1317 1317 branch
1318 1318 </a>
1319 1319 </td><td>
1320 1320 set or show the current branch name
1321 1321 </td></tr>
1322 1322 <tr><td>
1323 1323 <a href="/help/branches">
1324 1324 branches
1325 1325 </a>
1326 1326 </td><td>
1327 1327 list repository named branches
1328 1328 </td></tr>
1329 1329 <tr><td>
1330 1330 <a href="/help/bundle">
1331 1331 bundle
1332 1332 </a>
1333 1333 </td><td>
1334 1334 create a changegroup file
1335 1335 </td></tr>
1336 1336 <tr><td>
1337 1337 <a href="/help/cat">
1338 1338 cat
1339 1339 </a>
1340 1340 </td><td>
1341 1341 output the current or given revision of files
1342 1342 </td></tr>
1343 1343 <tr><td>
1344 1344 <a href="/help/config">
1345 1345 config
1346 1346 </a>
1347 1347 </td><td>
1348 1348 show combined config settings from all hgrc files
1349 1349 </td></tr>
1350 1350 <tr><td>
1351 1351 <a href="/help/copy">
1352 1352 copy
1353 1353 </a>
1354 1354 </td><td>
1355 1355 mark files as copied for the next commit
1356 1356 </td></tr>
1357 1357 <tr><td>
1358 1358 <a href="/help/graft">
1359 1359 graft
1360 1360 </a>
1361 1361 </td><td>
1362 1362 copy changes from other branches onto the current branch
1363 1363 </td></tr>
1364 1364 <tr><td>
1365 1365 <a href="/help/grep">
1366 1366 grep
1367 1367 </a>
1368 1368 </td><td>
1369 1369 search for a pattern in specified files and revisions
1370 1370 </td></tr>
1371 1371 <tr><td>
1372 1372 <a href="/help/heads">
1373 1373 heads
1374 1374 </a>
1375 1375 </td><td>
1376 1376 show branch heads
1377 1377 </td></tr>
1378 1378 <tr><td>
1379 1379 <a href="/help/help">
1380 1380 help
1381 1381 </a>
1382 1382 </td><td>
1383 1383 show help for a given topic or a help overview
1384 1384 </td></tr>
1385 1385 <tr><td>
1386 1386 <a href="/help/identify">
1387 1387 identify
1388 1388 </a>
1389 1389 </td><td>
1390 1390 identify the working copy or specified revision
1391 1391 </td></tr>
1392 1392 <tr><td>
1393 1393 <a href="/help/import">
1394 1394 import
1395 1395 </a>
1396 1396 </td><td>
1397 1397 import an ordered set of patches
1398 1398 </td></tr>
1399 1399 <tr><td>
1400 1400 <a href="/help/incoming">
1401 1401 incoming
1402 1402 </a>
1403 1403 </td><td>
1404 1404 show new changesets found in source
1405 1405 </td></tr>
1406 1406 <tr><td>
1407 1407 <a href="/help/locate">
1408 1408 locate
1409 1409 </a>
1410 1410 </td><td>
1411 1411 locate files matching specific patterns
1412 1412 </td></tr>
1413 1413 <tr><td>
1414 1414 <a href="/help/manifest">
1415 1415 manifest
1416 1416 </a>
1417 1417 </td><td>
1418 1418 output the current or given revision of the project manifest
1419 1419 </td></tr>
1420 1420 <tr><td>
1421 1421 <a href="/help/nohelp">
1422 1422 nohelp
1423 1423 </a>
1424 1424 </td><td>
1425 1425 (no help text available)
1426 1426 </td></tr>
1427 1427 <tr><td>
1428 1428 <a href="/help/outgoing">
1429 1429 outgoing
1430 1430 </a>
1431 1431 </td><td>
1432 1432 show changesets not found in the destination
1433 1433 </td></tr>
1434 1434 <tr><td>
1435 1435 <a href="/help/parents">
1436 1436 parents
1437 1437 </a>
1438 1438 </td><td>
1439 1439 show the parents of the working directory or revision
1440 1440 </td></tr>
1441 1441 <tr><td>
1442 1442 <a href="/help/paths">
1443 1443 paths
1444 1444 </a>
1445 1445 </td><td>
1446 1446 show aliases for remote repositories
1447 1447 </td></tr>
1448 1448 <tr><td>
1449 1449 <a href="/help/phase">
1450 1450 phase
1451 1451 </a>
1452 1452 </td><td>
1453 1453 set or show the current phase name
1454 1454 </td></tr>
1455 1455 <tr><td>
1456 1456 <a href="/help/recover">
1457 1457 recover
1458 1458 </a>
1459 1459 </td><td>
1460 1460 roll back an interrupted transaction
1461 1461 </td></tr>
1462 1462 <tr><td>
1463 1463 <a href="/help/rename">
1464 1464 rename
1465 1465 </a>
1466 1466 </td><td>
1467 1467 rename files; equivalent of copy + remove
1468 1468 </td></tr>
1469 1469 <tr><td>
1470 1470 <a href="/help/resolve">
1471 1471 resolve
1472 1472 </a>
1473 1473 </td><td>
1474 1474 redo merges or set/view the merge status of files
1475 1475 </td></tr>
1476 1476 <tr><td>
1477 1477 <a href="/help/revert">
1478 1478 revert
1479 1479 </a>
1480 1480 </td><td>
1481 1481 restore files to their checkout state
1482 1482 </td></tr>
1483 1483 <tr><td>
1484 1484 <a href="/help/root">
1485 1485 root
1486 1486 </a>
1487 1487 </td><td>
1488 1488 print the root (top) of the current working directory
1489 1489 </td></tr>
1490 1490 <tr><td>
1491 1491 <a href="/help/tag">
1492 1492 tag
1493 1493 </a>
1494 1494 </td><td>
1495 1495 add one or more tags for the current or given revision
1496 1496 </td></tr>
1497 1497 <tr><td>
1498 1498 <a href="/help/tags">
1499 1499 tags
1500 1500 </a>
1501 1501 </td><td>
1502 1502 list repository tags
1503 1503 </td></tr>
1504 1504 <tr><td>
1505 1505 <a href="/help/unbundle">
1506 1506 unbundle
1507 1507 </a>
1508 1508 </td><td>
1509 1509 apply one or more changegroup files
1510 1510 </td></tr>
1511 1511 <tr><td>
1512 1512 <a href="/help/verify">
1513 1513 verify
1514 1514 </a>
1515 1515 </td><td>
1516 1516 verify the integrity of the repository
1517 1517 </td></tr>
1518 1518 <tr><td>
1519 1519 <a href="/help/version">
1520 1520 version
1521 1521 </a>
1522 1522 </td><td>
1523 1523 output version and copyright information
1524 1524 </td></tr>
1525 1525 </table>
1526 1526 </div>
1527 1527 </div>
1528 1528
1529 1529 <script type="text/javascript">process_dates()</script>
1530 1530
1531 1531
1532 1532 </body>
1533 1533 </html>
1534 1534
1535 1535
1536 1536 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT "help/add"
1537 1537 200 Script output follows
1538 1538
1539 1539 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
1540 1540 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
1541 1541 <head>
1542 1542 <link rel="icon" href="/static/hgicon.png" type="image/png" />
1543 1543 <meta name="robots" content="index, nofollow" />
1544 1544 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
1545 1545 <script type="text/javascript" src="/static/mercurial.js"></script>
1546 1546
1547 1547 <title>Help: add</title>
1548 1548 </head>
1549 1549 <body>
1550 1550
1551 1551 <div class="container">
1552 1552 <div class="menu">
1553 1553 <div class="logo">
1554 1554 <a href="http://mercurial.selenic.com/">
1555 1555 <img src="/static/hglogo.png" alt="mercurial" /></a>
1556 1556 </div>
1557 1557 <ul>
1558 1558 <li><a href="/shortlog">log</a></li>
1559 1559 <li><a href="/graph">graph</a></li>
1560 1560 <li><a href="/tags">tags</a></li>
1561 1561 <li><a href="/bookmarks">bookmarks</a></li>
1562 1562 <li><a href="/branches">branches</a></li>
1563 1563 </ul>
1564 1564 <ul>
1565 1565 <li class="active"><a href="/help">help</a></li>
1566 1566 </ul>
1567 1567 </div>
1568 1568
1569 1569 <div class="main">
1570 1570 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
1571 1571 <h3>Help: add</h3>
1572 1572
1573 1573 <form class="search" action="/log">
1574 1574
1575 1575 <p><input name="rev" id="search1" type="text" size="30" /></p>
1576 1576 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
1577 1577 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
1578 1578 </form>
1579 1579 <div id="doc">
1580 1580 <p>
1581 1581 hg add [OPTION]... [FILE]...
1582 1582 </p>
1583 1583 <p>
1584 1584 add the specified files on the next commit
1585 1585 </p>
1586 1586 <p>
1587 1587 Schedule files to be version controlled and added to the
1588 1588 repository.
1589 1589 </p>
1590 1590 <p>
1591 1591 The files will be added to the repository at the next commit. To
1592 1592 undo an add before that, see &quot;hg forget&quot;.
1593 1593 </p>
1594 1594 <p>
1595 1595 If no names are given, add all files to the repository.
1596 1596 </p>
1597 1597 <p>
1598 1598 An example showing how new (unknown) files are added
1599 1599 automatically by &quot;hg add&quot;:
1600 1600 </p>
1601 1601 <pre>
1602 1602 \$ ls (re)
1603 1603 foo.c
1604 1604 \$ hg status (re)
1605 1605 ? foo.c
1606 1606 \$ hg add (re)
1607 1607 adding foo.c
1608 1608 \$ hg status (re)
1609 1609 A foo.c
1610 1610 </pre>
1611 1611 <p>
1612 1612 Returns 0 if all files are successfully added.
1613 1613 </p>
1614 1614 <p>
1615 1615 options:
1616 1616 </p>
1617 1617 <table>
1618 1618 <tr><td>-I</td>
1619 1619 <td>--include PATTERN [+]</td>
1620 1620 <td>include names matching the given patterns</td></tr>
1621 1621 <tr><td>-X</td>
1622 1622 <td>--exclude PATTERN [+]</td>
1623 1623 <td>exclude names matching the given patterns</td></tr>
1624 1624 <tr><td>-S</td>
1625 1625 <td>--subrepos</td>
1626 1626 <td>recurse into subrepositories</td></tr>
1627 1627 <tr><td>-n</td>
1628 1628 <td>--dry-run</td>
1629 1629 <td>do not perform actions, just print output</td></tr>
1630 1630 </table>
1631 1631 <p>
1632 1632 [+] marked option can be specified multiple times
1633 1633 </p>
1634 1634 <p>
1635 1635 global options:
1636 1636 </p>
1637 1637 <table>
1638 1638 <tr><td>-R</td>
1639 1639 <td>--repository REPO</td>
1640 1640 <td>repository root directory or name of overlay bundle file</td></tr>
1641 1641 <tr><td></td>
1642 1642 <td>--cwd DIR</td>
1643 1643 <td>change working directory</td></tr>
1644 1644 <tr><td>-y</td>
1645 1645 <td>--noninteractive</td>
1646 1646 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
1647 1647 <tr><td>-q</td>
1648 1648 <td>--quiet</td>
1649 1649 <td>suppress output</td></tr>
1650 1650 <tr><td>-v</td>
1651 1651 <td>--verbose</td>
1652 1652 <td>enable additional output</td></tr>
1653 1653 <tr><td></td>
1654 1654 <td>--config CONFIG [+]</td>
1655 1655 <td>set/override config option (use 'section.name=value')</td></tr>
1656 1656 <tr><td></td>
1657 1657 <td>--debug</td>
1658 1658 <td>enable debugging output</td></tr>
1659 1659 <tr><td></td>
1660 1660 <td>--debugger</td>
1661 1661 <td>start debugger</td></tr>
1662 1662 <tr><td></td>
1663 1663 <td>--encoding ENCODE</td>
1664 1664 <td>set the charset encoding (default: ascii)</td></tr>
1665 1665 <tr><td></td>
1666 1666 <td>--encodingmode MODE</td>
1667 1667 <td>set the charset encoding mode (default: strict)</td></tr>
1668 1668 <tr><td></td>
1669 1669 <td>--traceback</td>
1670 1670 <td>always print a traceback on exception</td></tr>
1671 1671 <tr><td></td>
1672 1672 <td>--time</td>
1673 1673 <td>time how long the command takes</td></tr>
1674 1674 <tr><td></td>
1675 1675 <td>--profile</td>
1676 1676 <td>print command execution profile</td></tr>
1677 1677 <tr><td></td>
1678 1678 <td>--version</td>
1679 1679 <td>output version information and exit</td></tr>
1680 1680 <tr><td>-h</td>
1681 1681 <td>--help</td>
1682 1682 <td>display help and exit</td></tr>
1683 1683 <tr><td></td>
1684 1684 <td>--hidden</td>
1685 1685 <td>consider hidden changesets</td></tr>
1686 1686 </table>
1687 1687 <p>
1688 1688 [+] marked option can be specified multiple times
1689 1689 </p>
1690 1690
1691 1691 </div>
1692 1692 </div>
1693 1693 </div>
1694 1694
1695 1695 <script type="text/javascript">process_dates()</script>
1696 1696
1697 1697
1698 1698 </body>
1699 1699 </html>
1700 1700
1701 1701
1702 1702 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT "help/remove"
1703 1703 200 Script output follows
1704 1704
1705 1705 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
1706 1706 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
1707 1707 <head>
1708 1708 <link rel="icon" href="/static/hgicon.png" type="image/png" />
1709 1709 <meta name="robots" content="index, nofollow" />
1710 1710 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
1711 1711 <script type="text/javascript" src="/static/mercurial.js"></script>
1712 1712
1713 1713 <title>Help: remove</title>
1714 1714 </head>
1715 1715 <body>
1716 1716
1717 1717 <div class="container">
1718 1718 <div class="menu">
1719 1719 <div class="logo">
1720 1720 <a href="http://mercurial.selenic.com/">
1721 1721 <img src="/static/hglogo.png" alt="mercurial" /></a>
1722 1722 </div>
1723 1723 <ul>
1724 1724 <li><a href="/shortlog">log</a></li>
1725 1725 <li><a href="/graph">graph</a></li>
1726 1726 <li><a href="/tags">tags</a></li>
1727 1727 <li><a href="/bookmarks">bookmarks</a></li>
1728 1728 <li><a href="/branches">branches</a></li>
1729 1729 </ul>
1730 1730 <ul>
1731 1731 <li class="active"><a href="/help">help</a></li>
1732 1732 </ul>
1733 1733 </div>
1734 1734
1735 1735 <div class="main">
1736 1736 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
1737 1737 <h3>Help: remove</h3>
1738 1738
1739 1739 <form class="search" action="/log">
1740 1740
1741 1741 <p><input name="rev" id="search1" type="text" size="30" /></p>
1742 1742 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
1743 1743 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
1744 1744 </form>
1745 1745 <div id="doc">
1746 1746 <p>
1747 1747 hg remove [OPTION]... FILE...
1748 1748 </p>
1749 1749 <p>
1750 1750 aliases: rm
1751 1751 </p>
1752 1752 <p>
1753 1753 remove the specified files on the next commit
1754 1754 </p>
1755 1755 <p>
1756 1756 Schedule the indicated files for removal from the current branch.
1757 1757 </p>
1758 1758 <p>
1759 1759 This command schedules the files to be removed at the next commit.
1760 1760 To undo a remove before that, see &quot;hg revert&quot;. To undo added
1761 1761 files, see &quot;hg forget&quot;.
1762 1762 </p>
1763 1763 <p>
1764 1764 -A/--after can be used to remove only files that have already
1765 1765 been deleted, -f/--force can be used to force deletion, and -Af
1766 1766 can be used to remove files from the next revision without
1767 1767 deleting them from the working directory.
1768 1768 </p>
1769 1769 <p>
1770 1770 The following table details the behavior of remove for different
1771 1771 file states (columns) and option combinations (rows). The file
1772 1772 states are Added [A], Clean [C], Modified [M] and Missing [!]
1773 1773 (as reported by &quot;hg status&quot;). The actions are Warn, Remove
1774 1774 (from branch) and Delete (from disk):
1775 1775 </p>
1776 1776 <table>
1777 1777 <tr><td>opt/state</td>
1778 1778 <td>A</td>
1779 1779 <td>C</td>
1780 1780 <td>M</td>
1781 1781 <td>!</td></tr>
1782 1782 <tr><td>none</td>
1783 1783 <td>W</td>
1784 1784 <td>RD</td>
1785 1785 <td>W</td>
1786 1786 <td>R</td></tr>
1787 1787 <tr><td>-f</td>
1788 1788 <td>R</td>
1789 1789 <td>RD</td>
1790 1790 <td>RD</td>
1791 1791 <td>R</td></tr>
1792 1792 <tr><td>-A</td>
1793 1793 <td>W</td>
1794 1794 <td>W</td>
1795 1795 <td>W</td>
1796 1796 <td>R</td></tr>
1797 1797 <tr><td>-Af</td>
1798 1798 <td>R</td>
1799 1799 <td>R</td>
1800 1800 <td>R</td>
1801 1801 <td>R</td></tr>
1802 1802 </table>
1803 1803 <p>
1804 1804 Note that remove never deletes files in Added [A] state from the
1805 1805 working directory, not even if option --force is specified.
1806 1806 </p>
1807 1807 <p>
1808 1808 Returns 0 on success, 1 if any warnings encountered.
1809 1809 </p>
1810 1810 <p>
1811 1811 options:
1812 1812 </p>
1813 1813 <table>
1814 1814 <tr><td>-A</td>
1815 1815 <td>--after</td>
1816 1816 <td>record delete for missing files</td></tr>
1817 1817 <tr><td>-f</td>
1818 1818 <td>--force</td>
1819 1819 <td>remove (and delete) file even if added or modified</td></tr>
1820 1820 <tr><td>-I</td>
1821 1821 <td>--include PATTERN [+]</td>
1822 1822 <td>include names matching the given patterns</td></tr>
1823 1823 <tr><td>-X</td>
1824 1824 <td>--exclude PATTERN [+]</td>
1825 1825 <td>exclude names matching the given patterns</td></tr>
1826 1826 </table>
1827 1827 <p>
1828 1828 [+] marked option can be specified multiple times
1829 1829 </p>
1830 1830 <p>
1831 1831 global options:
1832 1832 </p>
1833 1833 <table>
1834 1834 <tr><td>-R</td>
1835 1835 <td>--repository REPO</td>
1836 1836 <td>repository root directory or name of overlay bundle file</td></tr>
1837 1837 <tr><td></td>
1838 1838 <td>--cwd DIR</td>
1839 1839 <td>change working directory</td></tr>
1840 1840 <tr><td>-y</td>
1841 1841 <td>--noninteractive</td>
1842 1842 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
1843 1843 <tr><td>-q</td>
1844 1844 <td>--quiet</td>
1845 1845 <td>suppress output</td></tr>
1846 1846 <tr><td>-v</td>
1847 1847 <td>--verbose</td>
1848 1848 <td>enable additional output</td></tr>
1849 1849 <tr><td></td>
1850 1850 <td>--config CONFIG [+]</td>
1851 1851 <td>set/override config option (use 'section.name=value')</td></tr>
1852 1852 <tr><td></td>
1853 1853 <td>--debug</td>
1854 1854 <td>enable debugging output</td></tr>
1855 1855 <tr><td></td>
1856 1856 <td>--debugger</td>
1857 1857 <td>start debugger</td></tr>
1858 1858 <tr><td></td>
1859 1859 <td>--encoding ENCODE</td>
1860 1860 <td>set the charset encoding (default: ascii)</td></tr>
1861 1861 <tr><td></td>
1862 1862 <td>--encodingmode MODE</td>
1863 1863 <td>set the charset encoding mode (default: strict)</td></tr>
1864 1864 <tr><td></td>
1865 1865 <td>--traceback</td>
1866 1866 <td>always print a traceback on exception</td></tr>
1867 1867 <tr><td></td>
1868 1868 <td>--time</td>
1869 1869 <td>time how long the command takes</td></tr>
1870 1870 <tr><td></td>
1871 1871 <td>--profile</td>
1872 1872 <td>print command execution profile</td></tr>
1873 1873 <tr><td></td>
1874 1874 <td>--version</td>
1875 1875 <td>output version information and exit</td></tr>
1876 1876 <tr><td>-h</td>
1877 1877 <td>--help</td>
1878 1878 <td>display help and exit</td></tr>
1879 1879 <tr><td></td>
1880 1880 <td>--hidden</td>
1881 1881 <td>consider hidden changesets</td></tr>
1882 1882 </table>
1883 1883 <p>
1884 1884 [+] marked option can be specified multiple times
1885 1885 </p>
1886 1886
1887 1887 </div>
1888 1888 </div>
1889 1889 </div>
1890 1890
1891 1891 <script type="text/javascript">process_dates()</script>
1892 1892
1893 1893
1894 1894 </body>
1895 1895 </html>
1896 1896
1897 1897
1898 1898 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT "help/revisions"
1899 1899 200 Script output follows
1900 1900
1901 1901 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
1902 1902 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
1903 1903 <head>
1904 1904 <link rel="icon" href="/static/hgicon.png" type="image/png" />
1905 1905 <meta name="robots" content="index, nofollow" />
1906 1906 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
1907 1907 <script type="text/javascript" src="/static/mercurial.js"></script>
1908 1908
1909 1909 <title>Help: revisions</title>
1910 1910 </head>
1911 1911 <body>
1912 1912
1913 1913 <div class="container">
1914 1914 <div class="menu">
1915 1915 <div class="logo">
1916 1916 <a href="http://mercurial.selenic.com/">
1917 1917 <img src="/static/hglogo.png" alt="mercurial" /></a>
1918 1918 </div>
1919 1919 <ul>
1920 1920 <li><a href="/shortlog">log</a></li>
1921 1921 <li><a href="/graph">graph</a></li>
1922 1922 <li><a href="/tags">tags</a></li>
1923 1923 <li><a href="/bookmarks">bookmarks</a></li>
1924 1924 <li><a href="/branches">branches</a></li>
1925 1925 </ul>
1926 1926 <ul>
1927 1927 <li class="active"><a href="/help">help</a></li>
1928 1928 </ul>
1929 1929 </div>
1930 1930
1931 1931 <div class="main">
1932 1932 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
1933 1933 <h3>Help: revisions</h3>
1934 1934
1935 1935 <form class="search" action="/log">
1936 1936
1937 1937 <p><input name="rev" id="search1" type="text" size="30" /></p>
1938 1938 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
1939 1939 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
1940 1940 </form>
1941 1941 <div id="doc">
1942 1942 <h1>Specifying Single Revisions</h1>
1943 1943 <p>
1944 1944 Mercurial supports several ways to specify individual revisions.
1945 1945 </p>
1946 1946 <p>
1947 1947 A plain integer is treated as a revision number. Negative integers are
1948 1948 treated as sequential offsets from the tip, with -1 denoting the tip,
1949 1949 -2 denoting the revision prior to the tip, and so forth.
1950 1950 </p>
1951 1951 <p>
1952 1952 A 40-digit hexadecimal string is treated as a unique revision
1953 1953 identifier.
1954 1954 </p>
1955 1955 <p>
1956 1956 A hexadecimal string less than 40 characters long is treated as a
1957 1957 unique revision identifier and is referred to as a short-form
1958 1958 identifier. A short-form identifier is only valid if it is the prefix
1959 1959 of exactly one full-length identifier.
1960 1960 </p>
1961 1961 <p>
1962 1962 Any other string is treated as a bookmark, tag, or branch name. A
1963 1963 bookmark is a movable pointer to a revision. A tag is a permanent name
1964 1964 associated with a revision. A branch name denotes the tipmost open branch head
1965 1965 of that branch - or if they are all closed, the tipmost closed head of the
1966 1966 branch. Bookmark, tag, and branch names must not contain the &quot;:&quot; character.
1967 1967 </p>
1968 1968 <p>
1969 1969 The reserved name &quot;tip&quot; always identifies the most recent revision.
1970 1970 </p>
1971 1971 <p>
1972 1972 The reserved name &quot;null&quot; indicates the null revision. This is the
1973 1973 revision of an empty repository, and the parent of revision 0.
1974 1974 </p>
1975 1975 <p>
1976 1976 The reserved name &quot;.&quot; indicates the working directory parent. If no
1977 1977 working directory is checked out, it is equivalent to null. If an
1978 1978 uncommitted merge is in progress, &quot;.&quot; is the revision of the first
1979 1979 parent.
1980 1980 </p>
1981 1981
1982 1982 </div>
1983 1983 </div>
1984 1984 </div>
1985 1985
1986 1986 <script type="text/javascript">process_dates()</script>
1987 1987
1988 1988
1989 1989 </body>
1990 1990 </html>
1991 1991
1992 1992
1993 1993 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
1994 1994
1995 1995 #endif
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
This diff has been collapsed as it changes many lines, (649 lines changed) Show them Hide them
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now